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
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 5d6dc96..2ca6391 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2191,6 +2191,14 @@
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 20cc290..551ee92 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -496,12 +496,25 @@
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 @@
// 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 623cde8..250d14c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -936,6 +936,13 @@
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;
}