aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-11-16 17:46:48 +0000
committerChris Lattner <sabre@nondot.org>2007-11-16 17:46:48 +0000
commitf82228f6ed2b4bb195a519afa777ba521b5c62df (patch)
tree5abc81727ba6db57e5d46e875bb8154e83fb25cf
parent825502a9ee613fdfb73b84cc85b9fdc58e680d86 (diff)
Tighten up address-of checking, implementing test/Sema/expr-address-of.c.
This fixes a bug reported by Seo Sanghyeon. This was meant to be committed yesterday, but the commit failed. doh. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44190 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Sema/SemaExpr.cpp15
-rw-r--r--test/Sema/expr-address-of.c15
2 files changed, 25 insertions, 5 deletions
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 416661ee6c..6c3b06e015 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -1520,15 +1520,21 @@ static Decl *getPrimaryDeclaration(Expr *e) {
case Stmt::DeclRefExprClass:
return cast<DeclRefExpr>(e)->getDecl();
case Stmt::MemberExprClass:
+ // Fields cannot be declared with a 'register' storage class.
+ // &X->f is always ok, even if X is declared register.
+ if (cast<MemberExpr>(e)->isArrow())
+ return 0;
return getPrimaryDeclaration(cast<MemberExpr>(e)->getBase());
case Stmt::ArraySubscriptExprClass:
+ // &X[4] and &4[X] is invalid if X is invalid.
return getPrimaryDeclaration(cast<ArraySubscriptExpr>(e)->getBase());
- case Stmt::CallExprClass:
- return getPrimaryDeclaration(cast<CallExpr>(e)->getCallee());
case Stmt::UnaryOperatorClass:
return getPrimaryDeclaration(cast<UnaryOperator>(e)->getSubExpr());
case Stmt::ParenExprClass:
return getPrimaryDeclaration(cast<ParenExpr>(e)->getSubExpr());
+ case Stmt::ImplicitCastExprClass:
+ // &X[4] when X is an array, has an implicit cast from array to pointer.
+ return getPrimaryDeclaration(cast<ImplicitCastExpr>(e)->getSubExpr());
default:
return 0;
}
@@ -1544,9 +1550,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
Expr::isLvalueResult lval = op->isLvalue();
if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1
- if (dcl && isa<FunctionDecl>(dcl)) // allow function designators
- ;
- else { // FIXME: emit more specific diag...
+ if (!dcl || !isa<FunctionDecl>(dcl)) {// allow function designators
+ // FIXME: emit more specific diag...
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof,
op->getSourceRange());
return QualType();
diff --git a/test/Sema/expr-address-of.c b/test/Sema/expr-address-of.c
new file mode 100644
index 0000000000..f085b6012a
--- /dev/null
+++ b/test/Sema/expr-address-of.c
@@ -0,0 +1,15 @@
+// RUN: clang %s -verify -fsyntax-only
+struct entry { int value; };
+void add_one(int *p) { (*p)++; }
+
+void test() {
+ register struct entry *p;
+ add_one(&p->value);
+}
+
+void foo() {
+ register int x[10];
+ &x[10]; // expected-error {{address of register variable requested}}
+}
+
+