diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-10-24 17:54:18 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-10-24 17:54:18 +0000 |
commit | 03f96110bc2c2c773e06a42982b17a03dd2e5379 (patch) | |
tree | 4689968ffb6e162248605d40ee0b4dd8b50afd24 /lib/AST/ExprConstant.cpp | |
parent | 9158902bae11aec846edcf132a6dc29c834f197b (diff) |
Constant expression evaluation: factor out VarDecl initializer evaluation and
caching.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142812 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 110 |
1 files changed, 42 insertions, 68 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index f108c1a30e..5d34aff7a6 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -261,6 +261,39 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType, return Result; } +/// Try to evaluate the initializer for a variable declaration. +static APValue *EvaluateVarDeclInit(EvalInfo &Info, const VarDecl *VD) { + if (isa<ParmVarDecl>(VD)) + return 0; + + const Expr *Init = VD->getAnyInitializer(); + if (!Init) + return 0; + + if (APValue *V = VD->getEvaluatedValue()) + return V; + + if (VD->isEvaluatingValue()) + return 0; + + VD->setEvaluatingValue(); + + // FIXME: If the initializer isn't a constant expression, propagate up any + // diagnostic explaining why not. + Expr::EvalResult EResult; + if (Init->Evaluate(EResult, Info.Ctx) && !EResult.HasSideEffects) + VD->setEvaluatedValue(EResult.Val); + else + VD->setEvaluatedValue(APValue()); + + return VD->getEvaluatedValue(); +} + +bool IsConstNonVolatile(QualType T) { + Qualifiers Quals = T.getQualifiers(); + return Quals.hasConst() && !Quals.hasVolatile(); +} + namespace { class HasSideEffect : public ConstStmtVisitor<HasSideEffect, bool> { @@ -1163,38 +1196,11 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { // In C++, const, non-volatile integers initialized with ICEs are ICEs. // In C, they can also be folded, although they are not ICEs. - if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers() - == Qualifiers::Const) { - - if (isa<ParmVarDecl>(D)) - return false; - + if (IsConstNonVolatile(E->getType())) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - if (const Expr *Init = VD->getAnyInitializer()) { - if (APValue *V = VD->getEvaluatedValue()) { - if (V->isInt()) - return Success(V->getInt(), E); - return false; - } - - if (VD->isEvaluatingValue()) - return false; - - VD->setEvaluatingValue(); - - Expr::EvalResult EResult; - // FIXME: Produce a diagnostic if the initializer isn't a constant - // expression. - if (Init->Evaluate(EResult, Info.Ctx) && !EResult.HasSideEffects && - EResult.Val.isInt()) { - // Cache the evaluated value in the variable declaration. - Result = EResult.Val; - VD->setEvaluatedValue(Result); - return true; - } - - VD->setEvaluatedValue(APValue()); - } + APValue *V = EvaluateVarDeclInit(Info, VD); + if (V && V->isInt()) + return Success(V->getInt(), E); } } @@ -2145,41 +2151,14 @@ bool FloatExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { if (ExprEvaluatorBaseTy::VisitDeclRefExpr(E)) return true; - const Decl *D = E->getDecl(); - if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D)) return false; - const VarDecl *VD = cast<VarDecl>(D); - - // Require the qualifiers to be const and not volatile. - CanQualType T = Info.Ctx.getCanonicalType(E->getType()); - if (!T.isConstQualified() || T.isVolatileQualified()) - return false; - - const Expr *Init = VD->getAnyInitializer(); - if (!Init) return false; - - if (APValue *V = VD->getEvaluatedValue()) { - if (V->isFloat()) { + const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()); + if (VD && IsConstNonVolatile(VD->getType())) { + APValue *V = EvaluateVarDeclInit(Info, VD); + if (V && V->isFloat()) { Result = V->getFloat(); return true; } - return false; } - - if (VD->isEvaluatingValue()) - return false; - - VD->setEvaluatingValue(); - - Expr::EvalResult InitResult; - if (Init->Evaluate(InitResult, Info.Ctx) && !InitResult.HasSideEffects && - InitResult.Val.isFloat()) { - // Cache the evaluated value in the variable declaration. - Result = InitResult.Val.getFloat(); - VD->setEvaluatedValue(InitResult.Val); - return true; - } - - VD->setEvaluatedValue(APValue()); return false; } @@ -2947,8 +2926,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::DeclRefExprClass: if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl())) return NoDiag(); - if (Ctx.getLangOptions().CPlusPlus && - E->getType().getCVRQualifiers() == Qualifiers::Const) { + if (Ctx.getLangOptions().CPlusPlus && IsConstNonVolatile(E->getType())) { const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl(); // Parameter variables are never constants. Without this check, @@ -2961,10 +2939,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // A variable of non-volatile const-qualified integral or enumeration // type initialized by an ICE can be used in ICEs. if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) { - Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers(); - if (Quals.hasVolatile() || !Quals.hasConst()) - return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); - // Look for a declaration of this variable that has an initializer. const VarDecl *ID = 0; const Expr *Init = Dcl->getAnyInitializer(ID); |