diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-11-04 05:33:44 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-11-04 05:33:44 +0000 |
commit | 69c2c50498dadfa6bb99baba52187e3cfa0ac78a (patch) | |
tree | f063cba8ed0b12bb849ade5e141fcc7264574c98 /lib/AST/ExprConstant.cpp | |
parent | 0a3bdb646ee0318667f4cebec6792d2548fb9950 (diff) |
Constant expression evaluation: refactor to start the groundwork for coping with
initializations which refer indirectly to elements of the object being
initialized.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143680 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 70 |
1 files changed, 55 insertions, 15 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index dcdd9c3179..afd4e0e2e0 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -302,6 +302,8 @@ namespace { } static bool Evaluate(CCValue &Result, EvalInfo &Info, const Expr *E); +static bool EvaluateConstantExpression(APValue &Result, EvalInfo &Info, + const Expr *E); static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); @@ -335,9 +337,14 @@ static bool IsGlobalLValue(const Expr* E) { } /// Check that this core constant expression value is a valid value for a -/// constant expression. -static bool CheckConstantExpression(const CCValue &Value) { - return !Value.isLValue() || IsGlobalLValue(Value.getLValueBase()); +/// constant expression, and if it is, produce the corresponding constant value. +static bool CheckConstantExpression(const CCValue &CCValue, APValue &Value) { + if (CCValue.isLValue() && !IsGlobalLValue(CCValue.getLValueBase())) + return false; + + // Slice off the extra bits. + Value = CCValue; + return true; } const ValueDecl *GetLValueBaseDecl(const LValue &LVal) { @@ -512,12 +519,14 @@ static bool EvaluateVarDeclInit(EvalInfo &Info, const VarDecl *VD, EvalInfo InitInfo(Info.Ctx, EStatus); // FIXME: The caller will need to know whether the value was a constant // expression. If not, we should propagate up a diagnostic. - if (!Evaluate(Result, InitInfo, Init) || !CheckConstantExpression(Result)) { + APValue EvalResult; + if (!EvaluateConstantExpression(EvalResult, InitInfo, Init)) { VD->setEvaluatedValue(APValue()); return false; } - VD->setEvaluatedValue(Result); + VD->setEvaluatedValue(EvalResult); + Result = CCValue(EvalResult, CCValue::GlobalValue()); return true; } @@ -900,13 +909,14 @@ public: const FunctionDecl *Definition; Stmt *Body = FD->getBody(Definition); - CCValue Result; + CCValue CCResult; + APValue Result; llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); if (Body && Definition->isConstexpr() && !Definition->isInvalidDecl() && - HandleFunctionCall(Args, Body, Info, Result) && - CheckConstantExpression(Result)) - return DerivedSuccess(Result, E); + HandleFunctionCall(Args, Body, Info, CCResult) && + CheckConstantExpression(CCResult, Result)) + return DerivedSuccess(CCValue(Result, CCValue::GlobalValue()), E); return DerivedError(E); } @@ -1372,7 +1382,8 @@ namespace { Result = APValue(V.data(), V.size()); return true; } - bool Success(const APValue &V, const Expr *E) { + bool Success(const CCValue &V, const Expr *E) { + assert(V.isVector()); Result = V; return true; } @@ -3197,12 +3208,44 @@ static bool Evaluate(CCValue &Result, EvalInfo &Info, const Expr *E) { if (!EvaluateComplex(E, C, Info)) return false; C.moveInto(Result); + } else if (E->getType()->isMemberPointerType()) { + // FIXME: Implement evaluation of pointer-to-member types. + return false; + } else if (E->getType()->isArrayType() && E->getType()->isLiteralType()) { + // FIXME: Implement evaluation of array rvalues. + return false; + } else if (E->getType()->isRecordType() && E->getType()->isLiteralType()) { + // FIXME: Implement evaluation of record rvalues. + return false; } else return false; return true; } +/// EvaluateConstantExpression - Evaluate an expression as a constant expression +/// in-place in an APValue. In some cases, the in-place evaluation is essential, +/// since later initializers for an object can indirectly refer to subobjects +/// which were initialized earlier. +static bool EvaluateConstantExpression(APValue &Result, EvalInfo &Info, + const Expr *E) { + if (E->isRValue() && E->getType()->isLiteralType()) { + // Evaluate arrays and record types in-place, so that later initializers can + // refer to earlier-initialized members of the object. + if (E->getType()->isArrayType()) + // FIXME: Implement evaluation of array rvalues. + return false; + else if (E->getType()->isRecordType()) + // FIXME: Implement evaluation of record rvalues. + return false; + } + + // For any other type, in-place evaluation is unimportant. + CCValue CoreConstResult; + return Evaluate(CoreConstResult, Info, E) && + CheckConstantExpression(CoreConstResult, Result); +} + /// EvaluateAsRValue - Return true if this is a constant which we can fold using /// any crazy technique (that has nothing to do with language standards) that @@ -3224,11 +3267,8 @@ bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { } // Check this core constant expression is a constant expression, and if so, - // slice it down to one. - if (!CheckConstantExpression(Value)) - return false; - Result.Val = Value; - return true; + // convert it to one. + return CheckConstantExpression(Value, Result.Val); } bool Expr::EvaluateAsBooleanCondition(bool &Result, |