Ok.
On Tue, Jul 29, 2014 at 2:35 PM, Richard Smith <[email protected]> wrote: > On Tue, Jul 29, 2014 at 11:44 AM, Larisse Voufo <[email protected]> wrote: > >> 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; >> > > 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: > > namespace { template<typename> extern int n; } > template<typename T> int g() { return n<int>; } > > ... we should *not* produce a "variable '(anonymous namespace)::n<int>' > has internal linkage but is not defined" warning. > > } >> >> 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>(); >> } >> + >> >> >> _______________________________________________ >> cfe-commits mailing list >> [email protected] >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> > >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
