From 4caf055b9f08416d956590358796a1ed464b73f7 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Mon, 9 Jun 2008 05:05:07 +0000 Subject: [PATCH] Add code to make test/CodeGen/struct-init.c work correctly without the pointer cast hack currently in isIntegerConstantExpr (in lib/AST/Expr.cpp). Also removes an odd test that even gcc doesn't accept. The reason the pointer cast hack is relevant here is that it makes Sema end up misinterpreting the relevant expression as a null pointer constant. The reason for this patch is that I plan to remove the pointer cast hack sometime soon because it causes strange issues, especially in its current form; see my recent email to cfe-dev "[PATCH] add constant expression evaluation to the AST and fix PR2413". git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52120 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 105 +++++++++++++++++++++++++++++++++++++ test/CodeGen/struct-init.c | 1 - 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ed34f9fe00..1b1e636a76 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -935,6 +935,97 @@ bool Sema::CheckAddressConstantExpression(const Expr* Init) { } } +static const Expr* FindExpressionBaseAddress(const Expr* E); + +static const Expr* FindExpressionBaseAddressLValue(const Expr* E) { + switch (E->getStmtClass()) { + default: + return E; + case Expr::ParenExprClass: { + const ParenExpr* PE = cast(E); + return FindExpressionBaseAddressLValue(PE->getSubExpr()); + } + case Expr::MemberExprClass: { + const MemberExpr *M = cast(E); + if (M->isArrow()) + return FindExpressionBaseAddress(M->getBase()); + return FindExpressionBaseAddressLValue(M->getBase()); + } + case Expr::ArraySubscriptExprClass: { + const ArraySubscriptExpr *ASE = cast(E); + return FindExpressionBaseAddress(ASE->getBase()); + } + case Expr::UnaryOperatorClass: { + const UnaryOperator *Exp = cast(E); + + if (Exp->getOpcode() == UnaryOperator::Deref) + return FindExpressionBaseAddress(Exp->getSubExpr()); + + return E; + } + } +} + +static const Expr* FindExpressionBaseAddress(const Expr* E) { + switch (E->getStmtClass()) { + default: + return E; + case Expr::ParenExprClass: { + const ParenExpr* PE = cast(E); + return FindExpressionBaseAddress(PE->getSubExpr()); + } + case Expr::UnaryOperatorClass: { + const UnaryOperator *Exp = cast(E); + + // C99 6.6p9 + if (Exp->getOpcode() == UnaryOperator::AddrOf) + return FindExpressionBaseAddressLValue(Exp->getSubExpr()); + + if (Exp->getOpcode() == UnaryOperator::Extension) + return FindExpressionBaseAddress(Exp->getSubExpr()); + + return E; + } + case Expr::BinaryOperatorClass: { + const BinaryOperator *Exp = cast(E); + + Expr *PExp = Exp->getLHS(); + Expr *IExp = Exp->getRHS(); + if (IExp->getType()->isPointerType()) + std::swap(PExp, IExp); + + return FindExpressionBaseAddress(PExp); + } + case Expr::ImplicitCastExprClass: { + const Expr* SubExpr = cast(E)->getSubExpr(); + + // Check for implicit promotion + if (SubExpr->getType()->isFunctionType() || + SubExpr->getType()->isArrayType()) + return FindExpressionBaseAddressLValue(SubExpr); + + // Check for pointer->pointer cast + if (SubExpr->getType()->isPointerType()) + return FindExpressionBaseAddress(SubExpr); + + // We assume that we have an arithmetic expression here; + // if we don't, we'll figure it out later + return 0; + } + case Expr::CastExprClass: { + const Expr* SubExpr = cast(E)->getSubExpr(); + + // Check for pointer->pointer cast + if (SubExpr->getType()->isPointerType()) + return FindExpressionBaseAddress(SubExpr); + + // We assume that we have an arithmetic expression here; + // if we don't, we'll figure it out later + return 0; + } + } +} + bool Sema::CheckArithmeticConstantExpression(const Expr* Init) { switch (Init->getStmtClass()) { default: @@ -1027,6 +1118,20 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) { CheckArithmeticConstantExpression(Exp->getRHS()); } + if (Exp->getLHS()->getType()->isPointerType() && + Exp->getRHS()->getType()->isPointerType()) { + const Expr* LHSBase = FindExpressionBaseAddress(Exp->getLHS()); + const Expr* RHSBase = FindExpressionBaseAddress(Exp->getRHS()); + + // Only allow a null (constant integer) base; we could + // allow some additional cases if necessary, but this + // is sufficient to cover offsetof-like constructs. + if (!LHSBase && !RHSBase) { + return CheckAddressConstantExpression(Exp->getLHS()) || + CheckAddressConstantExpression(Exp->getRHS()); + } + } + Diag(Init->getExprLoc(), diag::err_init_element_not_constant, Init->getSourceRange()); return true; diff --git a/test/CodeGen/struct-init.c b/test/CodeGen/struct-init.c index 5b815de399..02cbee06b0 100644 --- a/test/CodeGen/struct-init.c +++ b/test/CodeGen/struct-init.c @@ -9,5 +9,4 @@ char a; const zend_ini_entry ini_entries[] = { { ((char*)&((zend_ini_entry*)0)->mh_arg1 - (char*)(void*)0)}, - { ((long long*)&a - (long long*)(void*)2)}, }; -- 2.40.0