[cfe-commits] r90463 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaCXX/type-traits.cpp

Anders Carlsson andersca at mac.com
Thu Dec 3 09:49:57 PST 2009


Author: andersca
Date: Thu Dec  3 11:49:57 2009
New Revision: 90463

URL: http://llvm.org/viewvc/llvm-project?rev=90463&view=rev
Log:
When instantiating a class, if a base specifier is not dependent we still need to copy its attributes down to the instantiated class.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=90463&r1=90462&r2=90463&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Dec  3 11:49:57 2009
@@ -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,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=90463&r1=90462&r2=90463&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Dec  3 11:49:57 2009
@@ -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

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=90463&r1=90462&r2=90463&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Dec  3 11:49:57 2009
@@ -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;
     }

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=90463&r1=90462&r2=90463&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Thu Dec  3 11:49:57 2009
@@ -250,3 +250,11 @@
   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





More information about the cfe-commits mailing list