summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2008-06-09 05:05:07 +0000
committerEli Friedman <eli.friedman@gmail.com>2008-06-09 05:05:07 +0000
commite6e0f23a29223d4c51a14efd0c0af3fe58261672 (patch)
tree7dc04dad7486cec24c87237417b4d6ff67ff7d6b /clang/lib/Sema/SemaDecl.cpp
parente30c937df3f3ca2aa1de0fafebd24c9133f4f197 (diff)
downloadbcm5719-llvm-e6e0f23a29223d4c51a14efd0c0af3fe58261672.tar.gz
bcm5719-llvm-e6e0f23a29223d4c51a14efd0c0af3fe58261672.zip
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". llvm-svn: 52120
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ed34f9fe00d..1b1e636a761 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/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<ParenExpr>(E);
+ return FindExpressionBaseAddressLValue(PE->getSubExpr());
+ }
+ case Expr::MemberExprClass: {
+ const MemberExpr *M = cast<MemberExpr>(E);
+ if (M->isArrow())
+ return FindExpressionBaseAddress(M->getBase());
+ return FindExpressionBaseAddressLValue(M->getBase());
+ }
+ case Expr::ArraySubscriptExprClass: {
+ const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(E);
+ return FindExpressionBaseAddress(ASE->getBase());
+ }
+ case Expr::UnaryOperatorClass: {
+ const UnaryOperator *Exp = cast<UnaryOperator>(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<ParenExpr>(E);
+ return FindExpressionBaseAddress(PE->getSubExpr());
+ }
+ case Expr::UnaryOperatorClass: {
+ const UnaryOperator *Exp = cast<UnaryOperator>(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<BinaryOperator>(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<ImplicitCastExpr>(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<CastExpr>(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;
OpenPOWER on IntegriCloud