Implement C++ copy-initialization for declarations. There is now some
duplication in the handling of copy-initialization by constructor,
which occurs both for initialization of a declaration and for
overloading. The initialization code is due for some refactoring.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58756 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 95d17fa..b95ebf0 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -835,7 +835,6 @@
   // Add this constructor to the set of constructors of the current
   // class.
   ClassDecl->addConstructor(Context, ConDecl);
-
   return (DeclTy *)ConDecl;
 }
 
@@ -960,15 +959,23 @@
 
   if (VDecl->getType()->isRecordType()) {
     CXXConstructorDecl *Constructor
-      = PerformDirectInitForClassType(DeclInitType, (Expr **)ExprTys, NumExprs,
-                                      VDecl->getLocation(),
-                                      SourceRange(VDecl->getLocation(),
-                                                  RParenLoc),
-                                      VDecl->getName(),
-                                      /*HasInitializer=*/true);
+      = PerformInitializationByConstructor(DeclInitType, 
+                                           (Expr **)ExprTys, NumExprs,
+                                           VDecl->getLocation(),
+                                           SourceRange(VDecl->getLocation(),
+                                                       RParenLoc),
+                                           VDecl->getName(),
+                                           IK_Direct);
     if (!Constructor) {
       RealDecl->setInvalidDecl();
     }
+
+    // Let clients know that initialization was done with a direct
+    // initializer.
+    VDecl->setCXXDirectInitializer(true);
+
+    // FIXME: Add ExprTys and Constructor to the RealDecl as part of
+    // the initializer.
     return;
   }
 
@@ -987,21 +994,26 @@
   AddInitializerToDecl(Dcl, ExprTys[0]);
 }
 
-/// PerformDirectInitForClassType - Perform direct-initialization (C++
-/// [dcl.init]) for a value of the given class type with the given set
-/// of arguments (@p Args). @p Loc is the location in the source code
-/// where the initializer occurs (e.g., a declaration, member
-/// initializer, functional cast, etc.) while @p Range covers the
-/// whole initialization. @p HasInitializer is true if the initializer
-/// was actually written in the source code. When successful, returns
+/// PerformInitializationByConstructor - Perform initialization by
+/// constructor (C++ [dcl.init]p14), which may occur as part of
+/// direct-initialization or copy-initialization. We are initializing
+/// an object of type @p ClassType with the given arguments @p
+/// Args. @p Loc is the location in the source code where the
+/// initializer occurs (e.g., a declaration, member initializer,
+/// functional cast, etc.) while @p Range covers the whole
+/// initialization. @p InitEntity is the entity being initialized,
+/// which may by the name of a declaration or a type. @p Kind is the
+/// kind of initialization we're performing, which affects whether
+/// explicit constructors will be considered. When successful, returns
 /// the constructor that will be used to perform the initialization;
-/// when the initialization fails, emits a diagnostic and returns null.
+/// when the initialization fails, emits a diagnostic and returns
+/// null.
 CXXConstructorDecl *
-Sema::PerformDirectInitForClassType(QualType ClassType,
-                                    Expr **Args, unsigned NumArgs,
-                                    SourceLocation Loc, SourceRange Range,
-                                    std::string InitEntity,
-                                    bool HasInitializer) {
+Sema::PerformInitializationByConstructor(QualType ClassType,
+                                         Expr **Args, unsigned NumArgs,
+                                         SourceLocation Loc, SourceRange Range,
+                                         std::string InitEntity,
+                                         InitializationKind Kind) {
   const RecordType *ClassRec = ClassType->getAsRecordType();
   assert(ClassRec && "Can only initialize a class type here");
 
@@ -1017,15 +1029,23 @@
   //   with the initializer expression(s) as its argument(s). If no
   //   constructor applies, or the overload resolution is ambiguous,
   //   the initialization is ill-formed.
-  //
-  // FIXME: We don't check cv-qualifiers on the class type, because we
-  // don't yet keep track of whether a class type is a POD class type
-  // (or a "trivial" class type, as is used in C++0x).
   const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
   OverloadCandidateSet CandidateSet;
+
+  // Add constructors to the overload set.
+  OverloadedFunctionDecl *Constructors 
+    = const_cast<OverloadedFunctionDecl *>(ClassDecl->getConstructors());
+  for (OverloadedFunctionDecl::function_iterator Con 
+         = Constructors->function_begin();
+       Con != Constructors->function_end(); ++Con) {
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+    if ((Kind == IK_Direct) ||
+        (Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
+        (Kind == IK_Default && Constructor->isDefaultConstructor()))
+      AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
+  }
+
   OverloadCandidateSet::iterator Best;
-  AddOverloadCandidates(ClassDecl->getConstructors(), Args, NumArgs,
-                        CandidateSet);
   switch (BestViableFunction(CandidateSet, Best)) {
   case OR_Success:
     // We found a constructor. Return it.