forked from OSchip/llvm-project
If a C++ qualified id is followed by a postfix suffix, it is never the direct
operand of an addressof operator, and so we should not treat it as an abstract member-pointer expression and therefore suppress the implicit member access. This is really a well-formedness constraint on expressions: a DeclRefExpr of a FieldDecl or a non-static CXXMethodDecl (or template thereof, or unresolved collection thereof) should not be allowed in an arbitrary location in the AST. Arguably it shouldn't be allowed anywhere and we should have a different expr node type for this. But unfortunately we don't have a good way of enforcing this kind of constraint right now. llvm-svn: 89578
This commit is contained in:
parent
663e0a06b0
commit
a9ee325d71
|
@ -326,6 +326,24 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
|
|||
/*ObjectType=*/0,
|
||||
Name))
|
||||
return ExprError();
|
||||
|
||||
// This is only the direct operand of an & operator if it is not
|
||||
// followed by a postfix-expression suffix.
|
||||
if (isAddressOfOperand) {
|
||||
switch (Tok.getKind()) {
|
||||
case tok::l_square:
|
||||
case tok::l_paren:
|
||||
case tok::arrow:
|
||||
case tok::period:
|
||||
case tok::plusplus:
|
||||
case tok::minusminus:
|
||||
isAddressOfOperand = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
|
||||
isAddressOfOperand);
|
||||
|
|
|
@ -623,6 +623,9 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
|
|||
UnqualifiedId &Name,
|
||||
bool HasTrailingLParen,
|
||||
bool IsAddressOfOperand) {
|
||||
assert(!(IsAddressOfOperand && HasTrailingLParen) &&
|
||||
"cannot be direct & operand and have a trailing lparen");
|
||||
|
||||
if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(*this,
|
||||
Name.TemplateId->getTemplateArgs(),
|
||||
|
@ -856,7 +859,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
|||
// performance.
|
||||
if (!ADL) {
|
||||
bool isAbstractMemberPointer =
|
||||
(isAddressOfOperand && !HasTrailingLParen && SS && !SS->isEmpty());
|
||||
(isAddressOfOperand && SS && !SS->isEmpty());
|
||||
|
||||
if (!isAbstractMemberPointer && !Lookup.empty() &&
|
||||
isa<CXXRecordDecl>((*Lookup.begin())->getDeclContext())) {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// RUN: clang-cc -emit-llvm-only %s
|
||||
|
||||
// Tests that Sema properly creates member-access expressions for
|
||||
// these instead of bare FieldDecls.
|
||||
|
||||
struct Foo {
|
||||
int myvalue;
|
||||
|
||||
// We have to override these to get something with an lvalue result.
|
||||
int &operator++(int);
|
||||
int &operator--(int);
|
||||
};
|
||||
|
||||
struct Test0 {
|
||||
Foo memfoo;
|
||||
int memint;
|
||||
int memarr[10];
|
||||
Test0 *memptr;
|
||||
struct MemClass { int a; } memstruct;
|
||||
int &memfun();
|
||||
|
||||
void test() {
|
||||
int *p;
|
||||
p = &Test0::memfoo++;
|
||||
p = &Test0::memfoo--;
|
||||
p = &Test0::memarr[1];
|
||||
p = &Test0::memptr->memint;
|
||||
p = &Test0::memstruct.a;
|
||||
p = &Test0::memfun();
|
||||
}
|
||||
};
|
||||
|
||||
void test0() {
|
||||
Test0 mytest;
|
||||
mytest.test();
|
||||
}
|
Loading…
Reference in New Issue