Initialization improvements: addition of string initialization and a few
small bug fixes in SemaInit, switch over SemaDecl to use it more often, and
change a bunch of diagnostics which are different with the new initialization
code.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91767 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 587c141..4b960e8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3525,26 +3525,22 @@
       Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
       VDecl->setInvalidDecl();
     } else if (!VDecl->isInvalidDecl()) {
-      if (VDecl->getType()->isReferenceType()
-          || isa<InitListExpr>(Init)) {
-        InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
-        if (InitSeq) {
-          OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
-                                           MultiExprArg(*this, (void**)&Init, 1),
-                                                    &DclT);
-          if (Result.isInvalid()) {
-            VDecl->setInvalidDecl();
-            return;
-          }
-
-          Init = Result.takeAs<Expr>();
-        } else {
-          InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
+      InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+      if (InitSeq) {
+        OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+                                          MultiExprArg(*this, (void**)&Init, 1),
+                                                  &DclT);
+        if (Result.isInvalid()) {
           VDecl->setInvalidDecl();
           return;
-        }    
-      } else if (CheckInitializerTypes(Init, DclT, Entity, Kind))
+        }
+
+        Init = Result.takeAs<Expr>();
+      } else {
+        InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
         VDecl->setInvalidDecl();
+        return;
+      }
 
       // C++ 3.6.2p2, allow dynamic initialization of static initializers.
       // Don't check invalid declarations to avoid emitting useless diagnostics.
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 6f11a87..44f6cf3 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -1988,6 +1988,7 @@
   case SK_ConstructorInitialization:
   case SK_ZeroInitialization:
   case SK_CAssignment:
+  case SK_StringInit:
     break;
     
   case SK_ConversionSequence:
@@ -2080,6 +2081,13 @@
   Steps.push_back(S);
 }
 
+void InitializationSequence::AddStringInitStep(QualType T) {
+  Step S;
+  S.Kind = SK_StringInit;
+  S.Type = T;
+  Steps.push_back(S);
+}
+
 void InitializationSequence::SetOverloadFailure(FailureKind Failure, 
                                                 OverloadingResult Result) {
   SequenceKind = FailedSequence;
@@ -2492,7 +2500,8 @@
                                            const InitializationKind &Kind,
                                            Expr *Initializer,
                                        InitializationSequence &Sequence) {
-  // FIXME: Implement!
+  Sequence.setSequenceKind(InitializationSequence::StringInit);
+  Sequence.AddStringInitStep(Entity.getType().getType());
 }
 
 /// \brief Attempt initialization by constructor (C++ [dcl.init]), which
@@ -2711,10 +2720,17 @@
       }
     }    
   }
-  
+
+  SourceLocation DeclLoc = Initializer->getLocStart();
+
   if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) {
     // The type we're converting from is a class type, enumerate its conversion
     // functions.
+
+    // Try to force the type to be complete before enumerating the conversion
+    // functions; it's okay if this fails, though.
+    S.RequireCompleteType(DeclLoc, SourceType, 0);
+
     CXXRecordDecl *SourceRecordDecl
       = cast<CXXRecordDecl>(SourceRecordType->getDecl());
     
@@ -2746,8 +2762,6 @@
     }
   }
   
-  SourceLocation DeclLoc = Initializer->getLocStart();
-  
   // Perform overload resolution. If it fails, return the failed result.  
   OverloadCandidateSet::iterator Best;
   if (OverloadingResult Result 
@@ -2876,13 +2890,6 @@
     return;
   }
 
-  // Handle initialization in C
-  if (!S.getLangOptions().CPlusPlus) {
-    setSequenceKind(CAssignment);
-    AddCAssignmentStep(DestType);
-    return;
-  }
-  
   //     - Otherwise, if the destination type is an array, the program is 
   //       ill-formed.
   if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
@@ -2893,6 +2900,13 @@
     
     return;
   }
+
+  // Handle initialization in C
+  if (!S.getLangOptions().CPlusPlus) {
+    setSequenceKind(CAssignment);
+    AddCAssignmentStep(DestType);
+    return;
+  }
   
   //     - If the destination type is a (possibly cv-qualified) class type:
   if (DestType->isRecordType()) {
@@ -3187,6 +3201,7 @@
   case SK_ConversionSequence:
   case SK_ListInitialization:
   case SK_CAssignment:
+  case SK_StringInit:
     assert(Args.size() == 1);
     CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain());
     if (CurInit.isInvalid())
@@ -3425,6 +3440,12 @@
       CurInit = S.Owned(CurInitExpr);
       break;
     }
+
+    case SK_StringInit: {
+      QualType Ty = Step->Type;
+      CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
+      break;
+    }
     }
   }
   
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
index 1987ad0..85f3d2c 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -389,7 +389,10 @@
     StandardConversion,
 
     /// \brief C conversion sequence.
-    CAssignment
+    CAssignment,
+
+    /// \brief String initialization
+    StringInit
   };
   
   /// \brief Describes the kind of a particular step in an initialization
@@ -422,7 +425,9 @@
     /// \brief Zero-initialize the object
     SK_ZeroInitialization,
     /// \brief C assignment
-    SK_CAssignment
+    SK_CAssignment,
+    /// \brief Initialization by string
+    SK_StringInit
   };
   
   /// \brief A single step in the initialization sequence.
@@ -632,6 +637,9 @@
   // path. However, that isn't the case yet.
   void AddCAssignmentStep(QualType T);
 
+  /// \brief Add a string init step.
+  void AddStringInitStep(QualType T);
+
   /// \brief Note that this initialization sequence failed.
   void SetFailed(FailureKind Failure) {
     SequenceKind = FailedSequence;