aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp52
1 files changed, 47 insertions, 5 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 1f544927b7..8896f43539 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1968,8 +1968,16 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) {
/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
/// This routine allows us to typecheck complex/recursive expressions
-/// where the declaration is needed for type checking. Here are some
-/// examples: &s.xx, &s.zz[1].yy, &(1+2), &(XX), &"123"[2].
+/// where the declaration is needed for type checking. We only need to
+/// handle cases when the expression references a function designator
+/// or is an lvalue. Here are some examples:
+/// - &(x) => x
+/// - &*****f => f for f a function designator.
+/// - &s.xx => s
+/// - &s.zz[1].yy -> s, if zz is an array
+/// - *(x + 1) -> x, if x is an array
+/// - &"123"[2] -> 0
+/// - & __real__ x -> x
static ValueDecl *getPrimaryDecl(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass:
@@ -1981,7 +1989,7 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
return 0;
return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
case Stmt::ArraySubscriptExprClass: {
- // &X[4] and &4[X] is invalid if X is invalid and X is not a pointer.
+ // &X[4] and &4[X] refers to X if X is not a pointer.
ValueDecl *VD = getPrimaryDecl(cast<ArraySubscriptExpr>(E)->getBase());
if (!VD || VD->getType()->isPointerType())
@@ -1989,8 +1997,42 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
else
return VD;
}
- case Stmt::UnaryOperatorClass:
- return getPrimaryDecl(cast<UnaryOperator>(E)->getSubExpr());
+ case Stmt::UnaryOperatorClass: {
+ UnaryOperator *UO = cast<UnaryOperator>(E);
+
+ switch(UO->getOpcode()) {
+ case UnaryOperator::Deref: {
+ // *(X + 1) refers to X if X is not a pointer.
+ ValueDecl *VD = getPrimaryDecl(UO->getSubExpr());
+ if (!VD || VD->getType()->isPointerType())
+ return 0;
+ return VD;
+ }
+ case UnaryOperator::Real:
+ case UnaryOperator::Imag:
+ case UnaryOperator::Extension:
+ return getPrimaryDecl(UO->getSubExpr());
+ default:
+ return 0;
+ }
+ }
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperator *BO = cast<BinaryOperator>(E);
+
+ // Handle cases involving pointer arithmetic. The result of an
+ // Assign or AddAssign is not an lvalue so they can be ignored.
+
+ // (x + n) or (n + x) => x
+ if (BO->getOpcode() == BinaryOperator::Add) {
+ if (BO->getLHS()->getType()->isPointerType()) {
+ return getPrimaryDecl(BO->getLHS());
+ } else if (BO->getRHS()->getType()->isPointerType()) {
+ return getPrimaryDecl(BO->getRHS());
+ }
+ }
+
+ return 0;
+ }
case Stmt::ParenExprClass:
return getPrimaryDecl(cast<ParenExpr>(E)->getSubExpr());
case Stmt::ImplicitCastExprClass: