r214192 - Fix PR10177 where non-type template arguments to alias templates are not marked as used in dependent contexts. The fix actually forces non-dependent names to be checked at template definition time as expected from the standard.

Larisse Voufo lvoufo at google.com
Tue Jul 29 11:44:20 PDT 2014


Author: lvoufo
Date: Tue Jul 29 13:44:19 2014
New Revision: 214192

URL: http://llvm.org/viewvc/llvm-project?rev=214192&view=rev
Log:
Fix PR10177 where non-type template arguments to alias templates are not marked as used in dependent contexts. The fix actually forces non-dependent names to be checked at template definition time as expected from the standard.

Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/SemaCXX/PR10177.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=214192&r1=214191&r2=214192&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jul 29 13:44:19 2014
@@ -12439,6 +12439,8 @@ static void DoMarkVarDeclReferenced(Sema
          "Invalid Expr argument to DoMarkVarDeclReferenced");
   Var->setReferenced();
 
+  TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
+
   // If the context is not potentially evaluated, this is not an odr-use and
   // does not trigger instantiation.
   if (!IsPotentiallyEvaluatedContext(SemaRef)) {
@@ -12453,25 +12455,26 @@ static void DoMarkVarDeclReferenced(Sema
     // arguments, where local variables can't be used.
     const bool RefersToEnclosingScope =
         (SemaRef.CurContext != Var->getDeclContext() &&
-         Var->getDeclContext()->isFunctionOrMethod() &&
-         Var->hasLocalStorage());
-    if (!RefersToEnclosingScope)
-      return;
-
-    if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {
-      // If a variable could potentially be odr-used, defer marking it so
-      // until we finish analyzing the full expression for any lvalue-to-rvalue
-      // or discarded value conversions that would obviate odr-use.
-      // Add it to the list of potential captures that will be analyzed
-      // later (ActOnFinishFullExpr) for eventual capture and odr-use marking
-      // unless the variable is a reference that was initialized by a constant
-      // expression (this will never need to be captured or odr-used).
-      assert(E && "Capture variable should be used in an expression.");
-      if (!Var->getType()->isReferenceType() ||
-          !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
-        LSI->addPotentialCapture(E->IgnoreParens());
+         Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage());
+    if (RefersToEnclosingScope) {
+      if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {
+        // If a variable could potentially be odr-used, defer marking it so
+        // until we finish analyzing the full expression for any
+        // lvalue-to-rvalue
+        // or discarded value conversions that would obviate odr-use.
+        // Add it to the list of potential captures that will be analyzed
+        // later (ActOnFinishFullExpr) for eventual capture and odr-use marking
+        // unless the variable is a reference that was initialized by a constant
+        // expression (this will never need to be captured or odr-used).
+        assert(E && "Capture variable should be used in an expression.");
+        if (!Var->getType()->isReferenceType() ||
+            !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
+          LSI->addPotentialCapture(E->IgnoreParens());
+      }
     }
-    return;
+
+    if (!isTemplateInstantiation(TSK))
+    	return;
   }
 
   VarTemplateSpecializationDecl *VarSpec =
@@ -12483,7 +12486,6 @@ static void DoMarkVarDeclReferenced(Sema
   // templates of class templates, and variable template specializations. Delay
   // instantiations of variable templates, except for those that could be used
   // in a constant expression.
-  TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
   if (isTemplateInstantiation(TSK)) {
     bool TryInstantiating = TSK == TSK_ImplicitInstantiation;
 

Modified: cfe/trunk/test/SemaCXX/PR10177.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR10177.cpp?rev=214192&r1=214191&r2=214192&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/PR10177.cpp (original)
+++ cfe/trunk/test/SemaCXX/PR10177.cpp Tue Jul 29 13:44:19 2014
@@ -9,22 +9,28 @@ struct U {
   static int a;
 };
 
-template<int N> struct S; // expected-note 2{{here}}
+template<int N> struct S; // expected-note 6{{here}}
 
 template<int N>
-int U<N>::a = S<N>::kError; // expected-error 2{{undefined}}
+int U<N>::a = S<N>::kError; // expected-error 6{{undefined}}
 
 template<typename T>
 void f() {
-  // FIXME: The standard suggests that U<0>::a is odr-used by this expression,
-  // but it's not entirely clear that's the right behaviour.
-  (void)alias_ref<int, int&, U<0>::a>();
+  (void)alias_ref<int, int&, U<0>::a>(); // expected-note {{here}}
   (void)func_ref<int, int&, U<1>::a>(); // expected-note {{here}}
   (void)class_ref<int, int&, U<2>::a>(); // expected-note {{here}}
 };
 
+template<int N>
+void fi() {
+  (void)alias_ref<int, int&, U<N>::a>(); // expected-note {{here}}
+  (void)func_ref<int, int&, U<N+1>::a>(); // expected-note {{here}}
+  (void)class_ref<int, int&, U<N+2>::a>(); // expected-note {{here}}
+};
+
 int main() {
-  f<int>(); // expected-note 2{{here}}
+  f<int>();   // NOTE: Non-dependent name uses are type-checked at template definition time.
+  fi<10>();   // expected-note 3{{here}}
 }
 
 namespace N {
@@ -38,3 +44,4 @@ namespace N {
   }
   int j = f<int>();
 }
+





More information about the cfe-commits mailing list