Migrate the mish-mash of declaration checks in
Sema::ActOnUninitializedDecl over to InitializationSequence (with
default initialization), eliminating redundancy. More importantly, we
now check that a const definition in C++ has an initilizer, which was
an #if 0'd code for many, many months. A few other tweaks were needed
to get everything working again:

  - Fix all of the places in the testsuite where we defined const
    objects without initializers (now that we diagnose this issue)
  - Teach instantiation of static data members to find the previous
    declaration, so that we build proper redeclaration
    chains. Previously, we had the redeclaration chain but built it
    too late to be useful, because...
  - Teach instantiation of static data member definitions not to try
    to check an initializer if a previous declaration already had an
    initializer. This makes sure that we don't complain about static
    const data members with in-class initializers and out-of-line
    definitions.
  - Move all of the incomplete-type checking logic out of
    Sema::FinalizeDeclaratorGroup; it makes more sense in
    ActOnUnitializedDecl.

There may still be a few places where we can improve these
diagnostics. I'll address that as a separate commit.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95657 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 521b420..e12902b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3658,24 +3658,6 @@
   if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
     QualType Type = Var->getType();
 
-    // Record tentative definitions.
-    if (Var->isTentativeDefinitionNow())
-      TentativeDefinitions.push_back(Var);
-
-    // C++ [dcl.init.ref]p3:
-    //   The initializer can be omitted for a reference only in a
-    //   parameter declaration (8.3.5), in the declaration of a
-    //   function return type, in the declaration of a class member
-    //   within its class declaration (9.2), and where the extern
-    //   specifier is explicitly used.
-    if (Type->isReferenceType() && !Var->hasExternalStorage()) {
-      Diag(Var->getLocation(), diag::err_reference_var_requires_init)
-        << Var->getDeclName()
-        << SourceRange(Var->getLocation(), Var->getLocation());
-      Var->setInvalidDecl();
-      return;
-    }
-
     // C++0x [dcl.spec.auto]p3
     if (TypeContainsUndeducedAuto) {
       Diag(Var->getLocation(), diag::err_auto_var_requires_init)
@@ -3684,99 +3666,133 @@
       return;
     }
 
-    // An array without size is an incomplete type, and there are no special
-    // rules in C++ to make such a definition acceptable.
-    if (getLangOptions().CPlusPlus && Type->isIncompleteArrayType() &&
-        !Var->hasExternalStorage()) {
+    switch (Var->isThisDeclarationADefinition()) {
+    case VarDecl::Definition:
+      if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
+        break;
+
+      // We have an out-of-line definition of a static data member
+      // that has an in-class initializer, so we type-check this like
+      // a declaration. 
+      //
+      // Fall through
+      
+    case VarDecl::DeclarationOnly:
+      // It's only a declaration. 
+
+      // Block scope. C99 6.7p7: If an identifier for an object is
+      // declared with no linkage (C99 6.2.2p6), the type for the
+      // object shall be complete.
+      if (!Type->isDependentType() && Var->isBlockVarDecl() && 
+          !Var->getLinkage() && !Var->isInvalidDecl() &&
+          RequireCompleteType(Var->getLocation(), Type,
+                              diag::err_typecheck_decl_incomplete_type))
+        Var->setInvalidDecl();
+
+      // Make sure that the type is not abstract.
+      if (!Type->isDependentType() && !Var->isInvalidDecl() &&
+          RequireNonAbstractType(Var->getLocation(), Type,
+                                 diag::err_abstract_type_in_decl,
+                                 AbstractVariableType))
+        Var->setInvalidDecl();
+      return;
+
+    case VarDecl::TentativeDefinition:
+      // File scope. C99 6.9.2p2: A declaration of an identifier for an
+      // object that has file scope without an initializer, and without a
+      // storage-class specifier or with the storage-class specifier "static",
+      // constitutes a tentative definition. Note: A tentative definition with
+      // external linkage is valid (C99 6.2.2p5).
+      if (!Var->isInvalidDecl()) {
+        if (const IncompleteArrayType *ArrayT
+                                    = Context.getAsIncompleteArrayType(Type)) {
+          if (RequireCompleteType(Var->getLocation(),
+                                  ArrayT->getElementType(),
+                                  diag::err_illegal_decl_array_incomplete_type))
+            Var->setInvalidDecl();
+        } else if (Var->getStorageClass() == VarDecl::Static) {
+          // C99 6.9.2p3: If the declaration of an identifier for an object is
+          // a tentative definition and has internal linkage (C99 6.2.2p3), the
+          // declared type shall not be an incomplete type.
+          // NOTE: code such as the following
+          //     static struct s;
+          //     struct s { int a; };
+          // is accepted by gcc. Hence here we issue a warning instead of
+          // an error and we do not invalidate the static declaration.
+          // NOTE: to avoid multiple warnings, only check the first declaration.
+          if (Var->getPreviousDeclaration() == 0)
+            RequireCompleteType(Var->getLocation(), Type,
+                                diag::ext_typecheck_decl_incomplete_type);
+        }
+      }
+
+      // Record the tentative definition; we're done.
+      if (!Var->isInvalidDecl())
+        TentativeDefinitions.push_back(Var);
+      return;
+    }
+
+    // Provide a specific diagnostic for uninitialized variable
+    // definitions with incomplete array type.
+    if (Type->isIncompleteArrayType()) {
       Diag(Var->getLocation(),
            diag::err_typecheck_incomplete_array_needs_initializer);
       Var->setInvalidDecl();
       return;
     }
 
-    // C++ [temp.expl.spec]p15:
-    //   An explicit specialization of a static data member of a template is a
-    //   definition if the declaration includes an initializer; otherwise, it 
-    //   is a declaration.
-    if (Var->isStaticDataMember() &&
-        Var->getInstantiatedFromStaticDataMember() &&
-        Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+   // Provide a specific diagnostic for uninitialized variable
+   // definitions with reference type.
+   if (Type->isReferenceType()) {
+     Diag(Var->getLocation(), diag::err_reference_var_requires_init)
+       << Var->getDeclName()
+       << SourceRange(Var->getLocation(), Var->getLocation());
+     Var->setInvalidDecl();
+     return;
+   }
+
+    // Do not attempt to type-check the default initializer for a
+    // variable with dependent type.
+    if (Type->isDependentType())
       return;
-    
-    // C++ [dcl.init]p9:
-    //   If no initializer is specified for an object, and the object
-    //   is of (possibly cv-qualified) non-POD class type (or array
-    //   thereof), the object shall be default-initialized; if the
-    //   object is of const-qualified type, the underlying class type
-    //   shall have a user-declared default constructor.
-    //
-    // FIXME: Diagnose the "user-declared default constructor" bit.
-    if (getLangOptions().CPlusPlus) {
-      QualType InitType = Type;
-      if (const ArrayType *Array = Context.getAsArrayType(Type))
-        InitType = Context.getBaseElementType(Array);
-      if ((!Var->hasExternalStorage() && !Var->isExternC()) &&
-          InitType->isRecordType() && !InitType->isDependentType()) {
-        if (!RequireCompleteType(Var->getLocation(), InitType,
-                                 diag::err_invalid_incomplete_type_use)) {
-          InitializedEntity Entity
-            = InitializedEntity::InitializeVariable(Var);
-          InitializationKind Kind
-            = InitializationKind::CreateDefault(Var->getLocation());
 
-          InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
-          OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
-                                                  MultiExprArg(*this, 0, 0));
-          if (Init.isInvalid())
-            Var->setInvalidDecl();
-          else {
-            if (Init.get())
-              Var->setInit(Context, 
-                       MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>()));
-            FinalizeVarWithDestructor(Var, InitType->getAs<RecordType>());
-          }
-        } else {
-          Var->setInvalidDecl();
-        }
-      }
+    if (Var->isInvalidDecl())
+      return;
 
-      // The variable can not have an abstract class type.
-      if (RequireNonAbstractType(Var->getLocation(), Type,
-                                 diag::err_abstract_type_in_decl,
-                                 AbstractVariableType))
-        Var->setInvalidDecl();
+    if (RequireCompleteType(Var->getLocation(), 
+                            Context.getBaseElementType(Type),
+                            diag::err_typecheck_decl_incomplete_type)) {
+      Var->setInvalidDecl();
+      return;
     }
 
-#if 0
-    // FIXME: Temporarily disabled because we are not properly parsing
-    // linkage specifications on declarations, e.g.,
-    //
-    //   extern "C" const CGPoint CGPointerZero;
-    //
-    // C++ [dcl.init]p9:
-    //
-    //     If no initializer is specified for an object, and the
-    //     object is of (possibly cv-qualified) non-POD class type (or
-    //     array thereof), the object shall be default-initialized; if
-    //     the object is of const-qualified type, the underlying class
-    //     type shall have a user-declared default
-    //     constructor. Otherwise, if no initializer is specified for
-    //     an object, the object and its subobjects, if any, have an
-    //     indeterminate initial value; if the object or any of its
-    //     subobjects are of const-qualified type, the program is
-    //     ill-formed.
-    //
-    // This isn't technically an error in C, so we don't diagnose it.
-    //
-    // FIXME: Actually perform the POD/user-defined default
-    // constructor check.
-    if (getLangOptions().CPlusPlus &&
-        Context.getCanonicalType(Type).isConstQualified() &&
-        !Var->hasExternalStorage())
-      Diag(Var->getLocation(),  diag::err_const_var_requires_init)
-        << Var->getName()
-        << SourceRange(Var->getLocation(), Var->getLocation());
-#endif
+    // The variable can not have an abstract class type.
+    if (RequireNonAbstractType(Var->getLocation(), Type,
+                               diag::err_abstract_type_in_decl,
+                               AbstractVariableType)) {
+      Var->setInvalidDecl();
+      return;
+    }
+
+    InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
+    InitializationKind Kind
+      = InitializationKind::CreateDefault(Var->getLocation());
+    
+    InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
+    OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+                                            MultiExprArg(*this, 0, 0));
+    if (Init.isInvalid())
+      Var->setInvalidDecl();
+    else {
+      if (Init.get())
+        Var->setInit(Context, 
+                     MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>()));
+
+      if (getLangOptions().CPlusPlus)
+        if (const RecordType *Record
+                        = Context.getBaseElementType(Type)->getAs<RecordType>())
+          FinalizeVarWithDestructor(Var, Record);
+    }
   }
 }
 
@@ -3792,78 +3808,6 @@
     if (Decl *D = Group[i].getAs<Decl>())
       Decls.push_back(D);
 
-  // Perform semantic analysis that depends on having fully processed both
-  // the declarator and initializer.
-  for (unsigned i = 0, e = Decls.size(); i != e; ++i) {
-    VarDecl *IDecl = dyn_cast<VarDecl>(Decls[i]);
-    if (!IDecl)
-      continue;
-    QualType T = IDecl->getType();
-
-    // Block scope. C99 6.7p7: If an identifier for an object is declared with
-    // no linkage (C99 6.2.2p6), the type for the object shall be complete...
-    if (IDecl->isBlockVarDecl() && !IDecl->hasExternalStorage()) {
-      if (T->isDependentType()) {
-        // If T is dependent, we should not require a complete type.
-        // (RequireCompleteType shouldn't be called with dependent types.)
-        // But we still can at least check if we've got an array of unspecified
-        // size without an initializer.
-        if (!IDecl->isInvalidDecl() && T->isIncompleteArrayType() &&
-            !IDecl->getInit()) {
-          Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)
-            << T;
-          IDecl->setInvalidDecl();
-        }
-      } else if (!IDecl->isInvalidDecl()) {
-        // If T is an incomplete array type with an initializer list that is
-        // dependent on something, its size has not been fixed. We could attempt
-        // to fix the size for such arrays, but we would still have to check
-        // here for initializers containing a C++0x vararg expansion, e.g.
-        // template <typename... Args> void f(Args... args) {
-        //   int vals[] = { args };
-        // }
-        const IncompleteArrayType *IAT = Context.getAsIncompleteArrayType(T);
-        Expr *Init = IDecl->getInit();
-        if (IAT && Init &&
-            (Init->isTypeDependent() || Init->isValueDependent())) {
-          // Check that the member type of the array is complete, at least.
-          if (RequireCompleteType(IDecl->getLocation(), IAT->getElementType(),
-                                  diag::err_typecheck_decl_incomplete_type))
-            IDecl->setInvalidDecl();
-        } else if (RequireCompleteType(IDecl->getLocation(), T,
-                                      diag::err_typecheck_decl_incomplete_type))
-          IDecl->setInvalidDecl();
-      }
-    }
-    // File scope. C99 6.9.2p2: A declaration of an identifier for an
-    // object that has file scope without an initializer, and without a
-    // storage-class specifier or with the storage-class specifier "static",
-    // constitutes a tentative definition. Note: A tentative definition with
-    // external linkage is valid (C99 6.2.2p5).
-    if (IDecl->isThisDeclarationADefinition() == VarDecl::TentativeDefinition &&
-        !IDecl->isInvalidDecl()) {
-      if (const IncompleteArrayType *ArrayT
-          = Context.getAsIncompleteArrayType(T)) {
-        if (RequireCompleteType(IDecl->getLocation(),
-                                ArrayT->getElementType(),
-                                diag::err_illegal_decl_array_incomplete_type))
-          IDecl->setInvalidDecl();
-      } else if (IDecl->getStorageClass() == VarDecl::Static) {
-        // C99 6.9.2p3: If the declaration of an identifier for an object is
-        // a tentative definition and has internal linkage (C99 6.2.2p3), the
-        // declared type shall not be an incomplete type.
-        // NOTE: code such as the following
-        //     static struct s;
-        //     struct s { int a; };
-        // is accepted by gcc. Hence here we issue a warning instead of
-        // an error and we do not invalidate the static declaration.
-        // NOTE: to avoid multiple warnings, only check the first declaration.
-        if (IDecl->getPreviousDeclaration() == 0)
-          RequireCompleteType(IDecl->getLocation(), T,
-                              diag::ext_typecheck_decl_incomplete_type);
-      }
-    }
-  }
   return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
                                                    Decls.data(), Decls.size()));
 }
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 3e710cf..d47b8ca 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2650,7 +2650,7 @@
   //     - if T is a (possibly cv-qualified) class type (Clause 9), the default
   //       constructor for T is called (and the initialization is ill-formed if
   //       T has no accessible default constructor);
-  if (DestType->isRecordType()) {
+  if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) {
     return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType,
                                         Sequence);
   }
@@ -2661,7 +2661,7 @@
   //   If a program calls for the default initialization of an object of
   //   a const-qualified type T, T shall be a class type with a user-provided 
   //   default constructor.
-  if (DestType.isConstQualified())
+  if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus)
     Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
 }
 
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d7820bb..08cb681 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -217,6 +217,8 @@
   // FIXME: having to fake up a LookupResult is dumb.
   LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
                         Sema::LookupOrdinaryName);
+  if (D->isStaticDataMember())
+    SemaRef.LookupQualifiedName(Previous, Owner, false);
   SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration);
 
   if (D->isOutOfLine()) {
@@ -232,7 +234,9 @@
     SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, 
                                                      TSK_ImplicitInstantiation);
   
-  if (D->getInit()) {
+  if (Var->getAnyInitializer()) {
+    // We already have an initializer in the class.
+  } else if (D->getInit()) {
     if (Var->isStaticDataMember() && !D->isOutOfLine())
       SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated);
     else
@@ -1821,7 +1825,6 @@
   CurContext = PreviousContext;
 
   if (Var) {
-    Var->setPreviousDeclaration(OldVar);
     MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
     assert(MSInfo && "Missing member specialization information?");
     Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),