diff options
author | Chris Lattner <sabre@nondot.org> | 2007-11-16 17:46:48 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-11-16 17:46:48 +0000 |
commit | f82228f6ed2b4bb195a519afa777ba521b5c62df (patch) | |
tree | 5abc81727ba6db57e5d46e875bb8154e83fb25cf | |
parent | 825502a9ee613fdfb73b84cc85b9fdc58e680d86 (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.cpp | 15 | ||||
-rw-r--r-- | test/Sema/expr-address-of.c | 15 |
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}} +} + + |