Add implicitly-declared default and copy constructors to C++ classes,
when appropriate.

Conversions for class types now make use of copy constructors. I've
replaced the egregious hack allowing class-to-class conversions with a
slightly less egregious hack calling these conversions standard
conversions (for overloading reasons).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58622 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 7de21a8..fa87479 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -799,6 +799,8 @@
                                            Declarator &D, ExprTy *BitfieldWidth,
                                            ExprTy *Init, DeclTy *LastInGroup);
 
+  void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
+
   virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
                                                  DeclTy *TagDecl,
                                                  SourceLocation LBrac,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 2651c7a..7035223 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -552,9 +552,115 @@
               FieldCollector->getCurNumFields(), LBrac, RBrac, 0);
 }
 
+/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
+/// special functions, such as the default constructor, copy
+/// constructor, or destructor, to the given C++ class (C++
+/// [special]p1).  This routine can only be executed just before the
+/// definition of the class is complete.
+void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
+  if (!ClassDecl->hasUserDeclaredConstructor()) {
+    // C++ [class.ctor]p5:
+    //   A default constructor for a class X is a constructor of class X
+    //   that can be called without an argument. If there is no
+    //   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.
+    CXXConstructorDecl *DefaultCon = 
+      CXXConstructorDecl::Create(Context, ClassDecl,
+                                 ClassDecl->getLocation(),
+                                 ClassDecl->getIdentifier(),
+                                 Context.getFunctionType(Context.VoidTy,
+                                                         0, 0, false, 0),
+                                 /*isExplicit=*/false,
+                                 /*isInline=*/true,
+                                 /*isImplicitlyDeclared=*/true);
+    DefaultCon->setAccess(AS_public);
+    ClassDecl->addConstructor(Context, DefaultCon);
+  }
+
+  if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
+    // C++ [class.copy]p4:
+    //   If the class definition does not explicitly declare a copy
+    //   constructor, one is declared implicitly.
+
+    // C++ [class.copy]p5:
+    //   The implicitly-declared copy constructor for a class X will
+    //   have the form
+    //
+    //       X::X(const X&)
+    //
+    //   if
+    bool HasConstCopyConstructor = true;
+
+    //     -- each direct or virtual base class B of X has a copy
+    //        constructor whose first parameter is of type const B& or
+    //        const volatile B&, and
+    for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+         HasConstCopyConstructor && Base != ClassDecl->bases_end(); ++Base) {
+      const CXXRecordDecl *BaseClassDecl
+        = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+      HasConstCopyConstructor 
+        = BaseClassDecl->hasConstCopyConstructor(Context);
+    }
+
+    //     -- for all the nonstatic data members of X that are of a
+    //        class type M (or array thereof), each such class type
+    //        has a copy constructor whose first parameter is of type
+    //        const M& or const volatile M&.
+    for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
+         HasConstCopyConstructor && Field != ClassDecl->field_end(); ++Field) {
+      QualType FieldType = (*Field)->getType();
+      if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+        FieldType = Array->getElementType();
+      if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+        const CXXRecordDecl *FieldClassDecl 
+          = cast<CXXRecordDecl>(FieldClassType->getDecl());
+        HasConstCopyConstructor 
+          = FieldClassDecl->hasConstCopyConstructor(Context);
+      }
+    }
+
+    //  Otherwise, the implicitly declared copy constructor will have
+    //  the form
+    //
+    //       X::X(X&)
+    QualType ArgType = Context.getTypeDeclType(ClassDecl);
+    if (HasConstCopyConstructor)
+      ArgType = ArgType.withConst();
+    ArgType = Context.getReferenceType(ArgType);
+
+    //  An implicitly-declared copy constructor is an inline public
+    //  member of its class.
+    CXXConstructorDecl *CopyConstructor
+      = CXXConstructorDecl::Create(Context, ClassDecl,
+                                   ClassDecl->getLocation(),
+                                   ClassDecl->getIdentifier(),
+                                   Context.getFunctionType(Context.VoidTy,
+                                                           &ArgType, 1,
+                                                           false, 0),
+                                   /*isExplicit=*/false,
+                                   /*isInline=*/true,
+                                   /*isImplicitlyDeclared=*/true);
+    CopyConstructor->setAccess(AS_public);
+
+    // Add the parameter to the constructor.
+    ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
+                                                 ClassDecl->getLocation(),
+                                                 /*IdentifierInfo=*/0,
+                                                 ArgType, VarDecl::None, 0, 0);
+    CopyConstructor->setParams(&FromParam, 1);
+
+    ClassDecl->addConstructor(Context, CopyConstructor);
+  }
+
+  // FIXME: Implicit destructor
+  // FIXME: Implicit copy assignment operator
+}
+
 void Sema::ActOnFinishCXXClassDef(DeclTy *D) {
   CXXRecordDecl *Rec = cast<CXXRecordDecl>(static_cast<Decl *>(D));
   FieldCollector->FinishClass();
+  AddImplicitlyDeclaredMembersToClass(Rec);
   PopDeclContext();
 
   // Everything, including inline method definitions, have been parsed.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d4d4f39..99b0829 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -982,6 +982,13 @@
     ImpCastExprToType(From, FromType);
     break;
 
+  case ICK_Derived_To_Base:
+    // FIXME: This should never happen. It's a consequence of
+    // pretending that a user-defined conversion via copy constructor
+    // is actually a standard conversion.
+    ImpCastExprToType(From, ToType);
+    break;
+
   default:
     assert(false && "Improper second standard conversion");
     break;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 69c0255..b20c026 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -350,24 +350,34 @@
   ImplicitConversionSequence ICS;
   if (IsStandardConversion(From, ToType, ICS.Standard))
     ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
-  else if (IsUserDefinedConversion(From, ToType, ICS.UserDefined))
+  else if (IsUserDefinedConversion(From, ToType, ICS.UserDefined)) {
     ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
-  else {
-    // FIXME: This is a hack to allow a class type S to implicitly
-    // convert to another class type S, at least until we have proper
-    // support for implicitly-declared copy constructors.
-    QualType FromType = Context.getCanonicalType(From->getType());
-    ToType = Context.getCanonicalType(ToType);
-    if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType()) {
-      ICS.Standard.setAsIdentityConversion();
-      ICS.Standard.FromTypePtr = From->getType().getAsOpaquePtr();
-      ICS.Standard.ToTypePtr = ToType.getAsOpaquePtr();
-      ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
-      return ICS;
+    // C++ [over.ics.user]p4:
+    //   A conversion of an expression of class type to the same class
+    //   type is given Exact Match rank, and a conversion of an
+    //   expression of class type to a base class of that type is
+    //   given Conversion rank, in spite of the fact that a copy
+    //   constructor (i.e., a user-defined conversion function) is
+    //   called for those cases.
+    if (CXXConstructorDecl *Constructor 
+          = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
+      if (Constructor->isCopyConstructor(Context)) {
+        // FIXME: This is a temporary hack to give copy-constructor
+        // calls the appropriate rank (Exact Match or Conversion) by
+        // making them into standard conversions. To really fix this, we
+        // need to tweak the rank-checking logic to deal with ranking
+        // different kinds of user conversions.
+        ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
+        ICS.Standard.setAsIdentityConversion();
+        ICS.Standard.FromTypePtr = From->getType().getAsOpaquePtr();
+        ICS.Standard.ToTypePtr = ToType.getAsOpaquePtr();
+        if (IsDerivedFrom(From->getType().getUnqualifiedType(),
+                          ToType.getUnqualifiedType()))
+          ICS.Standard.Second = ICK_Derived_To_Base;
+      }
     }
-
+  } else
     ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
-  }
 
   return ICS;
 }