AST contains "type-dependent" for non-dependency

Hi everyone,

I don’t understand why the AST for

template struct B {
int independent() {
return x[2];
}
std::array<int,3> x;

};

is

-ClassTemplateDecl 0x27faf20 <line:89:1, line:104:1> line:89:29 B

-NonTypeTemplateParmDecl 0x27fae20 <col:11, col:15> col:15 referenced ‘int’ Index
-CXXRecordDecl 0x27fae90 <col:22, line:104:1> line:89:29 struct B definition

-CXXRecordDecl 0x27fb1b8 <col:22, col:29> col:29 implicit struct B
-CXXMethodDecl 0x27fb2d0 <line:90:3, line:94:3> line:90:7 independent ‘int (void)’
-CompoundStmt 0x27fc430 <col:21, line:94:3> -ReturnStmt 0x27fc418 <line:91:5, col:16>
`-ArraySubscriptExpr 0x27fc3f0 <col:12, col:16> ‘’ lvalue

-MemberExpr 0x27fc378 col:12 ‘std::array<int, 3>’:‘struct std::array<int, 3>’ lvalue ->x 0x27fc318
-CXXThisExpr 0x27fc360 <col:12> 'B<Index> *' this -IntegerLiteral 0x27fc3b0 col:15 ‘int’ 2

Especially, why do we have the ArraySubscriptExpr ‘’?

When specializing to B<0>, the ArraySubscriptExpr becomes a CXXOperatorCallExpr as expected:

-ClassTemplateSpecializationDecl 0x27fc610 <line:89:1, line:104:1> line:89:29 struct B definition

-TemplateArgument integral 0
-CXXRecordDecl 0x27fc878 prev 0x27fc610 <col:22, col:29> col:29 implicit struct B
-CXXMethodDecl 0x27fc908 <line:90:3, line:94:3> line:90:7 used independent ‘int (void)’
-CompoundStmt 0x2800648 <col:21, line:94:3> -ReturnStmt 0x2800630 <line:91:5, col:16>
-ImplicitCastExpr 0x2800618 <col:12, col:16> 'int':'int' <LValueToRValue> -CXXOperatorCallExpr 0x28005d0 <col:12, col:16> ‘int’:‘int’ lvalue

-ImplicitCastExpr 0x28005b8 <col:12, col:16> ‘int &(*)(size_t)’
-DeclRefExpr 0x2800590 <col:12, col:16> 'int &(size_t)' lvalue CXXMethod 0x27fb870 'operator[]' 'int &(size_t)' -MemberExpr 0x2800540 <col:12> 'std::array<int, 3>':'struct std::array<int, 3>' lvalue ->x 0x27fca78 -CXXThisExpr 0x2800528 col:12 ‘struct B<0> *’ this
-ImplicitCastExpr 0x2800578 <col:14, col:15> 'size_t':'unsigned long' <IntegralCast> -IntegerLiteral 0x27fc3b0 col:15 ‘int’ 2

Why is the AST for the template and the specialization different? The method does not depend on the template parameter.

Thanks for any hints,

Matthias

Hi everyone,

I don't understand why the AST for

template <int Index> struct B {
  int independent() {
    return x[2];
  }
  std::array<int,3> x;
};

is

>-ClassTemplateDecl 0x27faf20 <line:89:1, line:104:1> line:89:29 B
> >-NonTypeTemplateParmDecl 0x27fae20 <col:11, col:15> col:15 referenced
'int' Index
> >-CXXRecordDecl 0x27fae90 <col:22, line:104:1> line:89:29 struct B
definition
> > >-CXXRecordDecl 0x27fb1b8 <col:22, col:29> col:29 implicit struct B
> > >-CXXMethodDecl 0x27fb2d0 <line:90:3, line:94:3> line:90:7 independent
'int (void)'
> > > `-CompoundStmt 0x27fc430 <col:21, line:94:3>
> > > `-ReturnStmt 0x27fc418 <line:91:5, col:16>
> > > `-ArraySubscriptExpr 0x27fc3f0 <col:12, col:16> '<dependent
>' lvalue
> > > >-MemberExpr 0x27fc378 <col:12> 'std::array<int, 3>':'struct
std::array<int, 3>' lvalue ->x 0x27fc318
> > > > `-CXXThisExpr 0x27fc360 <col:12> 'B<Index> *' this
> > > `-IntegerLiteral 0x27fc3b0 <col:15> 'int' 2

Especially, why do we have the ArraySubscriptExpr '<dependent type>'?

When specializing to B<0>, the ArraySubscriptExpr becomes a
CXXOperatorCallExpr as expected:

> >-ClassTemplateSpecializationDecl 0x27fc610 <line:89:1, line:104:1>
line:89:29 struct B definition
> > >-TemplateArgument integral 0
> > >-CXXRecordDecl 0x27fc878 prev 0x27fc610 <col:22, col:29> col:29
implicit struct B
> > >-CXXMethodDecl 0x27fc908 <line:90:3, line:94:3> line:90:7 used
independent 'int (void)'
> > > `-CompoundStmt 0x2800648 <col:21, line:94:3>
> > > `-ReturnStmt 0x2800630 <line:91:5, col:16>
> > > `-ImplicitCastExpr 0x2800618 <col:12, col:16> 'int':'int'
<LValueToRValue>
> > > `-CXXOperatorCallExpr 0x28005d0 <col:12, col:16> 'int':'int'
lvalue
> > > >-ImplicitCastExpr 0x28005b8 <col:12, col:16> 'int
&(*)(size_t)' <FunctionToPointerDecay>
> > > > `-DeclRefExpr 0x2800590 <col:12, col:16> 'int &(size_t)'
lvalue CXXMethod 0x27fb870 'operator' 'int &(size_t)'
> > > >-MemberExpr 0x2800540 <col:12> 'std::array<int, 3>':'struct
std::array<int, 3>' lvalue ->x 0x27fca78
> > > > `-CXXThisExpr 0x2800528 <col:12> 'struct B<0> *' this
> > > `-ImplicitCastExpr 0x2800578 <col:14, col:15>
'size_t':'unsigned long' <IntegralCast>
> > > `-IntegerLiteral 0x27fc3b0 <col:15> 'int' 2

Why is the AST for the template and the specialization different? The
method does not depend on the template parameter.

Yes, this is wrong; we don't correctly implement the type-dependence rules
for class member access expressions specified in core issue 224 (see
http://clang.llvm.org/cxx_dr_status.html#224, CWG Issue 224).

I proposed a patch for this here: https://reviews.llvm.org/D22476