This is an archive of the discontinued LLVM Phabricator instance.

[AST] Make MemberExpr non-dependent according to core issue 224
AbandonedPublic

Authored by mgehre on Jul 18 2016, 2:03 PM.

Details

Summary

A MemberExpr is non-dependent if

  1. it is a member of the current instantiation
  2. the member is non-dependent

We check 1) by asserting that the base of the
MemberExpr is a CXXThisExpr. In addition,
the parent of the member needs to be the current
class or a base of it. (It can happen that the member
decl resolves to a member of an outer class, and later
on Sema prints an error about it. In this case, we keep
it type-dependent, and the error will only appear if it is
ODR-used.)

This changes makes clang reject certain source code that it previously accepted,
namely invalid use of members in functions that are never specialized
or ODR-used. The changes to the tests show examples of this.

Diff Detail

Event Timeline

mgehre updated this revision to Diff 64379.Jul 18 2016, 2:03 PM
mgehre retitled this revision from to [AST] Make MemberExpr non-dependent according to core issue 224.
mgehre updated this object.
mgehre added reviewers: klimek, aaron.ballman, rsmith.
mgehre added a subscriber: cfe-commits.
rsmith added inline comments.Jul 18 2016, 2:25 PM
lib/AST/Expr.cpp
1425

The language rule for this says nothing about the base being a this expression; there are many other ways in which a MemberExpr could name a member of the current instantiation.

In general, the base expression should have (pointer to) RecordType or InjectedClassNameType as its type (that is, getAsCXXRecordDecl() should succeed) in all cases except when the member access denotes a member of an unknown specialization.

1454

Please assert that ty is not a dependent type here.

mgehre updated this revision to Diff 64777.Jul 20 2016, 3:16 PM
  • Properly check for being member of current instantiation.
  • Add new testcase test/CXX/temp/temp.res/temp.dep/temp.dep.expr/p5.cpp
  • Added assert() according to review comment
rsmith added inline comments.Aug 9 2016, 5:36 PM
lib/AST/Expr.cpp
1414

You should presumably be checking isValueDependent here.

I also don't see any test changes covering the handling of this attribute, and it's not completely clear to me why a dependent enable_if attribute would cause a member to be treated as not being a member of the current instantiation. This should probably be grouped with the check for a member with a dependent type down on line 1458, not as part of the determination of whether we have a member of the current instantiation.

1426

The E->isTypeDependent() test should be in isMemberOfCurrentInstantiation -- right now, that function is determining whether we have a member of the current instantiation or a member of a non-dependent type.

1426–1428

Please clang-format this.

test/CXX/temp/temp.res/temp.dep/temp.dep.expr/p5.cpp
14–15 ↗(On Diff #64777)

Do you know why we don't diagnose this?

mgehre updated this revision to Diff 90591.Mar 4 2017, 2:15 PM
mgehre marked 4 inline comments as done.

Thanks for your comments! I'm very sorry for the huge delay. I have now more time to work on this.
I added all your comments to the commit
and fixed a crash in SemaChecking::RefersToMemberWithReducedAlignment,
when the base is an InjectedClassNameType (because it assumed that it can only be a RecordType).

lib/AST/Expr.cpp
1414

Thanks, I will move the check down.

A test for this is in test/SemaCXX/enable_if.cpp:

template <typename T> class C {
  void f() __attribute__((enable_if(T::expr == 0, ""))) {}
  void g() { f(); }
};

If I would not check for value dependent attributes, then the call to f would be considered non-type dependent and produce the warnings

error: 'error' diagnostics seen but not expected: 
  File test/SemaCXX/enable_if.cpp Line 116: no matching member function for call to 'f'
error: 'note' diagnostics seen but not expected: 
  File test/SemaCXX/enable_if.cpp Line 115: candidate disabled: <no message provided>
2 errors generated.

We need to keep f() type-dependent until the template is instantiated.

1426

I will move it there.

1426–1428

Sorry, done.

test/CXX/temp/temp.res/temp.dep/temp.dep.expr/p5.cpp
14–15 ↗(On Diff #64777)

This patch adds support for the MemberExpr, e.g.

i = j; // expected-error {{incompatible type}}

which before this patch had the AST

|   |   |-BinaryOperator 0x3449f50 <line:10:5, col:9> '<dependent type>' '='
|   |   | |-MemberExpr 0x3449ef0 <col:5> 'int *' lvalue ->i 0x3449950
|   |   | | `-CXXThisExpr 0x3449ed8 <col:5> 'A<T, I> *' this
|   |   | `-DeclRefExpr 0x3449f28 <col:9> 'char *' lvalue Var 0x3449e30 'j' 'char *'

Not yet fixed are CXXDependentScopeMemberExpr, i.e.

(*this).i = j;               // FIXME {{incompatible type}}
  |   |   | - BinaryOperator 0x8cfbd0 <line:12:5, col:17> '<dependent type>' '='
  |   |   | |-CXXDependentScopeMemberExpr 0x8cfb50 <col:5, col:13> '<dependent type>' lvalue .i
  |   |   | | `-ParenExpr 0x8cfb30 <col:5, col:11> '<dependent type>'
  |   |   | |   `-UnaryOperator 0x8cfb10 <col:6, col:7> '<dependent type>' prefix '*'
  |   |   | |     `-CXXThisExpr 0x8cfaf8 <col:7> 'A<T, I> *' this
  |   |   | `-DeclRefExpr 0x8cfba8 <col:17> 'char *' lvalue Var 0x8a5a08 'j' 'char *'
this->i = j;                 // FIXME {{incompatible type}}
  |   |   |-BinaryOperator 0x8cfc90 <line:13:5, col:15> '<dependent type>' '='
  |   |   | |-CXXDependentScopeMemberExpr 0x8cfc10 <col:5, col:11> '<dependent type>' lvalue ->i
  |   |   | | `-CXXThisExpr 0x8cfbf8 <col:5> 'A<T, I> *' this
  |   |   | `-DeclRefExpr 0x8cfc68 <col:15> 'char *' lvalue Var 0x8a5a08 'j' 'char *'
mgehre updated this revision to Diff 90592.Mar 4 2017, 2:59 PM

Updated fix for the crash in SemaChecking::RefersToMemberWithReducedAlignment,
so it also works for C code.

Friendly ping

mgehre abandoned this revision.May 13 2019, 12:36 PM