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.
Richard Smith
richard at metafoo.co.uk
Tue Jul 29 14:35:40 PDT 2014
On Tue, Jul 29, 2014 at 11:44 AM, Larisse Voufo <lvoufo at google.com> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140729/0fa5846d/attachment.html>
More information about the cfe-commits
mailing list