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 15:32:55 PDT 2014


Ok.


On Tue, Jul 29, 2014 at 2:35 PM, Richard Smith <richard at metafoo.co.uk>
wrote:

> 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/5bcffc74/attachment.html>


More information about the cfe-commits mailing list