summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-11-13 00:03:19 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-11-13 00:03:19 +0000
commitc7ec5fcf24308e6151845e9c3e8740f7c8682e06 (patch)
tree8e2915241387c68e0422712972ab9aa0d51d578c
parente9c16a6a7939001b3cf1758335c4c4cf5277ebe4 (diff)
downloadbcm5719-llvm-c7ec5fcf24308e6151845e9c3e8740f7c8682e06.tar.gz
bcm5719-llvm-c7ec5fcf24308e6151845e9c3e8740f7c8682e06.zip
Fix bug in constant evaluation exposed by 176.gcc.
- Evaluation of , operator used bogus assumption that LHS could be evaluated as an integral expression even though its type is unspecified. This change is making isICE very permissive of the LHS in non-evaluated contexts because it is not clear what predicate we would use to reject code here. The standard didn't offer me any guidance; opinions? llvm-svn: 59196
-rw-r--r--clang/lib/AST/Expr.cpp34
-rw-r--r--clang/lib/AST/ExprConstant.cpp48
-rw-r--r--clang/test/Sema/const-eval.c2
3 files changed, 52 insertions, 32 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index c54fc40ecb2..e9903df6128 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -870,10 +870,26 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
const BinaryOperator *Exp = cast<BinaryOperator>(this);
llvm::APSInt LHS, RHS;
+ // Comma operator requires special handling.
+ if (Exp->getOpcode() == BinaryOperator::Comma) {
+ // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
+ // *except* when they are contained within a subexpression that is not
+ // evaluated". Note that Assignment can never happen due to constraints
+ // on the LHS subexpr, so we don't need to check it here.
+ if (isEvaluated) {
+ if (Loc) *Loc = getLocStart();
+ return false;
+ }
+
+ // The result of the constant expr is the RHS.
+ return Exp->getRHS()->isIntegerConstantExpr(Result, Ctx, Loc,
+ isEvaluated);
+ }
+
// Initialize result to have correct signedness and width.
Result = llvm::APSInt(static_cast<uint32_t>(Ctx.getTypeSize(getType())),
- !getType()->isSignedIntegerType());
-
+ !getType()->isSignedIntegerType());
+
// The LHS of a constant expr is always evaluated and needed.
if (!Exp->getLHS()->isIntegerConstantExpr(LHS, Ctx, Loc, isEvaluated))
return false;
@@ -945,20 +961,6 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
case BinaryOperator::LOr:
Result = LHS != 0 || RHS != 0;
break;
-
- case BinaryOperator::Comma:
- // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
- // *except* when they are contained within a subexpression that is not
- // evaluated". Note that Assignment can never happen due to constraints
- // on the LHS subexpr, so we don't need to check it here.
- if (isEvaluated) {
- if (Loc) *Loc = getLocStart();
- return false;
- }
-
- // The result of the constant expr is the RHS.
- Result = RHS;
- return true;
}
assert(!Exp->isAssignmentOp() && "LHS can't be a constant expr!");
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d6a4094520d..f5477f30b30 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -376,6 +376,7 @@ public:
}
bool VisitDeclRefExpr(const DeclRefExpr *E);
bool VisitCallExpr(const CallExpr *E);
+ bool VisitBinOpComma(const BinaryOperator *E);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitUnaryOperator(const UnaryOperator *E);
@@ -480,7 +481,37 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
}
+bool IntExprEvaluator::VisitBinOpComma(const BinaryOperator *E) {
+ llvm::APSInt RHS(32);
+
+ // Require that we be able to evaluate the LHS.
+ if (!E->getLHS()->isEvaluatable(Info.Ctx))
+ return false;
+
+ bool OldEval = Info.isEvaluated;
+ if (!EvaluateInteger(E->getRHS(), RHS, Info))
+ return false;
+ Info.isEvaluated = OldEval;
+
+ // Result of the comma is just the result of the RHS.
+ Result = RHS;
+
+ // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
+ // *except* when they are contained within a subexpression that is not
+ // evaluated". Note that Assignment can never happen due to constraints
+ // on the LHS subexpr, so we don't need to check it here.
+ if (!Info.isEvaluated)
+ return true;
+
+ // If the value is evaluated, we can accept it as an extension.
+ return Extension(E->getOperatorLoc(), diag::ext_comma_in_constant_expr);
+}
+
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ // Comma operator requires special handling.
+ if (E->getOpcode() == BinaryOperator::Comma)
+ return VisitBinOpComma(E);
+
// The LHS of a constant expr is always evaluated and needed.
llvm::APSInt RHS(32);
if (!Visit(E->getLHS())) {
@@ -585,22 +616,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Result = Result != 0 || RHS != 0;
Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
break;
-
-
- case BinaryOperator::Comma:
- // Result of the comma is just the result of the RHS.
- Result = RHS;
-
- // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
- // *except* when they are contained within a subexpression that is not
- // evaluated". Note that Assignment can never happen due to constraints
- // on the LHS subexpr, so we don't need to check it here.
- if (!Info.isEvaluated)
- return true;
-
- // If the value is evaluated, we can accept it as an extension.
- return Extension(E->getOperatorLoc(), diag::ext_comma_in_constant_expr);
- }
+}
Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
return true;
diff --git a/clang/test/Sema/const-eval.c b/clang/test/Sema/const-eval.c
index f42ed2504b1..c808b4818f7 100644
--- a/clang/test/Sema/const-eval.c
+++ b/clang/test/Sema/const-eval.c
@@ -11,3 +11,5 @@ struct y {int x,y;};
EVAL_EXPR(6, (int)(1+(struct y*)0))
EVAL_EXPR(7, (int)&((struct y*)0)->y)
EVAL_EXPR(8, (_Bool)"asdf")
+void g0(void);
+EVAL_EXPR(9, (g0(), 12)) // expected-error {{fields must have a constant size}}
OpenPOWER on IntegriCloud