]> granicus.if.org Git - clang/commitdiff
When attempting to complete an incomplete array bound type in an expression,
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 14 Dec 2017 15:40:16 +0000 (15:40 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 14 Dec 2017 15:40:16 +0000 (15:40 +0000)
update the type from the definition even if we didn't instantiate a definition.

We may have instantiated the definition in an earlier stage of semantic
analysis, after creating the DeclRefExpr but before we reach a point where a
complete expression type is required.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@320709 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaType.cpp
test/SemaTemplate/cxx17-inline-variables.cpp

index 2d8094b991c6e5bc1e21626d4e91df3c5bf6108d..2fffe8e1797077f6e02f6b161f2b060a07dd1652 100644 (file)
@@ -7268,27 +7268,29 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
 void Sema::completeExprArrayBound(Expr *E) {
   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
     if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
-      if (isTemplateInstantiation(Var->getTemplateSpecializationKind()) &&
-          !Var->getDefinition()) {
-        SourceLocation PointOfInstantiation = E->getExprLoc();
-        InstantiateVariableDefinition(PointOfInstantiation, Var);
+      if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
         auto *Def = Var->getDefinition();
-
-        // If we don't already have a point of instantiation, and we managed to
-        // instantiate a definition, this is the point of instantiation.
-        // Otherwise, we don't request an end-of-TU instantiation, so this is
-        // not a point of instantiation.
-        // FIXME: Is this really the right behavior?
-        if (Var->getPointOfInstantiation().isInvalid() && Def) {
-          assert(Var->getTemplateSpecializationKind() ==
-                     TSK_ImplicitInstantiation &&
-                 "explicit instantiation with no point of instantiation");
-          Var->setTemplateSpecializationKind(
-              Var->getTemplateSpecializationKind(), PointOfInstantiation);
+        if (!Def) {
+          SourceLocation PointOfInstantiation = E->getExprLoc();
+          InstantiateVariableDefinition(PointOfInstantiation, Var);
+          Def = Var->getDefinition();
+
+          // If we don't already have a point of instantiation, and we managed
+          // to instantiate a definition, this is the point of instantiation.
+          // Otherwise, we don't request an end-of-TU instantiation, so this is
+          // not a point of instantiation.
+          // FIXME: Is this really the right behavior?
+          if (Var->getPointOfInstantiation().isInvalid() && Def) {
+            assert(Var->getTemplateSpecializationKind() ==
+                       TSK_ImplicitInstantiation &&
+                   "explicit instantiation with no point of instantiation");
+            Var->setTemplateSpecializationKind(
+                Var->getTemplateSpecializationKind(), PointOfInstantiation);
+          }
         }
 
-        // Update the type to the newly instantiated definition's type both
-        // here and within the expression.
+        // Update the type to the definition's type both here and within the
+        // expression.
         if (Def) {
           DRE->setDecl(Def);
           QualType T = Def->getType();
index c0180506bebbb66326c2bfec0abc385d9b81aaf2..9e6761ee57aaf50d0eb34b7898b6bcb27b1521f7 100644 (file)
@@ -5,3 +5,14 @@ template<bool> struct DominatorTreeBase {
 };
 extern template class DominatorTreeBase<false>;
 constexpr bool k = DominatorTreeBase<false>::IsPostDominator;
+
+namespace CompleteType {
+  template<unsigned N> constexpr int f(const bool (&)[N]) { return 0; }
+
+  template<bool ...V> struct X {
+    static constexpr bool arr[] = {V...};
+    static constexpr int value = f(arr);
+  };
+
+  constexpr int n = X<true>::value;
+}