When performing template argument deduction given a function argument
of incomplete array type, attempt to complete the array type. This was
made much easier by Chandler's addition of RequireCompleteExprType(),
which I've tweaked (slightly) to improve the consistency of the
DeclRefExpr. Fixes PR7985.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132530 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index ed1b671..7d0ce8b 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2500,6 +2500,12 @@
   if (ParamRefType) {
     QualType PointeeType = ParamRefType->getPointeeType();
 
+    // If the argument has incomplete array type, try to complete it's type.
+    if (ArgType->isIncompleteArrayType() &&
+        !S.RequireCompleteExprType(Arg, S.PDiag(), 
+                                   std::make_pair(SourceLocation(), S.PDiag())))
+      ArgType = Arg->getType();
+
     //   [C++0x] If P is an rvalue reference to a cv-unqualified
     //   template parameter and the argument is an lvalue, the type
     //   "lvalue reference to A" is used in place of A for type
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index cd08b1e..22db4c8 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2555,6 +2555,10 @@
         == TSK_ExplicitInstantiationDeclaration)
     return;
 
+  // If we already have a definition, we're done.
+  if (Var->getDefinition())
+    return;
+
   InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
   if (Inst)
     return;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 9fccdb1..02bcb2b 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -3280,9 +3280,13 @@
           InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var);
           // Update the type to the newly instantiated definition's type both
           // here and within the expression.
-          T = Var->getDefinition()->getType();
-          E->setType(T);
-
+          if (VarDecl *Def = Var->getDefinition()) {
+            DRE->setDecl(Def);
+            T = Def->getType();
+            DRE->setType(T);
+            E->setType(T);
+          }
+          
           // We still go on to try to complete the type independently, as it
           // may also require instantiations or diagnostics if it remains
           // incomplete.
diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp
index d5711dd..ce2c163 100644
--- a/test/SemaTemplate/instantiate-init.cpp
+++ b/test/SemaTemplate/instantiate-init.cpp
@@ -73,3 +73,26 @@
 
   int x = S<int>::f();
 }
+
+namespace PR7985 {
+  template<int N> struct integral_c { };
+
+  template <typename T, int N>
+  integral_c<N> array_lengthof(T (&x)[N]) { return integral_c<N>(); }
+
+  struct Data {
+    int x;
+  };
+
+  template<typename T>
+  struct Description {
+    static const Data data[];
+  };
+
+  template<typename T>
+  const Data Description<T>::data[] = {{ 0 }};
+
+  void test() {
+    integral_c<1> ic1 = array_lengthof(Description<int>::data);
+  }
+}