diff options
author | Anders Carlsson <andersca@mac.com> | 2009-12-03 17:49:57 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-12-03 17:49:57 +0000 |
commit | 51f940457ab20f82c62c2093389763bb9f5187eb (patch) | |
tree | 25275640641e0cfedc05927199d9377856bcbc32 | |
parent | a7a8dfd702274fd19ef8b237682b75d814ecfc91 (diff) |
When instantiating a class, if a base specifier is not dependent we still need to copy its attributes down to the instantiated class.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90463 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 8 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 29 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 7 | ||||
-rw-r--r-- | test/SemaCXX/type-traits.cpp | 8 |
4 files changed, 41 insertions, 11 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 5d6dc96638..2ca639197e 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2191,6 +2191,14 @@ public: bool Virtual, AccessSpecifier Access, QualType BaseType, SourceLocation BaseLoc); + + /// SetClassDeclAttributesFromBase - Copies class decl traits + /// (such as whether the class has a trivial constructor, + /// trivial destructor etc) from the given base class. + void SetClassDeclAttributesFromBase(CXXRecordDecl *Class, + const CXXRecordDecl *BaseClass, + bool BaseIsVirtual); + virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 20cc290b18..551ee92266 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -496,12 +496,25 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, return 0; } + SetClassDeclAttributesFromBase(Class, cast<CXXRecordDecl>(BaseDecl), Virtual); + + // Create the base specifier. + // FIXME: Allocate via ASTContext? + return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, + Class->getTagKind() == RecordDecl::TK_class, + Access, BaseType); +} + +void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class, + const CXXRecordDecl *BaseClass, + bool BaseIsVirtual) { + // C++ [dcl.init.aggr]p1: // An aggregate is [...] a class with [...] no base classes [...]. Class->setAggregate(false); Class->setPOD(false); - if (Virtual) { + if (BaseIsVirtual) { // C++ [class.ctor]p5: // A constructor is trivial if its class has no virtual base classes. Class->setHasTrivialConstructor(false); @@ -523,33 +536,27 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // C++ [class.ctor]p5: // A constructor is trivial if all the direct base classes of its // class have trivial constructors. - if (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialConstructor()) + 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 (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialCopyConstructor()) + 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 (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialCopyAssignment()) + 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 (!cast<CXXRecordDecl>(BaseDecl)->hasTrivialDestructor()) + if (!BaseClass->hasTrivialDestructor()) Class->setHasTrivialDestructor(false); - - // Create the base specifier. - // FIXME: Allocate via ASTContext? - return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, - Class->getTagKind() == RecordDecl::TK_class, - Access, BaseType); } /// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 623cde87a9..250d14c865 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -936,6 +936,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/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 340c0ae489..dfb4edce67 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -250,3 +250,11 @@ void has_trivial_destructor() { int t17[T(__has_trivial_destructor(NonPODAr))]; int t18[T(__has_trivial_destructor(VirtAr))]; } + +struct A { ~A() {} }; +template<typename> struct B : A { }; + +void f() { + int t01[T(!__has_trivial_destructor(A))]; + int t02[T(!__has_trivial_destructor(B<int>))]; +}
\ No newline at end of file |