[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