//===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Expr constant evaluator.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
using llvm::APSInt;
using llvm::APFloat;
/// EvalInfo - This is a private struct used by the evaluator to capture
/// information about a subexpression as it is folded. It retains information
/// about the AST context, but also maintains information about the folded
/// expression.
///
/// If an expression could be evaluated, it is still possible it is not a C
/// "integer constant expression" or constant expression. If not, this struct
/// captures information about how and why not.
///
/// One bit of information passed *into* the request for constant folding
/// indicates whether the subexpression is "evaluated" or not according to C
/// rules. For example, the RHS of (0 && foo()) is not evaluated. We can
/// evaluate the expression regardless of what the RHS is, but C only allows
/// certain things in certain situations.
struct EvalInfo {
ASTContext &Ctx;
/// EvalResult - Contains information about the evaluation.
Expr::EvalResult &EvalResult;
/// ShortCircuit - will be greater than zero if the current subexpression has
/// will not be evaluated because it's short-circuited (according to C rules).
unsigned ShortCircuit;
EvalInfo(ASTContext &ctx, Expr::EvalResult& evalresult) : Ctx(ctx),
EvalResult(evalresult), ShortCircuit(0) {}
};
static bool EvaluateLValue(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
static bool EvaluateComplexFloat(const Expr *E, APValue &Result,
EvalInfo &Info);
//===----------------------------------------------------------------------===//
// Misc utilities
//===----------------------------------------------------------------------===//
static bool HandleConversionToBool(Expr* E, bool& Result, EvalInfo &Info) {
if (E->getType()->isIntegralType()) {
APSInt IntResult;
if (!EvaluateInteger(E, IntResult, Info))
return false;
Result = IntResult != 0;
return true;
} else if (E->getType()->isRealFloatingType()) {
APFloat FloatResult(0.0);
if (!EvaluateFloat(E, FloatResult, Info))
return false;
Result = !FloatResult.isZero();
return true;
} else if (E->getType()->isPointerType()) {
APValue PointerResult;
if (!EvaluatePointer(E, PointerResult, Info))
return false;
// FIXME: Is this accurate for all kinds of bases? If not, what would
// the check look like?
Result = PointerResult.getLValueBase() || PointerResult.getLValueOffset();
return true;
}
return false;
}
//===----------------------------------------------------------------------===//
// LValue Evaluation
//===-------------