aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-11-22 02:49:43 +0000
committerJohn McCall <rjmccall@apple.com>2009-11-22 02:49:43 +0000
commitb681b61fea36618778b8030360e90e3f4641233b (patch)
treeb319c2d05c7bede36cd63b6e1bcf48b261c8f8b6
parent5b3f9130b95c0b73b74a8835d428b1e89397e066 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89578 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Parse/ParseExprCXX.cpp18
-rw-r--r--lib/Sema/SemaExpr.cpp5
-rw-r--r--test/SemaCXX/member-pointers-2.cpp36
3 files changed, 58 insertions, 1 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index a57d718d48..56484720db 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f2ff6b6101..fd79935fbd 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/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/test/SemaCXX/member-pointers-2.cpp b/test/SemaCXX/member-pointers-2.cpp
new file mode 100644
index 0000000000..fea1d74b02
--- /dev/null
+++ b/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();
+}