]> granicus.if.org Git - clang/commitdiff
patch to mark use of implicit copy constructors.
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 22 Jun 2009 23:34:40 +0000 (23:34 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 22 Jun 2009 23:34:40 +0000 (23:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73922 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclCXX.h
lib/AST/DeclCXX.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp

index 2db0ca2274d0178db908505301840d09fffabbb7..52ed0ec8535e6406fe4604a3890407b4bb0f1584 100644 (file)
@@ -283,6 +283,10 @@ public:
   /// copy constructor that accepts a const-qualified argument.
   bool hasConstCopyConstructor(ASTContext &Context) const;
 
+  /// getCopyConstructor - Returns the copy constructor for this class
+  CXXConstructorDecl *getCopyConstructor(ASTContext &Context, 
+                                         unsigned TypeQuals) const;
+
   /// hasConstCopyAssignment - Determines whether this class has a
   /// copy assignment operator that accepts a const-qualified argument.
   bool hasConstCopyAssignment(ASTContext &Context) const;
index 7a930d78c12365f333dd17b9867b3e2070b11847..25e4d196177857da3ceab1f4829aef5799d374df 100644 (file)
@@ -66,21 +66,29 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
 }
 
 bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
+  return getCopyConstructor(Context, QualType::Const) != 0;
+}
+
+CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, 
+                                                      unsigned TypeQuals) const{
   QualType ClassType
     = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
   DeclarationName ConstructorName 
     = Context.DeclarationNames.getCXXConstructorName(
-                                           Context.getCanonicalType(ClassType));
-  unsigned TypeQuals;
+                                          Context.getCanonicalType(ClassType));
+  unsigned FoundTQs;
   DeclContext::lookup_const_iterator Con, ConEnd;
   for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName);
        Con != ConEnd; ++Con) {
-    if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
-        (TypeQuals & QualType::Const) != 0)
-      return true;
+    if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, 
+                                                          FoundTQs)) {
+      if (((TypeQuals & QualType::Const) == (FoundTQs & QualType::Const)) ||
+          (!(TypeQuals & QualType::Const) && (FoundTQs & QualType::Const)))
+        return cast<CXXConstructorDecl>(*Con);
+      
+    }
   }
-
-  return false;
+  return 0;
 }
 
 bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
index e5502a5937800e4cfa06f0a46c4f941c88570a64..8604fe56a27813d873711e0dd3510c7fa44eb3ad 100644 (file)
@@ -1582,10 +1582,16 @@ public:
                                     QualType DeclInitType, 
                                     Expr **Exprs, unsigned NumExprs);
   
-  /// DefineImplicitDefaultConstructor - Checks for feasibilityt of 
+  /// DefineImplicitDefaultConstructor - Checks for feasibility of 
   /// defining this constructor as the default constructor.
   void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
                                         CXXConstructorDecl *Constructor);
+  
+  /// DefineImplicitCopyConstructor - Checks for feasibility of 
+  /// defining this constructor as the copy constructor.
+  void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+                                     CXXConstructorDecl *Constructor,
+                                     unsigned TypeQuals);
 
   /// MaybeBindToTemporary - If the passed in expression has a record type with
   /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
index 962807450c5c82c9e79f7d3b0ee7f394d6a72b32..c9c662671c1f43b5c3d4ff309550de2a40087e14 100644 (file)
@@ -1878,7 +1878,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
   
   CXXRecordDecl *ClassDecl
     = cast<CXXRecordDecl>(Constructor->getDeclContext());
-  assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor");
+  assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
   // Before the implicitly-declared default constructor for a class is 
   // implicitly defined, all the implicitly-declared default constructors
   // for its base class and its non-static data members shall have been
@@ -1891,7 +1891,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
     if (!BaseClassDecl->hasTrivialConstructor()) {
       if (CXXConstructorDecl *BaseCtor = 
             BaseClassDecl->getDefaultConstructor(Context)) {
-        if (BaseCtor->isImplicit())
+        if (BaseCtor->isImplicit() && !BaseCtor->isUsed())
           MarkDeclarationReferenced(CurrentLocation, BaseCtor);
       }
       else {
@@ -1916,7 +1916,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
       if (!FieldClassDecl->hasTrivialConstructor())
         if (CXXConstructorDecl *FieldCtor = 
             FieldClassDecl->getDefaultConstructor(Context)) {
-          if (FieldCtor->isImplicit())
+          if (FieldCtor->isImplicit() && !FieldCtor->isUsed())
             MarkDeclarationReferenced(CurrentLocation, FieldCtor);
         }
         else {
@@ -1945,6 +1945,48 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
     Constructor->setUsed();  
 }
 
+void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+                                   CXXConstructorDecl *CopyConstructor,
+                                   unsigned TypeQuals) {
+  assert((CopyConstructor->isImplicit() && 
+          CopyConstructor->isCopyConstructor(Context, TypeQuals) &&
+          !CopyConstructor->isUsed()) &&
+         "DefineImplicitCopyConstructor - call it for implicit copy ctor");
+  
+  CXXRecordDecl *ClassDecl
+    = cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
+  assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+  // Before the implicitly-declared copy constructor for a class is 
+  // implicitly defined, all the implicitly-declared copy constructors
+  // for its base class and its non-static data members shall have been
+  // implicitly defined.
+  for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+       Base != ClassDecl->bases_end(); ++Base) {
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+    if (CXXConstructorDecl *BaseCopyCtor = 
+        BaseClassDecl->getCopyConstructor(Context, TypeQuals))
+      if (BaseCopyCtor->isImplicit() && !BaseCopyCtor->isUsed())
+        MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
+  }
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
+       Field != ClassDecl->field_end(Context);
+       ++Field) {
+    QualType FieldType = Context.getCanonicalType((*Field)->getType());
+    if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+      FieldType = Array->getElementType();
+    if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+      CXXRecordDecl *FieldClassDecl
+        = cast<CXXRecordDecl>(FieldClassType->getDecl());
+      if (CXXConstructorDecl *FieldCopyCtor = 
+          FieldClassDecl->getCopyConstructor(Context, TypeQuals))
+          if (FieldCopyCtor->isImplicit() && !FieldCopyCtor->isUsed())
+            MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
+    }
+  }
+  CopyConstructor->setUsed();
+}
+
 void Sema::InitializeVarWithConstructor(VarDecl *VD, 
                                         CXXConstructorDecl *Constructor,
                                         QualType DeclInitType, 
index 81765a57d60cf1411aed4fa2279e99049bcdc75a..56d3bfe690bffb63b0a2c75152c3d9c7df0a8e47 100644 (file)
@@ -5515,10 +5515,16 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
       
   // Note that this declaration has been used.
   if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+    unsigned TypeQuals;
     if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
         if (!Constructor->isUsed())
           DefineImplicitDefaultConstructor(Loc, Constructor);
     }
+    else if (Constructor->isImplicit() && 
+             Constructor->isCopyConstructor(Context, TypeQuals)) {
+      if (!Constructor->isUsed())
+        DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
+    }
     // FIXME: more checking for other implicits go here.
     else
       Constructor->setUsed(true);