diff options
| author | John McCall <rjmccall@apple.com> | 2009-11-22 02:49:43 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2009-11-22 02:49:43 +0000 |
| commit | a9ee325d719647a2bdee249d300153a9fc1753ee (patch) | |
| tree | 5cd58202b83b4584d0d9064f03c5cbe1167d0f66 | |
| parent | 663e0a06b02647e39fb3997a8cbfacab2e36760e (diff) | |
| download | bcm5719-llvm-a9ee325d719647a2bdee249d300153a9fc1753ee.tar.gz bcm5719-llvm-a9ee325d719647a2bdee249d300153a9fc1753ee.zip | |
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
| -rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 5 | ||||
| -rw-r--r-- | clang/test/SemaCXX/member-pointers-2.cpp | 36 |
3 files changed, 58 insertions, 1 deletions
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index a57d718d482..56484720db2 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -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); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f2ff6b6101e..fd79935fbd9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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())) { diff --git a/clang/test/SemaCXX/member-pointers-2.cpp b/clang/test/SemaCXX/member-pointers-2.cpp new file mode 100644 index 00000000000..fea1d74b025 --- /dev/null +++ b/clang/test/SemaCXX/member-pointers-2.cpp @@ -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(); +} |

