<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Jul 29, 2014 at 11:44 AM, Larisse Voufo <span dir="ltr"><<a href="mailto:lvoufo@google.com" target="_blank">lvoufo@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: lvoufo<br>
Date: Tue Jul 29 13:44:19 2014<br>
New Revision: 214192<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=214192&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=214192&view=rev</a><br>
Log:<br>
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.<br>
<br>
Modified:<br>
cfe/trunk/lib/Sema/SemaExpr.cpp<br>
cfe/trunk/test/SemaCXX/PR10177.cpp<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=214192&r1=214191&r2=214192&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=214192&r1=214191&r2=214192&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jul 29 13:44:19 2014<br>
@@ -12439,6 +12439,8 @@ static void DoMarkVarDeclReferenced(Sema<br>
"Invalid Expr argument to DoMarkVarDeclReferenced");<br>
Var->setReferenced();<br>
<br>
+ TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();<br>
+<br>
// If the context is not potentially evaluated, this is not an odr-use and<br>
// does not trigger instantiation.<br>
if (!IsPotentiallyEvaluatedContext(SemaRef)) {<br>
@@ -12453,25 +12455,26 @@ static void DoMarkVarDeclReferenced(Sema<br>
// arguments, where local variables can't be used.<br>
const bool RefersToEnclosingScope =<br>
(SemaRef.CurContext != Var->getDeclContext() &&<br>
- Var->getDeclContext()->isFunctionOrMethod() &&<br>
- Var->hasLocalStorage());<br>
- if (!RefersToEnclosingScope)<br>
- return;<br>
-<br>
- if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {<br>
- // If a variable could potentially be odr-used, defer marking it so<br>
- // until we finish analyzing the full expression for any lvalue-to-rvalue<br>
- // or discarded value conversions that would obviate odr-use.<br>
- // Add it to the list of potential captures that will be analyzed<br>
- // later (ActOnFinishFullExpr) for eventual capture and odr-use marking<br>
- // unless the variable is a reference that was initialized by a constant<br>
- // expression (this will never need to be captured or odr-used).<br>
- assert(E && "Capture variable should be used in an expression.");<br>
- if (!Var->getType()->isReferenceType() ||<br>
- !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))<br>
- LSI->addPotentialCapture(E->IgnoreParens());<br>
+ Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage());<br>
+ if (RefersToEnclosingScope) {<br>
+ if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {<br>
+ // If a variable could potentially be odr-used, defer marking it so<br>
+ // until we finish analyzing the full expression for any<br>
+ // lvalue-to-rvalue<br>
+ // or discarded value conversions that would obviate odr-use.<br>
+ // Add it to the list of potential captures that will be analyzed<br>
+ // later (ActOnFinishFullExpr) for eventual capture and odr-use marking<br>
+ // unless the variable is a reference that was initialized by a constant<br>
+ // expression (this will never need to be captured or odr-used).<br>
+ assert(E && "Capture variable should be used in an expression.");<br>
+ if (!Var->getType()->isReferenceType() ||<br>
+ !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))<br>
+ LSI->addPotentialCapture(E->IgnoreParens());<br>
+ }<br>
}<br>
- return;<br>
+<br>
+ if (!isTemplateInstantiation(TSK))<br>
+ return;<br></blockquote><div><br></div><div>Should we really mark the variable as odr-used in this case but not for non-template-instantiations? That inconsistency doesn't seem right to me. I think the right behavior here is to *only* perform the instantiation and to skip the marking as odr-used. In particular, for a case like:</div>
<div><br></div><div> namespace { template<typename> extern int n; }</div><div> template<typename T> int g() { return n<int>; }<br></div><div><br></div><div>... we should *not* produce a "variable '(anonymous namespace)::n<int>' has internal linkage but is not defined" warning.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
}<br>
<br>
VarTemplateSpecializationDecl *VarSpec =<br>
@@ -12483,7 +12486,6 @@ static void DoMarkVarDeclReferenced(Sema<br>
// templates of class templates, and variable template specializations. Delay<br>
// instantiations of variable templates, except for those that could be used<br>
// in a constant expression.<br>
- TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();<br>
if (isTemplateInstantiation(TSK)) {<br>
bool TryInstantiating = TSK == TSK_ImplicitInstantiation;<br>
<br>
<br>
Modified: cfe/trunk/test/SemaCXX/PR10177.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR10177.cpp?rev=214192&r1=214191&r2=214192&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR10177.cpp?rev=214192&r1=214191&r2=214192&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/PR10177.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/PR10177.cpp Tue Jul 29 13:44:19 2014<br>
@@ -9,22 +9,28 @@ struct U {<br>
static int a;<br>
};<br>
<br>
-template<int N> struct S; // expected-note 2{{here}}<br>
+template<int N> struct S; // expected-note 6{{here}}<br>
<br>
template<int N><br>
-int U<N>::a = S<N>::kError; // expected-error 2{{undefined}}<br>
+int U<N>::a = S<N>::kError; // expected-error 6{{undefined}}<br>
<br>
template<typename T><br>
void f() {<br>
- // FIXME: The standard suggests that U<0>::a is odr-used by this expression,<br>
- // but it's not entirely clear that's the right behaviour.<br>
- (void)alias_ref<int, int&, U<0>::a>();<br>
+ (void)alias_ref<int, int&, U<0>::a>(); // expected-note {{here}}<br>
(void)func_ref<int, int&, U<1>::a>(); // expected-note {{here}}<br>
(void)class_ref<int, int&, U<2>::a>(); // expected-note {{here}}<br>
};<br>
<br>
+template<int N><br>
+void fi() {<br>
+ (void)alias_ref<int, int&, U<N>::a>(); // expected-note {{here}}<br>
+ (void)func_ref<int, int&, U<N+1>::a>(); // expected-note {{here}}<br>
+ (void)class_ref<int, int&, U<N+2>::a>(); // expected-note {{here}}<br>
+};<br>
+<br>
int main() {<br>
- f<int>(); // expected-note 2{{here}}<br>
+ f<int>(); // NOTE: Non-dependent name uses are type-checked at template definition time.<br>
+ fi<10>(); // expected-note 3{{here}}<br>
}<br>
<br>
namespace N {<br>
@@ -38,3 +44,4 @@ namespace N {<br>
}<br>
int j = f<int>();<br>
}<br>
+<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>