From 23d58ce9d103115fec4693285d0bcdbaccefea0f Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Mon, 20 Apr 2009 08:23:18 +0000 Subject: [PATCH] Some cleanup and bug-fixing for address-of checking. This causes a couple of minor accepts-invalid regressions, but we weren't really rejecting them for the right reason. We really need a more general solution to detect all the cases of the promotion of arrays with a register storage class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69586 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 73 ++++++++++++------------------------- test/Sema/expr-address-of.c | 19 ++++++++-- 2 files changed, 40 insertions(+), 52 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3eeadce453..5abe106bce 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1330,8 +1330,6 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) { if (V->isTypeDependent()) return Context.DependentTy; - - DefaultFunctionArrayConversion(V); // These operators return the element type of a complex type. if (const ComplexType *CT = V->getType()->getAsComplexType()) @@ -3952,35 +3950,27 @@ static NamedDecl *getPrimaryDecl(Expr *E) { case Stmt::QualifiedDeclRefExprClass: return cast(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 this is an arrow operator, the address is an offset from + // the base's value, so the object the base refers to is + // irrelevant. if (cast(E)->isArrow()) return 0; + // Otherwise, the expression refers to a part of the base return getPrimaryDecl(cast(E)->getBase()); case Stmt::ArraySubscriptExprClass: { - // &X[4] and &4[X] refers to X if X is not a pointer. - - NamedDecl *D = getPrimaryDecl(cast(E)->getBase()); - ValueDecl *VD = dyn_cast_or_null(D); - if (!VD || VD->getType()->isPointerType()) - return 0; - else - return VD; + // FIXME: This code shouldn't be necessary! We should catch the + // implicit promotion of register arrays earlier. + Expr* Base = cast(E)->getBase(); + if (ImplicitCastExpr* ICE = dyn_cast(Base)) { + if (ICE->getSubExpr()->getType()->isArrayType()) + return getPrimaryDecl(ICE->getSubExpr()); + } + return 0; } case Stmt::UnaryOperatorClass: { UnaryOperator *UO = cast(E); switch(UO->getOpcode()) { - case UnaryOperator::Deref: { - // *(X + 1) refers to X if X is not a pointer. - if (NamedDecl *D = getPrimaryDecl(UO->getSubExpr())) { - ValueDecl *VD = dyn_cast(D); - if (!VD || VD->getType()->isPointerType()) - return 0; - return VD; - } - return 0; - } case UnaryOperator::Real: case UnaryOperator::Imag: case UnaryOperator::Extension: @@ -3989,27 +3979,11 @@ static NamedDecl *getPrimaryDecl(Expr *E) { return 0; } } - case Stmt::BinaryOperatorClass: { - BinaryOperator *BO = cast(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(E)->getSubExpr()); case Stmt::ImplicitCastExprClass: - // &X[4] when X is an array, has an implicit cast from array to pointer. + // If the result of an implicit cast is an l-value, we care about + // the sub-expression; otherwise, the result here doesn't matter. return getPrimaryDecl(cast(E)->getSubExpr()); default: return 0; @@ -4024,6 +3998,9 @@ static NamedDecl *getPrimaryDecl(Expr *E) { /// In C++, the operand might be an overloaded function name, in which case /// we allow the '&' but retain the overloaded-function type. QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { + // Make sure to ignore parentheses in subsequent checks + op = op->IgnoreParens(); + if (op->isTypeDependent()) return Context.DependentTy; @@ -4042,23 +4019,21 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { Expr::isLvalueResult lval = op->isLvalue(Context); if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1 - if (!dcl || !isa(dcl)) {// allow function designators + // The operand must be either an l-value or a function designator + if (!dcl || !isa(dcl)) { // FIXME: emit more specific diag... Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) << op->getSourceRange(); return QualType(); } - } else if (MemberExpr *MemExpr = dyn_cast(op)) { // C99 6.5.3.2p1 - if (FieldDecl *Field = dyn_cast(MemExpr->getMemberDecl())) { - if (Field->isBitField()) { - Diag(OpLoc, diag::err_typecheck_address_of) - << "bit-field" << op->getSourceRange(); + } else if (op->isBitField()) { // C99 6.5.3.2p1 + // The operand cannot be a bit-field + Diag(OpLoc, diag::err_typecheck_address_of) + << "bit-field" << op->getSourceRange(); return QualType(); - } - } - // Check for Apple extension for accessing vector components. } else if (isa(op) || (isa(op) && cast(op)->getBase()->getType()->isVectorType())){ + // The operand cannot be an element of a vector Diag(OpLoc, diag::err_typecheck_address_of) << "vector element" << op->getSourceRange(); return QualType(); diff --git a/test/Sema/expr-address-of.c b/test/Sema/expr-address-of.c index b3ea9c5066..909acfb266 100644 --- a/test/Sema/expr-address-of.c +++ b/test/Sema/expr-address-of.c @@ -45,18 +45,21 @@ void f0() { int *_dummy1 = &(*(x1 + 1)); } +// FIXME: The checks for this function are broken; we should error +// on promoting a register array to a pointer! (C99 6.3.2.1p3) void f1() { register int x0[10]; - int *_dummy0 = &(*x0); // expected-error {{address of register variable requested}} + int *_dummy00 = x0; // fixme-error {{address of register variable requested}} + int *_dummy01 = &(*x0); // fixme-error {{address of register variable requested}} register int x1[10]; - int *_dummy1 = &(*(x1 + 1)); // expected-error {{address of register variable requested}} + int *_dummy1 = &(*(x1 + 1)); // fixme-error {{address of register variable requested}} register int *x2; int *_dummy2 = &(*(x2 + 1)); register int x3[10][10][10]; - int *_dummy3 = &x3[0][0]; // expected-error {{address of register variable requested}} + int (*_dummy3)[10] = &x3[0][0]; // expected-error {{address of register variable requested}} register struct { int f0[10]; } x4; int *_dummy4 = &x4.f0[2]; // expected-error {{address of register variable requested}} @@ -94,3 +97,13 @@ void f5() { void f6(register int x) { int * dummy0 = &x; // expected-error {{address of register variable requested}} } + +char* f7() { + register struct {char* x;} t1 = {"Hello"}; + char* dummy1 = &(t1.x[0]); + + struct {int a : 10;} t2; + int* dummy2 = &(t2.a); // expected-error {{address of bit-field requested}} + + void* t3 = &(*(void*)0); +} -- 2.40.0