[cfe-commits] r107543 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclCXX.h lib/AST/ASTContext.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 16:41:54 PDT 2010


Author: dgregor
Date: Fri Jul  2 18:41:54 2010
New Revision: 107543

URL: http://llvm.org/viewvc/llvm-project?rev=107543&view=rev
Log:
Lazily declare implicit copy constructors.

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/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=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jul  2 18:41:54 2010
@@ -1327,6 +1327,13 @@
   //                    Statistics
   //===--------------------------------------------------------------------===//
 
+  /// \brief The number of implicitly-declared copy constructors.
+  static unsigned NumImplicitCopyConstructors;
+  
+  /// \brief The number of implicitly-declared constructors for 
+  /// which declarations were built.
+  static unsigned NumImplicitCopyConstructorsDeclared;
+
   /// \brief The number of implicitly-declared copy assignment operators.
   static unsigned NumImplicitCopyAssignmentOperators;
   

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jul  2 18:41:54 2010
@@ -319,6 +319,9 @@
     /// already computed and are available.
     bool ComputedVisibleConversions : 1;
   
+    /// \brief Whether we have already declared the copy constructor.
+    bool DeclaredCopyConstructor : 1;
+    
     /// \brief Whether we have already declared the copy-assignment operator.
     bool DeclaredCopyAssignment : 1;
     
@@ -576,6 +579,20 @@
     return data().UserDeclaredCopyConstructor;
   }
 
+  /// \brief Determine whether this class has had its copy constructor 
+  /// declared, either via the user or via an implicit declaration.
+  ///
+  /// This value is used for lazy creation of copy constructors.
+  bool hasDeclaredCopyConstructor() const {
+    return data().DeclaredCopyConstructor;
+  }
+  
+  /// \brief Note whether this class has already had its copy constructor 
+  /// declared.
+  void setDeclaredCopyConstructor(bool DCC) {
+    data().DeclaredCopyConstructor = DCC;
+  }
+  
   /// addedAssignmentOperator - Notify the class that another assignment
   /// operator has been added. This routine helps maintain information about the
   /// class based on which operators have been added.

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jul  2 18:41:54 2010
@@ -31,6 +31,8 @@
 
 using namespace clang;
 
+unsigned ASTContext::NumImplicitCopyConstructors;
+unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
 unsigned ASTContext::NumImplicitCopyAssignmentOperators;
 unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
 unsigned ASTContext::NumImplicitDestructors;
@@ -259,6 +261,9 @@
   fprintf(stderr, "Total bytes = %d\n", int(TotalBytes));
 
   // Implicit special member functions.
+  fprintf(stderr, "  %u/%u implicit copy constructors created\n",
+          NumImplicitCopyConstructorsDeclared, 
+          NumImplicitCopyConstructors);
   fprintf(stderr, "  %u/%u implicit copy assignment operators created\n",
           NumImplicitCopyAssignmentOperatorsDeclared, 
           NumImplicitCopyAssignmentOperators);

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Jul  2 18:41:54 2010
@@ -32,6 +32,7 @@
     Abstract(false), HasTrivialConstructor(true),
     HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
     HasTrivialDestructor(true), ComputedVisibleConversions(false),
+    DeclaredCopyConstructor(false), 
     DeclaredCopyAssignment(false), DeclaredDestructor(false),
     Bases(0), NumBases(0), VBases(0), NumVBases(0),
     Definition(D), FirstFriend(0) {
@@ -295,11 +296,13 @@
   // suppress the implicit declaration of a copy constructor.
   if (ConDecl->isCopyConstructor()) {
     data().UserDeclaredCopyConstructor = true;
-
+    data().DeclaredCopyConstructor = true;
+    
     // C++ [class.copy]p6:
     //   A copy constructor is trivial if it is implicitly declared.
     // FIXME: C++0x: don't do this for "= default" copy constructors.
     data().HasTrivialCopyConstructor = false;
+    
   }
 }
 

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Fri Jul  2 18:41:54 2010
@@ -657,6 +657,7 @@
       Data.HasTrivialCopyAssignment = Record[Idx++];
       Data.HasTrivialDestructor = Record[Idx++];
       Data.ComputedVisibleConversions = 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=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Jul  2 18:41:54 2010
@@ -654,6 +654,7 @@
       Record.push_back(Data.HasTrivialCopyAssignment);
       Record.push_back(Data.HasTrivialDestructor);
       Record.push_back(Data.ComputedVisibleConversions);
+      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=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jul  2 18:41:54 2010
@@ -2657,7 +2657,7 @@
     DeclareImplicitDefaultConstructor(ClassDecl);
 
   if (!ClassDecl->hasUserDeclaredCopyConstructor())
-    DeclareImplicitCopyConstructor(ClassDecl);
+    ++ASTContext::NumImplicitCopyConstructors;
 
   if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
     ++ASTContext::NumImplicitCopyAssignmentOperators;
@@ -5065,8 +5065,11 @@
     if (Base->isVirtual())
       continue;
     
-    const CXXRecordDecl *BaseClassDecl
+    CXXRecordDecl *BaseClassDecl
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (!BaseClassDecl->hasDeclaredCopyConstructor())
+      DeclareImplicitCopyConstructor(BaseClassDecl);
+  
     HasConstCopyConstructor
       = BaseClassDecl->hasConstCopyConstructor(Context);
   }
@@ -5075,8 +5078,11 @@
                                        BaseEnd = ClassDecl->vbases_end();
        HasConstCopyConstructor && Base != BaseEnd; 
        ++Base) {
-    const CXXRecordDecl *BaseClassDecl
+    CXXRecordDecl *BaseClassDecl
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (!BaseClassDecl->hasDeclaredCopyConstructor())
+      DeclareImplicitCopyConstructor(BaseClassDecl);
+    
     HasConstCopyConstructor
       = BaseClassDecl->hasConstCopyConstructor(Context);
   }
@@ -5091,8 +5097,11 @@
        ++Field) {
     QualType FieldType = Context.getBaseElementType((*Field)->getType());
     if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
-      const CXXRecordDecl *FieldClassDecl
+      CXXRecordDecl *FieldClassDecl
         = cast<CXXRecordDecl>(FieldClassType->getDecl());
+      if (!FieldClassDecl->hasDeclaredCopyConstructor())
+        DeclareImplicitCopyConstructor(FieldClassDecl);
+
       HasConstCopyConstructor
         = FieldClassDecl->hasConstCopyConstructor(Context);
     }
@@ -5121,8 +5130,11 @@
     if (Base->isVirtual())
       continue;
     
-    const CXXRecordDecl *BaseClassDecl
+    CXXRecordDecl *BaseClassDecl
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (!BaseClassDecl->hasDeclaredCopyConstructor())
+      DeclareImplicitCopyConstructor(BaseClassDecl);
+
     if (CXXConstructorDecl *CopyConstructor
                           = BaseClassDecl->getCopyConstructor(Context, Quals))
       ExceptSpec.CalledDecl(CopyConstructor);
@@ -5131,8 +5143,11 @@
                                        BaseEnd = ClassDecl->vbases_end();
        Base != BaseEnd; 
        ++Base) {
-    const CXXRecordDecl *BaseClassDecl
+    CXXRecordDecl *BaseClassDecl
       = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    if (!BaseClassDecl->hasDeclaredCopyConstructor())
+      DeclareImplicitCopyConstructor(BaseClassDecl);
+
     if (CXXConstructorDecl *CopyConstructor
                           = BaseClassDecl->getCopyConstructor(Context, Quals))
       ExceptSpec.CalledDecl(CopyConstructor);
@@ -5143,8 +5158,11 @@
        ++Field) {
     QualType FieldType = Context.getBaseElementType((*Field)->getType());
     if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
-      const CXXRecordDecl *FieldClassDecl
+      CXXRecordDecl *FieldClassDecl
         = cast<CXXRecordDecl>(FieldClassType->getDecl());
+      if (!FieldClassDecl->hasDeclaredCopyConstructor())
+        DeclareImplicitCopyConstructor(FieldClassDecl);
+
       if (CXXConstructorDecl *CopyConstructor
                           = FieldClassDecl->getCopyConstructor(Context, Quals))
         ExceptSpec.CalledDecl(CopyConstructor);
@@ -5175,6 +5193,10 @@
   CopyConstructor->setImplicit();
   CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
   
+  // Note that we have declared this constructor.
+  ClassDecl->setDeclaredCopyConstructor(true);
+  ++ASTContext::NumImplicitCopyConstructorsDeclared;
+  
   // Add the parameter to the constructor.
   ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
                                                ClassDecl->getLocation(),
@@ -5184,9 +5206,8 @@
                                                VarDecl::None, 0);
   CopyConstructor->setParams(&FromParam, 1);
   if (Scope *S = getScopeForContext(ClassDecl))
-    PushOnScopeChains(CopyConstructor, S, true);
-  else
-    ClassDecl->addDecl(CopyConstructor);
+    PushOnScopeChains(CopyConstructor, S, false);
+  ClassDecl->addDecl(CopyConstructor);
   
   return CopyConstructor;
 }

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=107543&r1=107542&r2=107543&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Jul  2 18:41:54 2010
@@ -464,14 +464,19 @@
 }
 
 void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) {
+  if (!CanDeclareSpecialMemberFunction(Context, Class))
+    return;
+  
+  // If the copy constructor has not yet been declared, do so now.
+  if (!Class->hasDeclaredCopyConstructor())
+    DeclareImplicitCopyConstructor(Class);
+  
   // If the copy assignment operator has not yet been declared, do so now.
-  if (CanDeclareSpecialMemberFunction(Context, Class) &&
-      !Class->hasDeclaredCopyAssignment())
+  if (!Class->hasDeclaredCopyAssignment())
     DeclareImplicitCopyAssignment(Class);
 
   // If the destructor has not yet been declared, do so now.
-  if (CanDeclareSpecialMemberFunction(Context, Class) &&
-      !Class->hasDeclaredDestructor())
+  if (!Class->hasDeclaredDestructor())
     DeclareImplicitDestructor(Class);  
 }
 
@@ -479,6 +484,7 @@
 /// special member function.
 static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) {
   switch (Name.getNameKind()) {
+  case DeclarationName::CXXConstructorName:
   case DeclarationName::CXXDestructorName:
     return true;
     
@@ -501,12 +507,18 @@
     return;
   
   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));
+    break;
+      
   case DeclarationName::CXXDestructorName:
     if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
       if (Record->getDefinition() && !Record->hasDeclaredDestructor() &&
           CanDeclareSpecialMemberFunction(S.Context, Record))
         S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record));
-    
     break;
     
   case DeclarationName::CXXOperatorName:
@@ -1992,9 +2004,11 @@
 
 /// \brief Look up the constructors for the given class.
 DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
-  if (!Class->getDefinition())
-    return DeclContext::lookup_result();
-
+  // If the copy constructor has not yet been declared, do so now.
+  if (CanDeclareSpecialMemberFunction(Context, Class) &&
+      !Class->hasDeclaredCopyConstructor())
+    DeclareImplicitCopyConstructor(Class);
+  
   CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class));
   DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T);
   return Class->lookup(Name);





More information about the cfe-commits mailing list