diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:17:06 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:17:06 +0000 |
commit | 53992adde3eda3ccf9da63bc7e45673f043de18f (patch) | |
tree | 3558f327a6f9ab59c5d7a06528d84e1560445247 /lib/Sema/SemaDecl.cpp | |
parent | 7e411337c0ed226dace6e07f1420486768161308 (diff) | |
download | FreeBSD-src-53992adde3eda3ccf9da63bc7e45673f043de18f.zip FreeBSD-src-53992adde3eda3ccf9da63bc7e45673f043de18f.tar.gz |
Update clang to r104832.
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 263 |
1 files changed, 154 insertions, 109 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a802679..af02099 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -90,8 +90,9 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // We know from the grammar that this name refers to a type, so build a // DependentNameType node to describe the type. return CheckTypenameType(ETK_None, - (NestedNameSpecifier *)SS->getScopeRep(), - II, SS->getRange()).getAsOpaquePtr(); + (NestedNameSpecifier *)SS->getScopeRep(), II, + SourceLocation(), SS->getRange(), NameLoc + ).getAsOpaquePtr(); } return 0; @@ -191,7 +192,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, T = Context.getTypeDeclType(TD); if (SS) - T = getQualifiedNameType(*SS, T); + T = getElaboratedType(ETK_None, *SS, T); } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { T = Context.getObjCInterfaceType(IDecl); @@ -223,10 +224,11 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { if (R.getResultKind() == LookupResult::Found) if (const TagDecl *TD = R.getAsSingle<TagDecl>()) { switch (TD->getTagKind()) { - case TagDecl::TK_struct: return DeclSpec::TST_struct; - case TagDecl::TK_union: return DeclSpec::TST_union; - case TagDecl::TK_class: return DeclSpec::TST_class; - case TagDecl::TK_enum: return DeclSpec::TST_enum; + default: return DeclSpec::TST_unspecified; + case TTK_Struct: return DeclSpec::TST_struct; + case TTK_Union: return DeclSpec::TST_union; + case TTK_Class: return DeclSpec::TST_class; + case TTK_Enum: return DeclSpec::TST_enum; } } @@ -285,8 +287,9 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, Name.setIdentifier(&II, IILoc); CXXScopeSpec EmptySS; TemplateTy TemplateResult; - if (isTemplateName(S, SS ? *SS : EmptySS, Name, 0, true, TemplateResult) - == TNK_Type_template) { + bool MemberOfUnknownSpecialization; + if (isTemplateName(S, SS ? *SS : EmptySS, Name, 0, true, TemplateResult, + MemberOfUnknownSpecialization) == TNK_Type_template) { TemplateName TplName = TemplateResult.getAsVal<TemplateName>(); Diag(IILoc, diag::err_template_missing_args) << TplName; if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) { @@ -544,9 +547,9 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; } - // If we failed to complete the type for some reason, don't - // diagnose the variable. - if (Ty->isIncompleteType()) + // If we failed to complete the type for some reason, or if the type is + // dependent, don't diagnose the variable. + if (Ty->isIncompleteType() || Ty->isDependentType()) return false; if (const TagType *TT = Ty->getAs<TagType>()) { @@ -555,9 +558,10 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { - if (!RD->hasTrivialConstructor()) - return false; - if (!RD->hasTrivialDestructor()) + // FIXME: Checking for the presence of a user-declared constructor + // isn't completely accurate; we'd prefer to check that the initializer + // has no side effects. + if (RD->hasUserDeclaredConstructor() || !RD->hasTrivialDestructor()) return false; } } @@ -568,6 +572,18 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return true; } +void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { + if (!ShouldDiagnoseUnusedDecl(D)) + return; + + if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable()) + Diag(D->getLocation(), diag::warn_unused_exception_param) + << D->getDeclName(); + else + Diag(D->getLocation(), diag::warn_unused_variable) + << D->getDeclName(); +} + void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && @@ -584,15 +600,9 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (!D->getDeclName()) continue; // Diagnose unused variables in this scope. - if (ShouldDiagnoseUnusedDecl(D) && - S->getNumErrorsAtStart() == getDiagnostics().getNumErrors()) { - if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable()) - Diag(D->getLocation(), diag::warn_unused_exception_param) - << D->getDeclName(); - else - Diag(D->getLocation(), diag::warn_unused_variable) - << D->getDeclName(); - } + if (S->getNumErrorsAtStart() == getDiagnostics().getNumErrors()) + DiagnoseUnusedDecl(D); + // Remove this name from our lexical scope. IdResolver.RemoveDecl(D); } @@ -1069,10 +1079,18 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { = cast<FunctionType>(OldQType.getTypePtr())->getResultType(); QualType NewReturnType = cast<FunctionType>(NewQType.getTypePtr())->getResultType(); + QualType ResQT; if (OldReturnType != NewReturnType) { - Diag(New->getLocation(), diag::err_ovl_diff_return_type); - Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); - return true; + if (NewReturnType->isObjCObjectPointerType() + && OldReturnType->isObjCObjectPointerType()) + ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType); + if (ResQT.isNull()) { + Diag(New->getLocation(), diag::err_ovl_diff_return_type); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + return true; + } + else + NewQType = ResQT; } const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); @@ -1356,6 +1374,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { = Context.getCanonicalType(New->getType())->getAs<ArrayType>(); if (OldArray->getElementType() == NewArray->getElementType()) MergedT = Old->getType(); + } else if (New->getType()->isObjCObjectPointerType() + && Old->getType()->isObjCObjectPointerType()) { + MergedT = Context.mergeObjCGCQualifiers(New->getType(), Old->getType()); } } else { MergedT = Context.mergeTypes(New->getType(), Old->getType()); @@ -1435,7 +1456,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. -Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { +Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS) { // FIXME: Error on auto/register at file scope // FIXME: Error on inline/virtual/explicit // FIXME: Warn on useless __thread @@ -1485,7 +1507,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { if (getLangOptions().CPlusPlus || Record->getDeclContext()->isRecord()) - return BuildAnonymousStructOrUnion(S, DS, Record); + return BuildAnonymousStructOrUnion(S, DS, AS, Record); Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) << DS.getSourceRange(); @@ -1563,8 +1585,10 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef, /// /// This routine is recursive, injecting the names of nested anonymous /// structs/unions into the owning context and scope as well. -bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, - RecordDecl *AnonRecord) { +static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, + DeclContext *Owner, + RecordDecl *AnonRecord, + AccessSpecifier AS) { unsigned diagKind = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl : diag::err_anonymous_struct_member_redecl; @@ -1574,7 +1598,7 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { - if (CheckAnonMemberRedeclaration(*this, S, Owner, (*F)->getDeclName(), + if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, (*F)->getDeclName(), (*F)->getLocation(), diagKind)) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be @@ -1588,15 +1612,19 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, // considered to have been defined in the scope in which the // anonymous union is declared. Owner->makeDeclVisibleInContext(*F); - S->AddDecl(DeclPtrTy::make(*F)); - IdResolver.AddDecl(*F); + S->AddDecl(Sema::DeclPtrTy::make(*F)); + SemaRef.IdResolver.AddDecl(*F); + + // That includes picking up the appropriate access specifier. + if (AS != AS_none) (*F)->setAccess(AS); } } else if (const RecordType *InnerRecordType = (*F)->getType()->getAs<RecordType>()) { RecordDecl *InnerRecord = InnerRecordType->getDecl(); if (InnerRecord->isAnonymousStructOrUnion()) Invalid = Invalid || - InjectAnonymousStructOrUnionMembers(S, Owner, InnerRecord); + InjectAnonymousStructOrUnionMembers(SemaRef, S, Owner, + InnerRecord, AS); } } @@ -1666,6 +1694,7 @@ StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec, /// (C++ [class.union]) and a GNU C extension; anonymous structures /// are a GNU C and GNU C++ extension. Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, + AccessSpecifier AS, RecordDecl *Record) { DeclContext *Owner = Record->getDeclContext(); @@ -1720,7 +1749,8 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // C++ [class.union]p3: // An anonymous union shall not have private or protected // members (clause 11). - if (FD->getAccess() == AS_protected || FD->getAccess() == AS_private) { + assert(FD->getAccess() != AS_none); + if (FD->getAccess() != AS_public) { Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member) << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected); Invalid = true; @@ -1777,7 +1807,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Context.getTypeDeclType(Record), TInfo, /*BitWidth=*/0, /*Mutable=*/false); - Anon->setAccess(AS_public); + Anon->setAccess(AS); if (getLangOptions().CPlusPlus) { FieldCollector->Add(cast<FieldDecl>(Anon)); if (!cast<CXXRecordDecl>(Record)->isEmpty()) @@ -1814,7 +1844,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Inject the members of the anonymous struct/union into the owning // context and into the identifier resolver chain for name lookup // purposes. - if (InjectAnonymousStructOrUnionMembers(S, Owner, Record)) + if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS)) Invalid = true; // Mark this as an anonymous struct/union type. Note that we do not @@ -2711,7 +2741,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, QualType T = NewVD->getType(); - if (T->isObjCInterfaceType()) { + if (T->isObjCObjectType()) { Diag(NewVD->getLocation(), diag::err_statically_allocated_object); return NewVD->setInvalidDecl(); } @@ -2929,7 +2959,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, D.setInvalidType(); // Do not allow returning a objc interface by-value. - if (R->getAs<FunctionType>()->getResultType()->isObjCInterfaceType()) { + if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) { Diag(D.getIdentifierLoc(), diag::err_object_cannot_be_passed_returned_by_value) << 0 << R->getAs<FunctionType>()->getResultType(); @@ -4322,7 +4352,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, // Parameter declarators cannot be interface types. All ObjC objects are // passed by reference. - if (T->isObjCInterfaceType()) { + if (T->isObjCObjectType()) { Diag(NameLoc, diag::err_object_cannot_be_passed_returned_by_value) << 1 << T; New->setInvalidDecl(); @@ -4540,6 +4570,38 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { return DeclPtrTy::make(FD); } +/// \brief Given the set of return statements within a function body, +/// compute the variables that are subject to the named return value +/// optimization. +/// +/// Each of the variables that is subject to the named return value +/// optimization will be marked as NRVO variables in the AST, and any +/// return statement that has a marked NRVO variable as its NRVO candidate can +/// use the named return value optimization. +/// +/// This function applies a very simplistic algorithm for NRVO: if every return +/// statement in the function has the same NRVO candidate, that candidate is +/// the NRVO variable. +/// +/// FIXME: Employ a smarter algorithm that accounts for multiple return +/// statements and the lifetimes of the NRVO candidates. We should be able to +/// find a maximal set of NRVO variables. +static void ComputeNRVO(Stmt *Body, ReturnStmt **Returns, unsigned NumReturns) { + const VarDecl *NRVOCandidate = 0; + for (unsigned I = 0; I != NumReturns; ++I) { + if (!Returns[I]->getNRVOCandidate()) + return; + + if (!NRVOCandidate) + NRVOCandidate = Returns[I]->getNRVOCandidate(); + else if (NRVOCandidate != Returns[I]->getNRVOCandidate()) + return; + } + + if (NRVOCandidate) + const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true); +} + Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) { return ActOnFinishFunctionBody(D, move(BodyArg), false); } @@ -4567,12 +4629,17 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, WP.disableCheckFallThrough(); } - if (!FD->isInvalidDecl()) + if (!FD->isInvalidDecl()) { DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); - - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) - MaybeMarkVirtualMembersReferenced(Method->getLocation(), Method); - + + // If this is a constructor, we need a vtable. + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD)) + MarkVTableUsed(FD->getLocation(), Constructor->getParent()); + + ComputeNRVO(Body, FunctionScopes.back()->Returns.data(), + FunctionScopes.back()->Returns.size()); + } + assert(FD == getCurFunctionDecl() && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { assert(MD == getCurMethodDecl() && "Method parsing confused"); @@ -4636,7 +4703,9 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, // Verify that that gotos and switch cases don't jump into scopes illegally. // Verify that that gotos and switch cases don't jump into scopes illegally. - if (FunctionNeedsScopeChecking() && !hasAnyErrorsInThisFunction()) + if (FunctionNeedsScopeChecking() && + !dcl->isInvalidDecl() && + !hasAnyErrorsInThisFunction()) DiagnoseInvalidJumps(Body); if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) @@ -4838,38 +4907,38 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, /// /// \returns true if the new tag kind is acceptable, false otherwise. bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, - TagDecl::TagKind NewTag, + TagTypeKind NewTag, SourceLocation NewTagLoc, const IdentifierInfo &Name) { // C++ [dcl.type.elab]p3: // The class-key or enum keyword present in the // elaborated-type-specifier shall agree in kind with the - // declaration to which the name in theelaborated-type-specifier + // declaration to which the name in the elaborated-type-specifier // refers. This rule also applies to the form of // elaborated-type-specifier that declares a class-name or // friend class since it can be construed as referring to the // definition of the class. Thus, in any // elaborated-type-specifier, the enum keyword shall be used to - // refer to an enumeration (7.2), the union class-keyshall be + // refer to an enumeration (7.2), the union class-key shall be // used to refer to a union (clause 9), and either the class or // struct class-key shall be used to refer to a class (clause 9) // declared using the class or struct class-key. - TagDecl::TagKind OldTag = Previous->getTagKind(); + TagTypeKind OldTag = Previous->getTagKind(); if (OldTag == NewTag) return true; - if ((OldTag == TagDecl::TK_struct || OldTag == TagDecl::TK_class) && - (NewTag == TagDecl::TK_struct || NewTag == TagDecl::TK_class)) { + if ((OldTag == TTK_Struct || OldTag == TTK_Class) && + (NewTag == TTK_Struct || NewTag == TTK_Class)) { // Warn about the struct/class tag mismatch. bool isTemplate = false; if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous)) isTemplate = Record->getDescribedClassTemplate(); Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) - << (NewTag == TagDecl::TK_class) + << (NewTag == TTK_Class) << isTemplate << &Name << FixItHint::CreateReplacement(SourceRange(NewTagLoc), - OldTag == TagDecl::TK_class? "class" : "struct"); + OldTag == TTK_Class? "class" : "struct"); Diag(Previous->getLocation(), diag::note_previous_use); return true; } @@ -4891,7 +4960,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, "Nameless record must be a definition!"); OwnedDecl = false; - TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec); + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); // FIXME: Check explicit specializations more carefully. bool isExplicitSpecialization = false; @@ -4915,7 +4984,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } else { // The "template<>" header is extraneous. Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) - << ElaboratedType::getNameForTagKind(Kind) << Name; + << TypeWithKeyword::getTagTypeKindName(Kind) << Name; isExplicitSpecialization = true; } } @@ -5134,8 +5203,8 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // struct or something similar. if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, KWLoc, *Name)) { bool SafeToContinue - = (PrevTagDecl->getTagKind() != TagDecl::TK_enum && - Kind != TagDecl::TK_enum); + = (PrevTagDecl->getTagKind() != TTK_Enum && + Kind != TTK_Enum); if (SafeToContinue) Diag(KWLoc, diag::err_use_with_wrong_tag) << Name @@ -5289,7 +5358,7 @@ CreateNewDecl: // PrevDecl. TagDecl *New; - if (Kind == TagDecl::TK_enum) { + if (Kind == TTK_Enum) { // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // enum X { A, B, C } D; D should chain to X. New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc, @@ -5319,16 +5388,18 @@ CreateNewDecl: // Maybe add qualifier info. if (SS.isNotEmpty()) { - NestedNameSpecifier *NNS - = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); - New->setQualifierInfo(NNS, SS.getRange()); + if (SS.isSet()) { + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + New->setQualifierInfo(NNS, SS.getRange()); + } + else + Invalid = true; } - if (Kind != TagDecl::TK_enum) { - // Handle #pragma pack: if the #pragma pack stack has non-default - // alignment, make up a packed attribute for this decl. These - // attributes are checked when the ASTContext lays out the - // structure. + if (RecordDecl *RD = dyn_cast<RecordDecl>(New)) { + // Add alignment attributes if necessary; these attributes are checked when + // the ASTContext lays out the structure. // // It is important for implementing the correct semantics that this // happen here (in act on tag decl). The #pragma pack stack is @@ -5336,15 +5407,14 @@ CreateNewDecl: // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the // parsing of the struct). - if (unsigned Alignment = getPragmaPackAlignment()) - New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8)); + AddAlignmentAttributesForRecord(RD); } // If this is a specialization of a member class (of a class template), // check the specialization. if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous)) Invalid = true; - + if (Invalid) New->setInvalidDecl(); @@ -5439,37 +5509,6 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD, "Broken injected-class-name"); } -// Traverses the class and any nested classes, making a note of any -// dynamic classes that have no key function so that we can mark all of -// their virtual member functions as "used" at the end of the translation -// unit. This ensures that all functions needed by the vtable will get -// instantiated/synthesized. -static void -RecordDynamicClassesWithNoKeyFunction(Sema &S, CXXRecordDecl *Record, - SourceLocation Loc) { - // We don't look at dependent or undefined classes. - if (Record->isDependentContext() || !Record->isDefinition()) - return; - - if (Record->isDynamicClass()) { - const CXXMethodDecl *KeyFunction = S.Context.getKeyFunction(Record); - - if (!KeyFunction) - S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, - Loc)); - - if ((!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined())) - && Record->getLinkage() == ExternalLinkage) - S.Diag(Record->getLocation(), diag::warn_weak_vtable) << Record; - } - for (DeclContext::decl_iterator D = Record->decls_begin(), - DEnd = Record->decls_end(); - D != DEnd; ++D) { - if (CXXRecordDecl *Nested = dyn_cast<CXXRecordDecl>(*D)) - RecordDynamicClassesWithNoKeyFunction(S, Nested, Loc); - } -} - void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, SourceLocation RBraceLoc) { AdjustDeclIfTemplate(TagD); @@ -5481,10 +5520,6 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, // Exit this scope of this tag's definition. PopDeclContext(); - - if (isa<CXXRecordDecl>(Tag) && !Tag->getLexicalDeclContext()->isRecord()) - RecordDynamicClassesWithNoKeyFunction(*this, cast<CXXRecordDecl>(Tag), - RBraceLoc); // Notify the consumer that we've defined a tag. Consumer.HandleTagDeclDefinition(Tag); @@ -6098,6 +6133,15 @@ void Sema::ActOnFields(Scope* S, EnclosingDecl->setInvalidDecl(); continue; } + if (!FD->getType()->isDependentType() && + !Context.getBaseElementType(FD->getType())->isPODType()) { + Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type) + << FD->getDeclName() << FD->getType(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + // Okay, we have a legal flexible array member at the end of the struct. if (Record) Record->setHasFlexibleArrayMember(true); @@ -6132,7 +6176,7 @@ void Sema::ActOnFields(Scope* S, } if (Record && FDTTy->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); - } else if (FDTy->isObjCInterfaceType()) { + } else if (FDTy->isObjCObjectType()) { /// A field cannot be an Objective-c object Diag(FD->getLocation(), diag::err_statically_allocated_object); FD->setInvalidDecl(); @@ -6435,7 +6479,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(EnumType); } - Enum->completeDefinition(Context.DependentTy, Context.DependentTy); + Enum->completeDefinition(Context.DependentTy, Context.DependentTy, 0, 0); return; } @@ -6616,7 +6660,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(NewTy); } - Enum->completeDefinition(BestType, BestPromotionType); + Enum->completeDefinition(BestType, BestPromotionType, + NumPositiveBits, NumNegativeBits); } Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, |