The following code causes an assert in `SemaExprMember.cpp` on line 981
to fail:
```
struct A { };
struct B;
void f(A *x) {
x->B::y; // crash here
}
```
This happens because we only return early from
`BuildMemberReferenceExpr` when the `CXXScopeSpecifier` is invalid
_before_ the lookup is performed. Since the lookup may invalidate the
`CXXScopeSpecifier` (e.g. if the _nested-name-specifier_ is incomplete),
this results in the second `BuildMemberReferenceExpr` overload being
called with an invalid `CXXScopeSpecifier`, which causes the assert to
fail. This patch moves the early return for invalid `CXXScopeSpecifiers`
to occur _after_ lookup is performed. This fixes #92972.
I also removed the `if (SS.isSet() && SS.isInvalid())` check in
`ActOnMemberAccessExpr` because the condition can never be true (`isSet`
returns `getScopeRep() != nullptr` and `isInvalid` returns
`Range.isValid() && getScopeRep() == nullptr`).
17 lines
521 B
C++
17 lines
521 B
C++
// RUN: %clang_cc1 -verify -Wno-unused %s
|
|
|
|
struct A {
|
|
int y;
|
|
};
|
|
|
|
struct B; // expected-note 4{{forward declaration of 'B'}}
|
|
|
|
void f(A *a, B *b) {
|
|
a->B::x; // expected-error {{incomplete type 'B' named in nested name specifier}}
|
|
a->A::x; // expected-error {{no member named 'x' in 'A'}}
|
|
a->A::y;
|
|
b->B::x; // expected-error {{member access into incomplete type 'B'}}
|
|
b->A::x; // expected-error {{member access into incomplete type 'B'}}
|
|
b->A::y; // expected-error {{member access into incomplete type 'B'}}
|
|
}
|