diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 30 | ||||
-rw-r--r-- | lib/AST/MicrosoftMangle.cpp | 13 | ||||
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 56 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 14 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 14 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 72 | ||||
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 76 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 44 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 40 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 18 |
15 files changed, 265 insertions, 137 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 2f21e4cbd6..c68a16bdae 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -463,13 +463,14 @@ void CXXRecordDecl::markedConstructorConstexpr(CXXConstructorDecl *CD) { } void CXXRecordDecl::addedMember(Decl *D) { - if (!D->isImplicit() && - !isa<FieldDecl>(D) && - !isa<IndirectFieldDecl>(D) && - (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class)) - data().HasOnlyCMembers = false; - - // Ignore friends and invalid declarations. + if (!D->isImplicit() &&
+ !isa<FieldDecl>(D) &&
+ !isa<IndirectFieldDecl>(D) &&
+ (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class ||
+ cast<TagDecl>(D)->getTagKind() == TTK_Interface))
+ data().HasOnlyCMembers = false;
+
+ // Ignore friends and invalid declarations.
if (D->getFriendObjectKind() || D->isInvalidDecl()) return; @@ -933,13 +934,14 @@ NotASpecialMember:; if (Shadow->getDeclName().getNameKind() == DeclarationName::CXXConversionFunctionName) data().Conversions.addDecl(Shadow, Shadow->getAccess()); -} - -bool CXXRecordDecl::isCLike() const { - if (getTagKind() == TTK_Class || !TemplateOrInstantiation.isNull()) - return false; - if (!hasDefinition()) - return true; +}
+
+bool CXXRecordDecl::isCLike() const {
+ if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
+ !TemplateOrInstantiation.isNull())
+ return false;
+ if (!hasDefinition())
+ return true;
return isPOD() && data().HasOnlyCMembers; } diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 982e3aceec..f0041b2422 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1270,12 +1270,13 @@ void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) { void MicrosoftCXXNameMangler::mangleType(const TagType *T) { switch (T->getDecl()->getTagKind()) { case TTK_Union: - Out << 'T'; - break; - case TTK_Struct: - Out << 'U'; - break; - case TTK_Class: + Out << 'T';
+ break;
+ case TTK_Struct:
+ case TTK_Interface:
+ Out << 'U';
+ break;
+ case TTK_Class:
Out << 'V'; break; case TTK_Enum: diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index d5df63f7d1..043e46e9d6 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -2260,12 +2260,28 @@ RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field, } // Use the externally-supplied field offset. - return ExternalFieldOffset; -} - -void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, - uint64_t UnpaddedOffset, - uint64_t UnpackedOffset, + return ExternalFieldOffset;
+}
+
+/// \brief Get diagnostic %select index for tag kind for
+/// field padding diagnostic message.
+/// WARNING: Indexes apply to particular diagnostics only!
+///
+/// \returns diagnostic %select index.
+static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag)
+{
+ switch (Tag) {
+ case TTK_Struct: return 0;
+ case TTK_Interface: return 1;
+ case TTK_Class: return 2;
+ default: assert("Invalid tag kind for field padding diagnostic!");
+ }
+ return -1;
+}
+
+void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset,
+ uint64_t UnpaddedOffset,
+ uint64_t UnpackedOffset,
unsigned UnpackedAlign, bool isPacked, const FieldDecl *D) { @@ -2288,20 +2304,20 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, if (PadSize % CharBitNum == 0) { PadSize = PadSize / CharBitNum; InBits = false; - } - if (D->getIdentifier()) - Diag(D->getLocation(), diag::warn_padded_struct_field) - << (D->getParent()->isStruct() ? 0 : 1) // struct|class - << Context.getTypeDeclType(D->getParent()) - << PadSize - << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not - << D->getIdentifier(); - else - Diag(D->getLocation(), diag::warn_padded_struct_anon_field) - << (D->getParent()->isStruct() ? 0 : 1) // struct|class - << Context.getTypeDeclType(D->getParent()) - << PadSize - << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not + }
+ if (D->getIdentifier())
+ Diag(D->getLocation(), diag::warn_padded_struct_field)
+ << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
+ << Context.getTypeDeclType(D->getParent())
+ << PadSize
+ << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not
+ << D->getIdentifier();
+ else
+ Diag(D->getLocation(), diag::warn_padded_struct_anon_field)
+ << getPaddingDiagFromTagKind(D->getParent()->getTagKind())
+ << Context.getTypeDeclType(D->getParent())
+ << PadSize
+ << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not
} // Warn if we packed it unnecessarily. If the alignment is 1 byte don't diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 7445152d62..c54250a479 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -357,9 +357,15 @@ bool Type::isStructureType() const { return RT->getDecl()->isStruct(); return false; } +bool Type::isInterfaceType() const { + if (const RecordType *RT = getAs<RecordType>()) + return RT->getDecl()->isInterface(); + return false; +} bool Type::isStructureOrClassType() const { if (const RecordType *RT = getAs<RecordType>()) - return RT->getDecl()->isStruct() || RT->getDecl()->isClass(); + return RT->getDecl()->isStruct() || RT->getDecl()->isClass() || + RT->getDecl()->isInterface(); return false; } bool Type::isVoidPointerType() const { @@ -1317,6 +1323,7 @@ TypeWithKeyword::getKeywordForTypeSpec(unsigned TypeSpec) { case TST_typename: return ETK_Typename; case TST_class: return ETK_Class; case TST_struct: return ETK_Struct; + case TST_interface: return ETK_Interface; case TST_union: return ETK_Union; case TST_enum: return ETK_Enum; } @@ -1327,6 +1334,7 @@ TypeWithKeyword::getTagTypeKindForTypeSpec(unsigned TypeSpec) { switch(TypeSpec) { case TST_class: return TTK_Class; case TST_struct: return TTK_Struct; + case TST_interface: return TTK_Interface; case TST_union: return TTK_Union; case TST_enum: return TTK_Enum; } @@ -1339,6 +1347,7 @@ TypeWithKeyword::getKeywordForTagTypeKind(TagTypeKind Kind) { switch (Kind) { case TTK_Class: return ETK_Class; case TTK_Struct: return ETK_Struct; + case TTK_Interface: return ETK_Interface; case TTK_Union: return ETK_Union; case TTK_Enum: return ETK_Enum; } @@ -1350,6 +1359,7 @@ TypeWithKeyword::getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword) { switch (Keyword) { case ETK_Class: return TTK_Class; case ETK_Struct: return TTK_Struct; + case ETK_Interface: return TTK_Interface; case ETK_Union: return TTK_Union; case ETK_Enum: return TTK_Enum; case ETK_None: // Fall through. @@ -1367,6 +1377,7 @@ TypeWithKeyword::KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword) { return false; case ETK_Class: case ETK_Struct: + case ETK_Interface: case ETK_Union: case ETK_Enum: return true; @@ -1381,6 +1392,7 @@ TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) { case ETK_Typename: return "typename"; case ETK_Class: return "class"; case ETK_Struct: return "struct"; + case ETK_Interface: return "__interface"; case ETK_Union: return "union"; case ETK_Enum: return "enum"; } diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index d5cf4d0b0e..212923421b 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -520,13 +520,13 @@ llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD, const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD); unsigned Tag = 0; if (CXXDecl) { - RDName = getClassName(RD); - Tag = llvm::dwarf::DW_TAG_class_type; - } - else if (RD->isStruct()) - Tag = llvm::dwarf::DW_TAG_structure_type; - else if (RD->isUnion()) - Tag = llvm::dwarf::DW_TAG_union_type; + RDName = getClassName(RD);
+ Tag = llvm::dwarf::DW_TAG_class_type;
+ }
+ else if (RD->isStruct() || RD->isInterface())
+ Tag = llvm::dwarf::DW_TAG_structure_type;
+ else if (RD->isUnion())
+ Tag = llvm::dwarf::DW_TAG_union_type;
else llvm_unreachable("Unknown RecordDecl type!"); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 28d8811b9b..bcc9106eb7 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1875,6 +1875,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break; case DeclSpec::TST_struct: TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break; + case DeclSpec::TST_interface: + TagName="__interface"; FixitTagName = "__interface "; + TagKind=tok::kw___interface;break; case DeclSpec::TST_class: TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break; } @@ -2709,6 +2712,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // class-specifier: case tok::kw_class: case tok::kw_struct: + case tok::kw___interface: case tok::kw_union: { tok::TokenKind Kind = Tok.getKind(); ConsumeToken(); @@ -3531,6 +3535,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: + case tok::kw___interface: case tok::kw_union: // enum-specifier case tok::kw_enum: @@ -3602,6 +3607,7 @@ bool Parser::isTypeSpecifierQualifier() { // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: + case tok::kw___interface: case tok::kw_union: // enum-specifier case tok::kw_enum: @@ -3740,6 +3746,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_class: case tok::kw_struct: case tok::kw_union: + case tok::kw___interface: // enum-specifier case tok::kw_enum: diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 42ec6b0205..e5740112bb 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1031,12 +1031,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, bool EnteringContext, DeclSpecContext DSC) { - DeclSpec::TST TagType; - if (TagTokKind == tok::kw_struct) - TagType = DeclSpec::TST_struct; - else if (TagTokKind == tok::kw_class) - TagType = DeclSpec::TST_class; - else { + DeclSpec::TST TagType;
+ if (TagTokKind == tok::kw_struct)
+ TagType = DeclSpec::TST_struct;
+ else if (TagTokKind == tok::kw___interface)
+ TagType = DeclSpec::TST_interface;
+ else if (TagTokKind == tok::kw_class)
+ TagType = DeclSpec::TST_class;
+ else {
assert(TagTokKind == tok::kw_union && "Not a class specifier"); TagType = DeclSpec::TST_union; } @@ -1148,13 +1150,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } Diag(NameLoc, diag::err_explicit_spec_non_template) - << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) - << (TagType == DeclSpec::TST_class? 0 - : TagType == DeclSpec::TST_struct? 1 - : 2) - << Name - << SourceRange(LAngleLoc, RAngleLoc); - + << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+ << (TagType == DeclSpec::TST_class? 0
+ : TagType == DeclSpec::TST_struct? 1
+ : TagType == DeclSpec::TST_interface? 2
+ : 3)
+ << Name
+ << SourceRange(LAngleLoc, RAngleLoc);
+
// Strip off the last template parameter list if it was empty, since // we've removed its template argument list. if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) { @@ -1240,14 +1243,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, (Tok.is(tok::semi) || (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) { TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration; - if (Tok.isNot(tok::semi)) { - // A semicolon was missing after this declaration. Diagnose and recover. - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, - TagType == DeclSpec::TST_class ? "class" : - TagType == DeclSpec::TST_struct ? "struct" : "union"); - PP.EnterToken(Tok); - Tok.setKind(tok::semi); - } + if (Tok.isNot(tok::semi)) {
+ // A semicolon was missing after this declaration. Diagnose and recover.
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
+ DeclSpec::getSpecifierName(TagType));
+ PP.EnterToken(Tok);
+ Tok.setKind(tok::semi);
+ }
} else TUK = Sema::TUK_Reference; @@ -1466,14 +1468,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Also enforce C++ [temp]p3: // In a template-declaration which defines a class, no declarator // is permitted. - if (TUK == Sema::TUK_Definition && - (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) { - ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, - TagType == DeclSpec::TST_class ? "class" : - TagType == DeclSpec::TST_struct ? "struct" : "union"); - // Push this token back into the preprocessor and change our current token - // to ';' so that the rest of the code recovers as though there were an - // ';' after the definition. + if (TUK == Sema::TUK_Definition &&
+ (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
+ DeclSpec::getSpecifierName(TagType));
+ // Push this token back into the preprocessor and change our current token
+ // to ';' so that the rest of the code recovers as though there were an
+ // ';' after the definition.
PP.EnterToken(Tok); Tok.setKind(tok::semi); } @@ -2236,12 +2237,13 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, /// member-declaration member-specification[opt] /// access-specifier ':' member-specification[opt] /// -void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, - unsigned TagType, Decl *TagDecl) { - assert((TagType == DeclSpec::TST_struct || - TagType == DeclSpec::TST_union || - TagType == DeclSpec::TST_class) && "Invalid TagType!"); - +void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
+ unsigned TagType, Decl *TagDecl) {
+ assert((TagType == DeclSpec::TST_struct ||
+ TagType == DeclSpec::TST_interface ||
+ TagType == DeclSpec::TST_union ||
+ TagType == DeclSpec::TST_class) && "Invalid TagType!");
+
PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc, "parsing struct/union/class body"); diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 8fdb07029a..86833c0e94 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -270,6 +270,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_int: case TST_int128: case TST_struct: + case TST_interface: case TST_union: case TST_unknown_anytype: case TST_unspecified: @@ -400,6 +401,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_class: return "class"; case DeclSpec::TST_union: return "union"; case DeclSpec::TST_struct: return "struct"; + case DeclSpec::TST_interface: return "__interface"; case DeclSpec::TST_typename: return "type-name"; case DeclSpec::TST_typeofType: case DeclSpec::TST_typeofExpr: return "typeof"; diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 05b22fa537..15737b3928 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1059,10 +1059,12 @@ bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const { // Allow us to find class templates, too. if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); - + + // For purposes of this check, interfaces match too. if (RecordDecl *RD = dyn_cast<RecordDecl>(ND)) return RD->getTagKind() == TTK_Class || - RD->getTagKind() == TTK_Struct; + RD->getTagKind() == TTK_Struct || + RD->getTagKind() == TTK_Interface; return false; } @@ -1422,7 +1424,8 @@ static const char *GetCompletionTypeString(QualType T, if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { switch (Tag->getTagKind()) { case TTK_Struct: return "struct <anonymous>"; - case TTK_Class: return "class <anonymous>"; + case TTK_Interface: return "__interface <anonymous>"; + case TTK_Class: return "class <anonymous>"; case TTK_Union: return "union <anonymous>"; case TTK_Enum: return "enum <anonymous>"; } @@ -1449,7 +1452,7 @@ static void addThisCompletion(Sema &S, ResultBuilder &Results) { Policy, Allocator)); Builder.AddTypedTextChunk("this"); - Results.AddResult(CodeCompletionResult(Builder.TakeString())); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); } /// \brief Add language constructs that show up for "ordinary" names. @@ -2884,6 +2887,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { default: if (TagDecl *TD = dyn_cast<TagDecl>(D)) { switch (TD->getTagKind()) { + case TTK_Interface: // fall through case TTK_Struct: return CXCursor_StructDecl; case TTK_Class: return CXCursor_ClassDecl; case TTK_Union: return CXCursor_UnionDecl; @@ -3601,6 +3605,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { case DeclSpec::TST_struct: case DeclSpec::TST_class: + case DeclSpec::TST_interface: Filter = &ResultBuilder::IsClassOrStruct; ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; break; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 048dbb68cb..93e07bef62 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -350,8 +350,8 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, /// isTagName() - This method is called *for error recovery purposes only* /// to determine if the specified name is a valid tag name ("struct foo"). If /// so, this returns the TST for the tag corresponding to it (TST_enum, -/// TST_union, TST_struct, TST_class). This is used to diagnose cases in C -/// where the user forgot to specify the tag. +/// TST_union, TST_struct, TST_interface, TST_class). This is used to diagnose +/// cases in C where the user forgot to specify the tag. DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { // Do a tag name lookup in this scope. LookupResult R(*this, &II, SourceLocation(), LookupTagName); @@ -361,6 +361,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { if (const TagDecl *TD = R.getAsSingle<TagDecl>()) { switch (TD->getTagKind()) { case TTK_Struct: return DeclSpec::TST_struct; + case TTK_Interface: return DeclSpec::TST_interface; case TTK_Union: return DeclSpec::TST_union; case TTK_Class: return DeclSpec::TST_class; case TTK_Enum: return DeclSpec::TST_enum; @@ -538,6 +539,11 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, FixItTagName = "struct "; break; + case TTK_Interface: + TagName = "__interface"; + FixItTagName = "__interface "; + break; + case TTK_Union: TagName = "union"; FixItTagName = "union "; @@ -2604,6 +2610,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || DS.getTypeSpecType() == DeclSpec::TST_struct || + DS.getTypeSpecType() == DeclSpec::TST_interface || DS.getTypeSpecType() == DeclSpec::TST_union || DS.getTypeSpecType() == DeclSpec::TST_enum) { TagD = DS.getRepAsDecl(); @@ -2642,7 +2649,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag) << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 : DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 : - DS.getTypeSpecType() == DeclSpec::TST_union ? 2 : 3); + DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 : + DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4); else Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators); // Don't emit warnings after this error. @@ -2763,6 +2771,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec::TST TypeSpecType = DS.getTypeSpecType(); if (TypeSpecType == DeclSpec::TST_class || TypeSpecType == DeclSpec::TST_struct || + TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { AttributeList* attrs = DS.getAttributes().getList(); @@ -2772,7 +2781,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, << attrs->getName() << (TypeSpecType == DeclSpec::TST_class ? 0 : TypeSpecType == DeclSpec::TST_struct ? 1 : - TypeSpecType == DeclSpec::TST_union ? 2 : 3); + TypeSpecType == DeclSpec::TST_union ? 2 : + TypeSpecType == DeclSpec::TST_interface ? 3 : 4); attrs = attrs->getNext(); } } @@ -5185,6 +5195,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setImplicitlyInline(); } + // if this is a method defined in an __interface, set pure + // (isVirtual will already return true) + if (CXXRecordDecl *Parent = dyn_cast<CXXRecordDecl>( + NewFD->getDeclContext())) { + if (Parent->getTagKind() == TTK_Interface) + NewFD->setPure(true); + } + SetNestedNameSpecifier(NewFD, D); isExplicitSpecialization = false; isFunctionTemplateSpecialization = false; @@ -8118,6 +8136,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, switch (D.getDeclSpec().getTypeSpecType()) { case TST_enum: case TST_struct: + case TST_interface: case TST_union: case TST_class: { TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); @@ -8193,6 +8212,31 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, return false; } +/// \brief Get diagnostic %select index for tag kind for +/// redeclaration diagnostic message. +/// WARNING: Indexes apply to particular diagnostics only! +/// +/// \returns diagnostic %select index. +static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag) +{ + switch (Tag) { + case TTK_Struct: return 0; + case TTK_Interface: return 1; + case TTK_Class: return 2; + default: assert("Invalid tag kind for redecl diagnostic!"); + } + return -1; +} + +/// \brief Determine if tag kind is a class-key compatible with +/// class for redeclaration (class, struct, or __interface). +/// +/// \returns true iff the tag kind is compatible. +static bool isClassCompatTagKind(TagTypeKind Tag) +{ + return Tag == TTK_Struct || Tag == TTK_Class || Tag == TTK_Interface; +} + /// \brief Determine whether a tag with a given kind is acceptable /// as a redeclaration of the given tag declaration. /// @@ -8215,12 +8259,11 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, // struct class-key shall be used to refer to a class (clause 9) // declared using the class or struct class-key. TagTypeKind OldTag = Previous->getTagKind(); - if (!isDefinition || (NewTag != TTK_Class && NewTag != TTK_Struct)) + if (!isDefinition || !isClassCompatTagKind(NewTag)) if (OldTag == NewTag) return true; - if ((OldTag == TTK_Struct || OldTag == TTK_Class) && - (NewTag == TTK_Struct || NewTag == TTK_Class)) { + if (isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)) { // Warn about the struct/class tag mismatch. bool isTemplate = false; if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous)) @@ -8230,7 +8273,8 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, // In a template instantiation, do not offer fix-its for tag mismatches // since they usually mess up the template instead of fixing the problem. Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) - << (NewTag == TTK_Class) << isTemplate << &Name; + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name + << getRedeclDiagFromTagKind(OldTag); return true; } @@ -8249,13 +8293,13 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, if (!previousMismatch) { previousMismatch = true; Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch) - << (NewTag == TTK_Class) << isTemplate << &Name; + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name + << getRedeclDiagFromTagKind(I->getTagKind()); } Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion) - << (NewTag == TTK_Class) + << getRedeclDiagFromTagKind(NewTag) << FixItHint::CreateReplacement(I->getInnerLocStart(), - NewTag == TTK_Class? - "class" : "struct"); + TypeWithKeyword::getTagTypeKindName(NewTag)); } } return true; @@ -8271,16 +8315,16 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, } Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) - << (NewTag == TTK_Class) - << isTemplate << &Name; + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name + << getRedeclDiagFromTagKind(OldTag); Diag(Redecl->getLocation(), diag::note_previous_use); // If there is a previous defintion, suggest a fix-it. if (Previous->getDefinition()) { Diag(NewTagLoc, diag::note_struct_class_suggestion) - << (Redecl->getTagKind() == TTK_Class) + << getRedeclDiagFromTagKind(Redecl->getTagKind()) << FixItHint::CreateReplacement(SourceRange(NewTagLoc), - Redecl->getTagKind() == TTK_Class? "class" : "struct"); + TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind())); } return true; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 176e3fecb9..bae03f25af 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -672,12 +672,28 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, isa<CXXConstructorDecl>(FD))) return false; } - return true; -} - -// CheckConstexprFunctionDecl - Check whether a function declaration satisfies -// the requirements of a constexpr function definition or a constexpr -// constructor definition. If so, return true. If not, produce appropriate + return true;
+}
+
+/// \brief Get diagnostic %select index for tag kind for
+/// record diagnostic message.
+/// WARNING: Indexes apply to particular diagnostics only!
+///
+/// \returns diagnostic %select index.
+static unsigned getRecordDiagFromTagKind(TagTypeKind Tag)
+{
+ switch (Tag) {
+ case TTK_Struct: return 0;
+ case TTK_Interface: return 1;
+ case TTK_Class: return 2;
+ default: assert("Invalid tag kind for record diagnostic!");
+ }
+ return -1;
+}
+
+// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
+// the requirements of a constexpr function definition or a constexpr
+// constructor definition. If so, return true. If not, produce appropriate
// diagnostics and return false. // // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. @@ -688,14 +704,14 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { // The definition of a constexpr constructor shall satisfy the following // constraints: // - the class shall not have any virtual base classes; - const CXXRecordDecl *RD = MD->getParent(); - if (RD->getNumVBases()) { - Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) - << isa<CXXConstructorDecl>(NewFD) << RD->isStruct() - << RD->getNumVBases(); - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) - Diag(I->getLocStart(), + const CXXRecordDecl *RD = MD->getParent();
+ if (RD->getNumVBases()) {
+ Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
+ << isa<CXXConstructorDecl>(NewFD)
+ << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I)
+ Diag(I->getLocStart(),
diag::note_constexpr_virtual_base_here) << I->getSourceRange(); return false; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 4fc9abd5c9..4efab1b83b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2998,7 +2998,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, case UTT_IsUnion: return T->isUnionType(); case UTT_IsClass: - return T->isClassType() || T->isStructureType(); + return T->isClassType() || T->isStructureType() || T->isInterfaceType(); case UTT_IsFunction: return T->isFunctionType(); diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index aece90b785..6147d63ef4 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -727,6 +727,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_enum: case TST_union: case TST_struct: + case TST_interface: case TST_class: case TST_auto: case TST_unknown_anytype: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 94ddc239cd..0935e2e2e0 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -753,7 +753,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case DeclSpec::TST_class: case DeclSpec::TST_enum: case DeclSpec::TST_union: - case DeclSpec::TST_struct: { + case DeclSpec::TST_struct: + case DeclSpec::TST_interface: { TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl()); if (!D) { // This can happen in C++ with ambiguous lookups. @@ -1853,30 +1854,31 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case TTK_Struct: Error = 1; /* Struct member */ break; case TTK_Union: Error = 2; /* Union member */ break; case TTK_Class: Error = 3; /* Class member */ break;< |