[cfe-commits] r69586 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/Sema/expr-address-of.c
Eli Friedman
eli.friedman at gmail.com
Mon Apr 20 01:23:18 PDT 2009
Author: efriedma
Date: Mon Apr 20 03:23:18 2009
New Revision: 69586
URL: http://llvm.org/viewvc/llvm-project?rev=69586&view=rev
Log:
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.
Modified:
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/Sema/expr-address-of.c
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=69586&r1=69585&r2=69586&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Apr 20 03:23:18 2009
@@ -1330,8 +1330,6 @@
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 @@
case Stmt::QualifiedDeclRefExprClass:
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 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<MemberExpr>(E)->isArrow())
return 0;
+ // Otherwise, the expression refers to a part of the base
return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
case Stmt::ArraySubscriptExprClass: {
- // &X[4] and &4[X] refers to X if X is not a pointer.
-
- NamedDecl *D = getPrimaryDecl(cast<ArraySubscriptExpr>(E)->getBase());
- ValueDecl *VD = dyn_cast_or_null<ValueDecl>(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<ArraySubscriptExpr>(E)->getBase();
+ if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Base)) {
+ if (ICE->getSubExpr()->getType()->isArrayType())
+ return getPrimaryDecl(ICE->getSubExpr());
+ }
+ return 0;
}
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.
- if (NamedDecl *D = getPrimaryDecl(UO->getSubExpr())) {
- ValueDecl *VD = dyn_cast<ValueDecl>(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 @@
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:
- // &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<ImplicitCastExpr>(E)->getSubExpr());
default:
return 0;
@@ -4024,6 +3998,9 @@
/// 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 @@
Expr::isLvalueResult lval = op->isLvalue(Context);
if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1
- if (!dcl || !isa<FunctionDecl>(dcl)) {// allow function designators
+ // The operand must be either an l-value or a function designator
+ if (!dcl || !isa<FunctionDecl>(dcl)) {
// FIXME: emit more specific diag...
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
<< op->getSourceRange();
return QualType();
}
- } else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(op)) { // C99 6.5.3.2p1
- if (FieldDecl *Field = dyn_cast<FieldDecl>(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<ExtVectorElementExpr>(op) || (isa<ArraySubscriptExpr>(op) &&
cast<ArraySubscriptExpr>(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();
Modified: cfe/trunk/test/Sema/expr-address-of.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/expr-address-of.c?rev=69586&r1=69585&r2=69586&view=diff
==============================================================================
--- cfe/trunk/test/Sema/expr-address-of.c (original)
+++ cfe/trunk/test/Sema/expr-address-of.c Mon Apr 20 03:23:18 2009
@@ -45,18 +45,21 @@
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 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);
+}
More information about the cfe-commits
mailing list