aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-06-30 17:15:34 +0000
committerJohn McCall <rjmccall@apple.com>2011-06-30 17:15:34 +0000
commitea4aba0e97ca71369a0f6e287443b670cf5c353f (patch)
treebc16866b8a4be69ec04110b5d0510e7ffa8ddc10
parent0e3d76c8d7fe78219a247478a0617b182de171d7 (diff)
Perform lvalue-to-rvalue conversions on both operands of ->*
and the RHS of .*. Noticed by Enea Zaffanella! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134170 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaExprCXX.cpp14
-rw-r--r--test/SemaCXX/member-pointer.cpp16
2 files changed, 30 insertions, 0 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 100681df5e..8dc9ceef9f 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -3168,6 +3168,20 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex,
ExprValueKind &VK,
SourceLocation Loc,
bool isIndirect) {
+ assert(!lex.get()->getType()->isPlaceholderType() &&
+ !rex.get()->getType()->isPlaceholderType() &&
+ "placeholders should have been weeded out by now");
+
+ // The LHS undergoes lvalue conversions if this is ->*.
+ if (isIndirect) {
+ lex = DefaultLvalueConversion(lex.take());
+ if (lex.isInvalid()) return QualType();
+ }
+
+ // The RHS always undergoes lvalue conversions.
+ rex = DefaultLvalueConversion(rex.take());
+ if (rex.isInvalid()) return QualType();
+
const char *OpSpelling = isIndirect ? "->*" : ".*";
// C++ 5.5p2
// The binary operator .* [p3: ->*] binds its second operand, which shall
diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp
index de3b211acf..cf6481015a 100644
--- a/test/SemaCXX/member-pointer.cpp
+++ b/test/SemaCXX/member-pointer.cpp
@@ -296,3 +296,19 @@ namespace PR9973 {
mem_fn(&test::nullary_v)(t); // expected-note{{in instantiation of}}
}
}
+
+namespace test8 {
+ struct A { int foo; };
+ int test1() {
+ // Verify that we perform (and check) an lvalue conversion on the operands here.
+ return (*((A**) 0)) // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
+ ->**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
+ }
+
+ int test2() {
+ // Verify that we perform (and check) an lvalue conversion on the operands here.
+ // TODO: the .* should itself warn about being a dereference of null.
+ return (*((A*) 0))
+ .**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
+ }
+}