diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 47 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 69 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 |
4 files changed, 123 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c189bce8ebf..68cdc556e8d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1958,8 +1958,11 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, TInfo, /*BitWidth=*/0, /*Mutable=*/false); Anon->setAccess(AS); - if (getLangOptions().CPlusPlus) + if (getLangOptions().CPlusPlus) { FieldCollector->Add(cast<FieldDecl>(Anon)); + if (!cast<CXXRecordDecl>(Record)->isEmpty()) + cast<CXXRecordDecl>(OwningClass)->setEmpty(false); + } } else { DeclSpec::SCS SCSpec = DS.getStorageClassSpec(); assert(SCSpec != DeclSpec::SCS_typedef && @@ -3425,7 +3428,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); } else { // Okay: Add virtual to the method. - NewFD->setVirtualAsWritten(true); + CXXRecordDecl *CurClass = cast<CXXRecordDecl>(DC); + CurClass->setMethodAsVirtual(NewFD); } } @@ -3926,6 +3930,15 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, return NewFD->setInvalidDecl(); } } + + // C++ [class]p4: A POD-struct is an aggregate class that has [...] no + // user-defined destructor. + Record->setPOD(false); + + // C++ [class.dtor]p3: A destructor is trivial if it is an implicitly- + // declared destructor. + // FIXME: C++0x: don't do this for "= default" destructors + Record->setHasTrivialDestructor(false); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD)) { ActOnConversionDeclarator(Conversion); @@ -6179,9 +6192,27 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } if (!InvalidDecl && getLangOptions().CPlusPlus) { + CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record); + + if (!T->isPODType()) + CXXRecord->setPOD(false); + if (!ZeroWidth) + CXXRecord->setEmpty(false); + if (T->isReferenceType()) + CXXRecord->setHasTrivialConstructor(false); + if (const RecordType *RT = EltTy->getAs<RecordType>()) { CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); if (RDecl->getDefinition()) { + if (!RDecl->hasTrivialConstructor()) + CXXRecord->setHasTrivialConstructor(false); + if (!RDecl->hasTrivialCopyConstructor()) + CXXRecord->setHasTrivialCopyConstructor(false); + if (!RDecl->hasTrivialCopyAssignment()) + CXXRecord->setHasTrivialCopyAssignment(false); + if (!RDecl->hasTrivialDestructor()) + CXXRecord->setHasTrivialDestructor(false); + // C++ 9.5p1: An object of a class with a non-trivial // constructor, a non-trivial copy constructor, a non-trivial // destructor, or a non-trivial copy assignment operator @@ -6204,6 +6235,18 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, Diag(Loc, diag::warn_attribute_weak_on_field); NewFD->setAccess(AS); + + // C++ [dcl.init.aggr]p1: + // An aggregate is an array or a class (clause 9) with [...] no + // private or protected non-static data members (clause 11). + // A POD must be an aggregate. + if (getLangOptions().CPlusPlus && + (AS == AS_private || AS == AS_protected)) { + CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record); + CXXRecord->setAggregate(false); + CXXRecord->setPOD(false); + } + return NewFD; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 63acb095a66..473247139e6 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -502,6 +502,8 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, return 0; } + SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual); + if (BaseDecl->isInvalidDecl()) Class->setInvalidDecl(); @@ -511,6 +513,73 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access, TInfo); } +void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class, + const CXXRecordDecl *BaseClass, + bool BaseIsVirtual) { + // A class with a non-empty base class is not empty. + // FIXME: Standard ref? + if (!BaseClass->isEmpty()) + Class->setEmpty(false); + + // C++ [class.virtual]p1: + // A class that [...] inherits a virtual function is called a polymorphic + // class. + if (BaseClass->isPolymorphic()) + Class->setPolymorphic(true); + + // C++ [dcl.init.aggr]p1: + // An aggregate is [...] a class with [...] no base classes [...]. + Class->setAggregate(false); + + // C++ [class]p4: + // A POD-struct is an aggregate class... + Class->setPOD(false); + + if (BaseIsVirtual) { + // C++ [class.ctor]p5: + // A constructor is trivial if its class has no virtual base classes. + Class->setHasTrivialConstructor(false); + + // C++ [class.copy]p6: + // A copy constructor is trivial if its class has no virtual base classes. + Class->setHasTrivialCopyConstructor(false); + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if its class has no virtual + // base classes. + Class->setHasTrivialCopyAssignment(false); + + // C++0x [meta.unary.prop] is_empty: + // T is a class type, but not a union type, with ... no virtual base + // classes + Class->setEmpty(false); + } else { + // C++ [class.ctor]p5: + // A constructor is trivial if all the direct base classes of its + // class have trivial constructors. + if (!BaseClass->hasTrivialConstructor()) + Class->setHasTrivialConstructor(false); + + // C++ [class.copy]p6: + // A copy constructor is trivial if all the direct base classes of its + // class have trivial copy constructors. + if (!BaseClass->hasTrivialCopyConstructor()) + Class->setHasTrivialCopyConstructor(false); + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if all the direct base classes + // of its class have trivial copy assignment operators. + if (!BaseClass->hasTrivialCopyAssignment()) + Class->setHasTrivialCopyAssignment(false); + } + + // C++ [class.ctor]p3: + // A destructor is trivial if all the direct base classes of its class + // have trivial destructors. + if (!BaseClass->hasTrivialDestructor()) + Class->setHasTrivialDestructor(false); +} + /// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is /// one entry in the base class list of a class specifier, for /// example: diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a2c3df653b7..5520f640447 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1091,6 +1091,13 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end(); Base != BaseEnd; ++Base) { if (!Base->getType()->isDependentType()) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + // Make sure to set the attributes from the base. + SetClassDeclAttributesFromBase(Instantiation, BaseDecl, + Base->isVirtual()); + InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base)); continue; } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index d87629151eb..f9ff20463ab 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1996,9 +1996,10 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, if (InitFunctionInstantiation(New, Tmpl)) return true; + CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner); New->setAccess(Tmpl->getAccess()); if (Tmpl->isVirtualAsWritten()) - New->setVirtualAsWritten(true); + Record->setMethodAsVirtual(New); // FIXME: attributes // FIXME: New needs a pointer to Tmpl |

