[cfe-commits] r53499 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def lib/AST/ExprConstant.cpp
Chris Lattner
sabre at nondot.org
Fri Jul 11 17:14:42 PDT 2008
Author: lattner
Date: Fri Jul 11 19:14:42 2008
New Revision: 53499
URL: http://llvm.org/viewvc/llvm-project?rev=53499&view=rev
Log:
start remembering diagnostics for various cases, add some missing
code. Switch to Eli's getIntWidth method.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/AST/ExprConstant.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=53499&r1=53498&r2=53499&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri Jul 11 19:14:42 2008
@@ -526,6 +526,14 @@
// Semantic Analysis
//===----------------------------------------------------------------------===//
+// Constant expressions
+DIAG(err_expr_not_constant, ERROR,
+ "expression is invalid in a constant expression")
+DIAG(err_expr_divide_by_zero, ERROR,
+ "division by zero")
+DIAG(ext_comma_in_constant_expr, EXTENSION,
+ "C does not permit evaluated commas in constant expression")
+
// Semantic analysis of string and character constant literals.
DIAG(ext_nonstandard_escape, EXTENSION,
"use of non-standard escape character '\\%0'")
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=53499&r1=53498&r2=53499&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Fri Jul 11 19:14:42 2008
@@ -15,6 +15,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
@@ -72,13 +73,19 @@
/// if it is short-circuited (according to C rules).
bool isEvaluated;
- /// ICEDiag - If the expression is foldable, but the expression is not an
- /// integer constant expression, this contains the extension diagnostic to
- /// emit which describes why it isn't an integer constant expression. The
- /// caller can choose to emit this or not, depending on whether they require
- /// an i-c-e or not. DiagLoc indicates the caret position for the report.
+ /// ICEDiag - If the expression is unfoldable, then ICEDiag contains the
+ /// error diagnostic indicating why it is not foldable and DiagLoc indicates a
+ /// caret position for the error. If it is foldable, but the expression is
+ /// not an integer constant expression, ICEDiag contains the extension
+ /// diagnostic to emit which describes why it isn't an integer constant
+ /// expression. If this expression *is* an integer-constant-expr, then
+ /// ICEDiag is zero.
///
- /// If ICEDiag is zero, then this expression is an i-c-e.
+ /// The caller can choose to emit this diagnostic or not, depending on whether
+ /// they require an i-c-e or a constant or not. DiagLoc indicates the caret
+ /// position for the report.
+ ///
+ /// If ICEDiag is zero, then this expression is an i-c-e.
unsigned ICEDiag;
SourceLocation DiagLoc;
@@ -189,7 +196,24 @@
: Info(info), Result(result) {}
unsigned getIntTypeSizeInBits(QualType T) const {
- return (unsigned)Info.Ctx.getTypeSize(T);
+ return (unsigned)Info.Ctx.getIntWidth(T);
+ }
+
+ bool Extension(SourceLocation L, diag::kind D) {
+ Info.DiagLoc = L;
+ Info.ICEDiag = D;
+ return true; // still a constant.
+ }
+
+ bool Error(SourceLocation L, diag::kind D) {
+ // If this is in an unevaluated portion of the subexpression, ignore the
+ // error.
+ if (!Info.isEvaluated)
+ return true;
+
+ Info.DiagLoc = L;
+ Info.ICEDiag = D;
+ return false;
}
//===--------------------------------------------------------------------===//
@@ -197,10 +221,7 @@
//===--------------------------------------------------------------------===//
bool VisitStmt(Stmt *S) {
- // FIXME: Remove this when we support more expressions.
- printf("unhandled int expression");
- S->dump();
- return false;
+ return Error(S->getLocStart(), diag::err_expr_not_constant);
}
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
@@ -216,11 +237,19 @@
return HandleCast(E->getSubExpr(), E->getType());
}
bool VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
- return EvaluateSizeAlignOf(E->isSizeOf(),E->getArgumentType(),E->getType());
+ return EvaluateSizeAlignOf(E->isSizeOf(), E->getArgumentType(),
+ E->getType());
}
bool VisitIntegerLiteral(const IntegerLiteral *E) {
Result = E->getValue();
+ Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
+ return true;
+ }
+ bool VisitCharacterLiteral(const CharacterLiteral *E) {
+ Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
+ Result = E->getValue();
+ Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
return true;
}
private:
@@ -237,26 +266,41 @@
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// The LHS of a constant expr is always evaluated and needed.
llvm::APSInt RHS(32);
- if (!Visit(E->getLHS()) || !EvaluateInteger(E->getRHS(), RHS, Info))
+ if (!Visit(E->getLHS()))
+ return false; // error in subexpression.
+
+ bool OldEval = Info.isEvaluated;
+
+ // The short-circuiting &&/|| operators don't necessarily evaluate their
+ // RHS. Make sure to pass isEvaluated down correctly.
+ if ((E->getOpcode() == BinaryOperator::LAnd && Result == 0) ||
+ (E->getOpcode() == BinaryOperator::LOr && Result != 0))
+ Info.isEvaluated = false;
+
+ if (!EvaluateInteger(E->getRHS(), RHS, Info))
return false;
+ Info.isEvaluated = OldEval;
switch (E->getOpcode()) {
- default: return false;
- case BinaryOperator::Mul: Result *= RHS; break;
- case BinaryOperator::Add: Result += RHS; break;
- case BinaryOperator::Sub: Result -= RHS; break;
- case BinaryOperator::And: Result &= RHS; break;
- case BinaryOperator::Xor: Result ^= RHS; break;
- case BinaryOperator::Or: Result |= RHS; break;
+ default: return Error(E->getOperatorLoc(), diag::err_expr_not_constant);
+ case BinaryOperator::Mul: Result *= RHS; return true;
+ case BinaryOperator::Add: Result += RHS; return true;
+ case BinaryOperator::Sub: Result -= RHS; return true;
+ case BinaryOperator::And: Result &= RHS; return true;
+ case BinaryOperator::Xor: Result ^= RHS; return true;
+ case BinaryOperator::Or: Result |= RHS; return true;
case BinaryOperator::Div:
- if (RHS == 0) return false;
+ if (RHS == 0)
+ return Error(E->getOperatorLoc(), diag::err_expr_divide_by_zero);
Result /= RHS;
- break;
+ return true;
case BinaryOperator::Rem:
- if (RHS == 0) return false;
+ if (RHS == 0)
+ return Error(E->getOperatorLoc(), diag::err_expr_divide_by_zero);
Result %= RHS;
- break;
+ return true;
case BinaryOperator::Shl:
+ // FIXME: Warn about out of range shift amounts!
Result <<= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1);
break;
case BinaryOperator::Shr:
@@ -287,16 +331,29 @@
Result = Result != RHS;
Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
break;
+ case BinaryOperator::LAnd:
+ Result = Result != 0 && RHS != 0;
+ Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
+ break;
+ case BinaryOperator::LOr:
+ 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.
- // FIXME: Need to come up with an efficient way to deal with the C99
- // rules on evaluation while still evaluating this. Maybe a
- // "evaluated comma" out parameter?
- return false;
+ 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());
More information about the cfe-commits
mailing list