diff --git a/clang/AST/Expr.cpp b/clang/AST/Expr.cpp index 61e997da27ff..986f0ad95f6b 100644 --- a/clang/AST/Expr.cpp +++ b/clang/AST/Expr.cpp @@ -929,47 +929,36 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, 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(exp)) { - return getNullPointerConstantExpr(CE->getSubExpr()); - } else if (const ImplicitCastExpr *ICE = dyn_cast(exp)) { - return getNullPointerConstantExpr(ICE->getSubExpr()); - } else if (const ParenExpr *PE = dyn_cast(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 { - const CastExpr *CE = dyn_cast(this); - const Expr *e = getNullPointerConstantExpr(this); - - if (CE) { - bool castToVoidStar = false; - // Check if the highest precedence cast is "void *". + // Strip off a cast to void*, if it exists. + if (const CastExpr *CE = dyn_cast(this)) { + // Check that it is a cast to void*. if (const PointerType *PT = dyn_cast(CE->getType())) { QualType Pointee = PT->getPointeeType(); - if (Pointee.getQualifiers() == 0 && Pointee->isVoidType()) - castToVoidStar = true; + if (Pointee.getQualifiers() == 0 && Pointee->isVoidType() && // to void* + CE->getSubExpr()->getType()->isIntegerType()) // from int. + return CE->getSubExpr()->isNullPointerConstant(Ctx); } - // 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; + } else if (const ImplicitCastExpr *ICE = dyn_cast(this)) { + // Ignore the ImplicitCastExpr type entirely. + return ICE->getSubExpr()->isNullPointerConstant(Ctx); + } else if (const ParenExpr *PE = dyn_cast(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()) + 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 e->isIntegerConstantExpr(Val, Ctx, 0, true) && Val == 0; + return isIntegerConstantExpr(Val, Ctx, 0, true) && Val == 0; } unsigned OCUVectorElementExpr::getNumElements() const { diff --git a/clang/test/Sema/conditional-expr.c b/clang/test/Sema/conditional-expr.c index 24e71153f19f..c7c6ff242c76 100644 --- a/clang/test/Sema/conditional-expr.c +++ b/clang/test/Sema/conditional-expr.c @@ -1,8 +1,8 @@ // RUN: clang -fsyntax-only -verify -pedantic %s void foo() { *(0 ? (double *)0 : (void *)0) = 0; - *(0 ? (double *)0 : (void *)(int *)0) = 0; - *(0 ? (double *)0 : (void *)(double *)0) = 0; + *(0 ? (double *)0 : (void *)(int *)0) = 0; // expected-error {{incomplete type 'void' is not assignable}} + *(0 ? (double *)0 : (void *)(double *)0) = 0; // expected-error {{incomplete type 'void' is not assignable}} *(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}}