[cfe-commits] r45951 - in /cfe/trunk: AST/Expr.cpp test/Sema/conditional-expr.c

Steve Naroff snaroff at apple.com
Sun Jan 13 18:53:34 PST 2008


Author: snaroff
Date: Sun Jan 13 20:53:34 2008
New Revision: 45951

URL: http://llvm.org/viewvc/llvm-project?rev=45951&view=rev
Log:

Rewrite Expr::isNullPointerConstant() to deal with multiple levels of explicit casts.

Now, isNullPointerConstant() will return true for the following: "(void*)(double*)0"


Modified:
    cfe/trunk/AST/Expr.cpp
    cfe/trunk/test/Sema/conditional-expr.c

Modified: cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Expr.cpp?rev=45951&r1=45950&r2=45951&view=diff

==============================================================================
--- cfe/trunk/AST/Expr.cpp (original)
+++ cfe/trunk/AST/Expr.cpp Sun Jan 13 20:53:34 2008
@@ -929,37 +929,47 @@
   return true;
 }
 
+/// Helper function for isNullPointerConstant. This routine skips all
+/// explicit casts, implicit casts and paren expressions.
+const Expr * getNullPointerConstantExpr(const Expr *exp) {
+  if (const CastExpr *CE = dyn_cast<CastExpr>(exp)) {
+    return getNullPointerConstantExpr(CE->getSubExpr());
+  } else if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(exp)) {
+    return getNullPointerConstantExpr(ICE->getSubExpr());
+  } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(exp)) {
+    // Accept ((void*)0) as a null pointer constant, as many other
+    // implementations do.
+    return getNullPointerConstantExpr(PE->getSubExpr());
+  }
+  return exp;
+}
 
 /// isNullPointerConstant - C99 6.3.2.3p3 -  Return true if this is either an
 /// integer constant expression with the value zero, or if this is one that is
 /// cast to void*.
 bool Expr::isNullPointerConstant(ASTContext &Ctx) const {
-  // Strip off a cast to void*, if it exists.
-  if (const CastExpr *CE = dyn_cast<CastExpr>(this)) {
-    // Check that it is a cast to void*.
+  const CastExpr *CE = dyn_cast<CastExpr>(this);
+  const Expr *e = getNullPointerConstantExpr(this);
+  
+  if (CE) {
+    bool castToVoidStar = false;
+    // Check if the highest precedence cast is "void *".
     if (const PointerType *PT = dyn_cast<PointerType>(CE->getType())) {
       QualType Pointee = PT->getPointeeType();
-      if (Pointee.getQualifiers() == 0 && Pointee->isVoidType() && // to void*
-          CE->getSubExpr()->getType()->isIntegerType())            // from int.
-        return CE->getSubExpr()->isNullPointerConstant(Ctx);
+      if (Pointee.getQualifiers() == 0 && Pointee->isVoidType())
+        castToVoidStar = true;
     }
-  } else if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(this)) {
-    // Ignore the ImplicitCastExpr type entirely.
-    return ICE->getSubExpr()->isNullPointerConstant(Ctx);
-  } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(this)) {
-    // Accept ((void*)0) as a null pointer constant, as many other
-    // implementations do.
-    return PE->getSubExpr()->isNullPointerConstant(Ctx);
-  }
-  
-  // This expression must be an integer type.
-  if (!getType()->isIntegerType())
+    // This cast must be an integer type or void *.
+    if (!CE->getType()->isIntegerType() && !castToVoidStar)
+      return false;
+  } else if (!e->getType()->isIntegerType()) {
+    // This expression must be an integer type.
     return false;
-  
+  }
   // If we have an integer constant expression, we need to *evaluate* it and
   // test for the value 0.
   llvm::APSInt Val(32);
-  return isIntegerConstantExpr(Val, Ctx, 0, true) && Val == 0;
+  return e->isIntegerConstantExpr(Val, Ctx, 0, true) && Val == 0;
 }
 
 unsigned OCUVectorElementExpr::getNumElements() const {

Modified: cfe/trunk/test/Sema/conditional-expr.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/conditional-expr.c?rev=45951&r1=45950&r2=45951&view=diff

==============================================================================
--- cfe/trunk/test/Sema/conditional-expr.c (original)
+++ cfe/trunk/test/Sema/conditional-expr.c Sun Jan 13 20:53:34 2008
@@ -1,17 +1,21 @@
 // RUN: clang -fsyntax-only -verify -pedantic %s
 void foo() {
   *(0 ? (double *)0 : (void *)0) = 0;
-  *((void *) 0) = 0; // -expected-error {{incomplete type 'void' is not assignable}}
+  *(0 ? (double *)0 : (void *)(int *)0) = 0;
+  *(0 ? (double *)0 : (void *)(double *)0) = 0;
+  *(0 ? (double *)0 : (int *)(void *)0) = 0; // expected-warning {{pointer type mismatch ('double *' and 'int *')}}
+  *(0 ? (double *)0 : (double *)(void *)0) = 0;
+  *((void *) 0) = 0; // expected-error {{incomplete type 'void' is not assignable}}
   double *dp;
   int *ip;
   void *vp;
 
   dp = vp;
   vp = dp;
-  ip = dp; // -expected-warning {{incompatible pointer types assigning 'double *', expected 'int *'}}
-  dp = ip; // -expected-warning {{incompatible pointer types assigning 'int *', expected 'double *'}}
+  ip = dp; // expected-warning {{incompatible pointer types assigning 'double *', expected 'int *'}}
+  dp = ip; // expected-warning {{incompatible pointer types assigning 'int *', expected 'double *'}}
   dp = 0 ? (double *)0 : (void *)0;
   vp = 0 ? (double *)0 : (void *)0;
-  ip = 0 ? (double *)0 : (void *)0; // -expected-warning {{incompatible pointer types assigning 'double *', expected 'int *'}}
+  ip = 0 ? (double *)0 : (void *)0; // expected-warning {{incompatible pointer types assigning 'double *', expected 'int *'}}
 }
 





More information about the cfe-commits mailing list