From: Eli Friedman Date: Mon, 25 Aug 2008 20:46:57 +0000 (+0000) Subject: Fix for PR2720; be a little bit more permissive in initializers for X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c3f07644a7846ac6fa8d952afcec7649a48213c4;p=clang Fix for PR2720; be a little bit more permissive in initializers for casting pointers to integers. Eventually, we should check whether we can evaluate an expression using Expr::tryEvaluate, and this codepath should be tightened to only handle standard-compliant cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55331 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d8d77b0d54..066969ce9e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -927,35 +927,37 @@ bool Sema::CheckAddressConstantExpression(const Expr* Init) { return CheckAddressConstantExpression(PExp) || CheckArithmeticConstantExpression(IExp); } - case Expr::ImplicitCastExprClass: { - const Expr* SubExpr = cast(Init)->getSubExpr(); - - // Check for implicit promotion - if (SubExpr->getType()->isFunctionType() || - SubExpr->getType()->isArrayType()) - return CheckAddressConstantExpressionLValue(SubExpr); - - // Check for pointer->pointer cast - if (SubExpr->getType()->isPointerType()) - return CheckAddressConstantExpression(SubExpr); - - if (SubExpr->getType()->isArithmeticType()) - return CheckArithmeticConstantExpression(SubExpr); - - Diag(Init->getExprLoc(), - diag::err_init_element_not_constant, Init->getSourceRange()); - return true; - } + case Expr::ImplicitCastExprClass: case Expr::ExplicitCastExprClass: { const Expr* SubExpr = cast(Init)->getSubExpr(); + if (Init->getStmtClass() == Expr::ImplicitCastExprClass) { + // Check for implicit promotion + if (SubExpr->getType()->isFunctionType() || + SubExpr->getType()->isArrayType()) + return CheckAddressConstantExpressionLValue(SubExpr); + } // Check for pointer->pointer cast if (SubExpr->getType()->isPointerType()) return CheckAddressConstantExpression(SubExpr); - // FIXME: Should we pedwarn for (int*)(0+0)? - if (SubExpr->getType()->isArithmeticType()) + if (SubExpr->getType()->isIntegralType()) { + // Check for the special-case of a pointer->int->pointer cast; + // this isn't standard, but some code requires it. See + // PR2720 for an example. + if (const CastExpr* SubCast = dyn_cast(SubExpr)) { + if (SubCast->getSubExpr()->getType()->isPointerType()) { + unsigned IntWidth = Context.getIntWidth(SubCast->getType()); + unsigned PointerWidth = Context.getTypeSize(Context.VoidPtrTy); + if (IntWidth >= PointerWidth) { + return CheckAddressConstantExpression(SubCast->getSubExpr()); + } + } + } + } + if (SubExpr->getType()->isArithmeticType()) { return CheckArithmeticConstantExpression(SubExpr); + } Diag(Init->getExprLoc(), diag::err_init_element_not_constant, Init->getSourceRange()); diff --git a/test/Sema/const-ptr-int-ptr-cast.c b/test/Sema/const-ptr-int-ptr-cast.c new file mode 100644 index 0000000000..6bf44b05b3 --- /dev/null +++ b/test/Sema/const-ptr-int-ptr-cast.c @@ -0,0 +1,3 @@ +// RUN: clang -fsyntax-only -verify %s + +char *a = (void*)(unsigned long long)(void*)&a;