[cfe-commits] r107551 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclCXX.h lib/AST/ASTContext.cpp lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/Frontend/PCHReaderDecl.cpp lib/Frontend/PCHWriterDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLookup.cpp

Douglas Gregor dgregor at apple.com
Fri Jul 2 17:47:01 PDT 2010


Author: dgregor
Date: Fri Jul  2 19:47:00 2010
New Revision: 107551

URL: http://llvm.org/viewvc/llvm-project?rev=107551&view=rev
Log:
Lazily declare default constructors. We now delay the construction of
declarations for implicit default constructors, copy constructors,
copy assignment operators, and destructors. On a "simple" translation
unit that includes a bunch of C++ standard library headers, we
generate relatively few of these implicit declarations now:

  4/159 implicit default constructors created
  18/236 implicit copy constructors created
  70/241 implicit copy assignment operators created
  0/173 implicit destructors created

And, on this translation unit, this optimization doesn't really
provide any benefit. I'll do some more performance measurements soon,
but this completes the implementation work for <rdar://problem/8151045>.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
    cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jul  2 19:47:00 2010
@@ -1327,10 +1327,17 @@
   //                    Statistics
   //===--------------------------------------------------------------------===//
 
+  /// \brief The number of implicitly-declared default constructors.
+  static unsigned NumImplicitDefaultConstructors;
+  
+  /// \brief The number of implicitly-declared default constructors for 
+  /// which declarations were built.
+  static unsigned NumImplicitDefaultConstructorsDeclared;
+
   /// \brief The number of implicitly-declared copy constructors.
   static unsigned NumImplicitCopyConstructors;
   
-  /// \brief The number of implicitly-declared constructors for 
+  /// \brief The number of implicitly-declared copy constructors for 
   /// which declarations were built.
   static unsigned NumImplicitCopyConstructorsDeclared;
 

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jul  2 19:47:00 2010
@@ -318,7 +318,11 @@
     /// ComputedVisibleConversions - True when visible conversion functions are
     /// already computed and are available.
     bool ComputedVisibleConversions : 1;
-  
+
+    /// \brief Whether we have already declared the default constructor or 
+    /// do not need to have one declared.
+    bool DeclaredDefaultConstructor : 1;
+
     /// \brief Whether we have already declared the copy constructor.
     bool DeclaredCopyConstructor : 1;
     
@@ -540,6 +544,20 @@
     return data().FirstFriend != 0;
   }
 
+  /// \brief Determine whether this class has had its default constructor 
+  /// declared implicitly or does not need one declared implicitly.
+  ///
+  /// This value is used for lazy creation of default constructors.
+  bool hasDeclaredDefaultConstructor() const {
+    return data().DeclaredDefaultConstructor;
+  }
+  
+  /// \brief Note whether this class has already had its default constructor 
+  /// implicitly declared or doesn't need one.
+  void setDeclaredDefaultConstructor(bool DDC) {
+    data().DeclaredDefaultConstructor = DDC;
+  }
+  
   /// hasConstCopyConstructor - Determines whether this class has a
   /// copy constructor that accepts a const-qualified argument.
   bool hasConstCopyConstructor(ASTContext &Context) const;

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jul  2 19:47:00 2010
@@ -31,6 +31,8 @@
 
 using namespace clang;
 
+unsigned ASTContext::NumImplicitDefaultConstructors;
+unsigned ASTContext::NumImplicitDefaultConstructorsDeclared;
 unsigned ASTContext::NumImplicitCopyConstructors;
 unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
 unsigned ASTContext::NumImplicitCopyAssignmentOperators;
@@ -261,6 +263,9 @@
   fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));
 
   // Implicit special member functions.
+  fprintf(stderr, "  %u/%u implicit default constructors created\n",
+          NumImplicitDefaultConstructorsDeclared, 
+          NumImplicitDefaultConstructors);
   fprintf(stderr, "  %u/%u implicit copy constructors created\n",
           NumImplicitCopyConstructorsDeclared, 
           NumImplicitCopyConstructors);

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Fri Jul  2 19:47:00 2010
@@ -975,6 +975,12 @@
     CreateStoredDeclsMap(*C);
   }
 
+  // If there is an external AST source, load any declarations it knows about
+  // with this declaration's name.
+  if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
+    if (hasExternalVisibleStorage())
+      Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
+
   // Insert this declaration into the map.
   StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
   if (DeclNameEntries.isNull()) {

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jul  2 19:47:00 2010
@@ -32,7 +32,7 @@
     Abstract(false), HasTrivialConstructor(true),
     HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
     HasTrivialDestructor(true), ComputedVisibleConversions(false),
-    DeclaredCopyConstructor(false), 
+    DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), 
     DeclaredCopyAssignment(false), DeclaredDestructor(false),
     Bases(0), NumBases(0), VBases(0), NumVBases(0),
     Definition(D), FirstFriend(0) {
@@ -277,6 +277,9 @@
   // Note that we have a user-declared constructor.
   data().UserDeclaredConstructor = true;
 
+  // Note that we have no need of an implicitly-declared default constructor.
+  data().DeclaredDefaultConstructor = true;
+  
   // C++ [dcl.init.aggr]p1:
   //   An aggregate is an array or a class (clause 9) with no
   //   user-declared constructors (12.1) [...].

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Fri Jul  2 19:47:00 2010
@@ -657,6 +657,7 @@
       Data.HasTrivialCopyAssignment = Record[Idx++];
       Data.HasTrivialDestructor = Record[Idx++];
       Data.ComputedVisibleConversions = Record[Idx++];
+      Data.DeclaredDefaultConstructor = Record[Idx++];
       Data.DeclaredCopyConstructor = Record[Idx++];
       Data.DeclaredCopyAssignment = Record[Idx++];
       Data.DeclaredDestructor = Record[Idx++];

Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Jul  2 19:47:00 2010
@@ -654,6 +654,7 @@
       Record.push_back(Data.HasTrivialCopyAssignment);
       Record.push_back(Data.HasTrivialDestructor);
       Record.push_back(Data.ComputedVisibleConversions);
+      Record.push_back(Data.DeclaredDefaultConstructor);
       Record.push_back(Data.DeclaredCopyConstructor);
       Record.push_back(Data.DeclaredCopyAssignment);
       Record.push_back(Data.DeclaredDestructor);

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jul  2 19:47:00 2010
@@ -2654,7 +2654,7 @@
 /// definition of the class is complete.
 void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
   if (!ClassDecl->hasUserDeclaredConstructor())
-    DeclareImplicitDefaultConstructor(ClassDecl);
+    ++ASTContext::NumImplicitDefaultConstructors;
 
   if (!ClassDecl->hasUserDeclaredCopyConstructor())
     ++ASTContext::NumImplicitCopyConstructors;
@@ -4156,6 +4156,19 @@
   //   user-declared constructor for class X, a default constructor is
   //   implicitly declared. An implicitly-declared default constructor
   //   is an inline public member of its class.
+  assert(!ClassDecl->hasUserDeclaredConstructor() && 
+         "Should not build implicit default constructor!");
+  
+  // FIXME: HACK HACK HACK
+  if (Context.getExternalSource()) {
+    // This hack ensures that, when using precompiled headers, the lookup
+    // table in the DeclContext has already loaded the constructor declarations
+    // so that we can add a new one. The real fix will go into DeclContext,
+    // when I figure out what that is.
+    CanQualType T
+      = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+    ClassDecl->lookup(Context.DeclarationNames.getCXXConstructorName(T));
+  }
   
   // C++ [except.spec]p14:
   //   An implicitly declared special member function (Clause 12) shall have an 
@@ -4169,20 +4182,28 @@
     if (B->isVirtual()) // Handled below.
       continue;
     
-    if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
-      if (CXXConstructorDecl *Constructor
-            = cast<CXXRecordDecl>(BaseType->getDecl())->getDefaultConstructor())
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+        ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
+      else if (CXXConstructorDecl *Constructor 
+                                       = BaseClassDecl->getDefaultConstructor())
         ExceptSpec.CalledDecl(Constructor);
+    }
   }
   
   // Virtual base-class destructors.
   for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
                                        BEnd = ClassDecl->vbases_end();
        B != BEnd; ++B) {
-    if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
-      if (CXXConstructorDecl *Constructor
-            = cast<CXXRecordDecl>(BaseType->getDecl())->getDefaultConstructor())
+    if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+        ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
+      else if (CXXConstructorDecl *Constructor
+                                       = BaseClassDecl->getDefaultConstructor())
         ExceptSpec.CalledDecl(Constructor);
+    }
   }
   
   // Field destructors.
@@ -4190,10 +4211,15 @@
                                FEnd = ClassDecl->field_end();
        F != FEnd; ++F) {
     if (const RecordType *RecordTy
-                = Context.getBaseElementType(F->getType())->getAs<RecordType>())
-      if (CXXConstructorDecl *Constructor
-            = cast<CXXRecordDecl>(RecordTy->getDecl())->getDefaultConstructor())
+              = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
+      CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+      if (!FieldClassDecl->hasDeclaredDefaultConstructor())
+        ExceptSpec.CalledDecl(
+                            DeclareImplicitDefaultConstructor(FieldClassDecl));
+      else if (CXXConstructorDecl *Constructor
+                                      = FieldClassDecl->getDefaultConstructor())
         ExceptSpec.CalledDecl(Constructor);
+    }
   }
   
   
@@ -4219,10 +4245,15 @@
   DefaultCon->setAccess(AS_public);
   DefaultCon->setImplicit();
   DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
+  
+  // Note that we have declared this constructor.
+  ClassDecl->setDeclaredDefaultConstructor(true);
+  ++ASTContext::NumImplicitDefaultConstructorsDeclared;
+  
   if (Scope *S = getScopeForContext(ClassDecl))
-    PushOnScopeChains(DefaultCon, S, true);
-  else
-    ClassDecl->addDecl(DefaultCon);
+    PushOnScopeChains(DefaultCon, S, false);
+  ClassDecl->addDecl(DefaultCon);
+  
   return DefaultCon;
 }
 
@@ -4612,7 +4643,17 @@
   // constructor rules. Note that virtual bases are not taken into account
   // for determining the argument type of the operator. Note also that
   // operators taking an object instead of a reference are allowed.
-  //
+  
+  
+  // FIXME: HACK HACK HACK
+  if (Context.getExternalSource()) {
+    // This hack ensures that, when using precompiled headers, the lookup
+    // table in the DeclContext has already loaded the assignment operator
+    // declarations so that we can add a new one. The real fix will go into 
+    // DeclContext, when I figure out what that is.
+    ClassDecl->lookup(Context.DeclarationNames.getCXXOperatorName(OO_Equal));
+  }
+  
   // C++ [class.copy]p10:
   //   If the class definition does not explicitly declare a copy
   //   assignment operator, one is declared implicitly.
@@ -5045,6 +5086,17 @@
   //   If the class definition does not explicitly declare a copy
   //   constructor, one is declared implicitly.
   
+  // FIXME: HACK HACK HACK
+  if (Context.getExternalSource()) {
+    // This hack ensures that, when using precompiled headers, the lookup
+    // table in the DeclContext has already loaded the constructor declarations
+    // so that we can add a new one. The real fix will go into DeclContext,
+    // when I figure out what that is.
+    CanQualType T
+      = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
+    ClassDecl->lookup(Context.DeclarationNames.getCXXConstructorName(T));
+  }
+  
   // C++ [class.copy]p5:
   //   The implicitly-declared copy constructor for a class X will
   //   have the form

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=107551&r1=107550&r2=107551&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jul  2 19:47:00 2010
@@ -466,6 +466,10 @@
 void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
   if (!CanDeclareSpecialMemberFunction(Context, Class))
     return;
+
+  // If the default constructor has not yet been declared, do so now.
+  if (!Class->hasDeclaredDefaultConstructor())
+    DeclareImplicitDefaultConstructor(Class);
   
   // If the copy constructor has not yet been declared, do so now.
   if (!Class->hasDeclaredCopyConstructor())
@@ -509,9 +513,14 @@
   switch (Name.getNameKind()) {
   case DeclarationName::CXXConstructorName:
     if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
-      if (Record->getDefinition() && !Record->hasDeclaredCopyConstructor() &&
-          CanDeclareSpecialMemberFunction(S.Context, Record))
-        S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record));
+      if (Record->getDefinition() &&
+          CanDeclareSpecialMemberFunction(S.Context, Record)) {
+        if (!Record->hasDeclaredDefaultConstructor())
+          S.DeclareImplicitDefaultConstructor(
+                                           const_cast<CXXRecordDecl *>(Record));
+        if (!Record->hasDeclaredCopyConstructor())
+          S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record));
+      }
     break;
       
   case DeclarationName::CXXDestructorName:
@@ -2005,9 +2014,12 @@
 /// \brief Look up the constructors for the given class.
 DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
   // If the copy constructor has not yet been declared, do so now.
-  if (CanDeclareSpecialMemberFunction(Context, Class) &&
-      !Class->hasDeclaredCopyConstructor())
-    DeclareImplicitCopyConstructor(Class);
+  if (CanDeclareSpecialMemberFunction(Context, Class)) {
+    if (!Class->hasDeclaredDefaultConstructor())
+      DeclareImplicitDefaultConstructor(Class);
+    if (!Class->hasDeclaredCopyConstructor())
+      DeclareImplicitCopyConstructor(Class);
+  }
   
   CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));
   DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);





More information about the cfe-commits mailing list