diff options
author | Bill Wendling <isanbard@gmail.com> | 2018-11-20 08:53:30 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2018-11-20 08:53:30 +0000 |
commit | 107b0e9881c87dba9f51109bae70b63d9e444546 (patch) | |
tree | c2bcc110804ddf7dca9704e3a47a2f26a6e2bcd5 /clang/lib/AST/ExprConstant.cpp | |
parent | cabb36d38d9e71610c7767a22477576aa8a4d9fa (diff) | |
download | bcm5719-llvm-107b0e9881c87dba9f51109bae70b63d9e444546.tar.gz bcm5719-llvm-107b0e9881c87dba9f51109bae70b63d9e444546.zip |
Use is.constant intrinsic for __builtin_constant_p
Summary:
A __builtin_constant_p may end up with a constant after inlining. Use
the is.constant intrinsic if it's a variable that's in a context where
it may resolve to a constant, e.g., an argument to a function after
inlining.
Reviewers: rsmith, shafik
Subscribers: jfb, kristina, cfe-commits, nickdesaulniers, jyknight
Differential Revision: https://reviews.llvm.org/D54355
llvm-svn: 347294
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 85 |
1 files changed, 61 insertions, 24 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index b0dc7d4a4a9..37839fc1d92 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -45,6 +45,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" #include <cstring> #include <functional> @@ -721,6 +722,10 @@ namespace { /// Whether or not we're currently speculatively evaluating. bool IsSpeculativelyEvaluating; + /// Whether or not we're in a context where the front end requires a + /// constant value. + bool InConstantContext; + enum EvaluationMode { /// Evaluate as a constant expression. Stop if we find that the expression /// is not a constant expression. @@ -782,7 +787,7 @@ namespace { EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false), - EvalMode(Mode) {} + InConstantContext(false), EvalMode(Mode) {} void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { EvaluatingDecl = Base; @@ -7348,6 +7353,8 @@ public: // Visitor Methods //===--------------------------------------------------------------------===// + bool VisitConstantExpr(const ConstantExpr *E); + bool VisitIntegerLiteral(const IntegerLiteral *E) { return Success(E->getValue(), E); } @@ -8088,6 +8095,11 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type, return true; } +bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) { + llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true); + return ExprEvaluatorBaseTy::VisitConstantExpr(E); +} + bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { if (unsigned BuiltinOp = E->getBuiltinCallee()) return VisitBuiltinCallExpr(E, BuiltinOp); @@ -8175,8 +8187,20 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(Val.countLeadingZeros(), E); } - case Builtin::BI__builtin_constant_p: - return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E); + case Builtin::BI__builtin_constant_p: { + auto Arg = E->getArg(0); + if (EvaluateBuiltinConstantP(Info.Ctx, Arg)) + return Success(true, E); + auto ArgTy = Arg->IgnoreImplicit()->getType(); + if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) && + !ArgTy->isAggregateType() && !ArgTy->isPointerType()) { + // We can delay calculation of __builtin_constant_p until after + // inlining. Note: This diagnostic won't be shown to the user. + Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); + return false; + } + return Success(false, E); + } case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: @@ -10746,6 +10770,14 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, return false; } +static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result, + const ASTContext &Ctx, EvalInfo &Info) { + bool IsConst; + if (FastEvaluateAsRValue(E, Result, Ctx, IsConst)) + return IsConst; + + return EvaluateAsRValue(Info, E, Result.Val); +} /// 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 @@ -10753,12 +10785,8 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result, /// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion /// will be applied to the result. bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { - bool IsConst; - if (FastEvaluateAsRValue(this, Result, Ctx, IsConst)) - return IsConst; - EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); - return ::EvaluateAsRValue(Info, this, Result.Val); + return ::EvaluateAsRValue(this, Result, Ctx, Info); } bool Expr::EvaluateAsBooleanCondition(bool &Result, @@ -10878,35 +10906,40 @@ bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const { APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const { - EvalResult EvalResult; - EvalResult.Diag = Diag; - bool Result = EvaluateAsRValue(EvalResult, Ctx); + EvalResult EVResult; + EVResult.Diag = Diag; + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); + Info.InConstantContext = true; + + bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info); (void)Result; assert(Result && "Could not evaluate expression"); - assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); + assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); - return EvalResult.Val.getInt(); + return EVResult.Val.getInt(); } APSInt Expr::EvaluateKnownConstIntCheckOverflow( const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const { - EvalResult EvalResult; - EvalResult.Diag = Diag; - EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); - bool Result = ::EvaluateAsRValue(Info, this, EvalResult.Val); + EvalResult EVResult; + EVResult.Diag = Diag; + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow); + Info.InConstantContext = true; + + bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val); (void)Result; assert(Result && "Could not evaluate expression"); - assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); + assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); - return EvalResult.Val.getInt(); + return EVResult.Val.getInt(); } void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { bool IsConst; - EvalResult EvalResult; - if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { - EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); - (void)::EvaluateAsRValue(Info, this, EvalResult.Val); + EvalResult EVResult; + if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) { + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow); + (void)::EvaluateAsRValue(Info, this, EVResult.Val); } } @@ -10959,7 +10992,11 @@ static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; } static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { Expr::EvalResult EVResult; - if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || + Expr::EvalStatus Status; + EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); + + Info.InConstantContext = true; + if (!::EvaluateAsRValue(E, EVResult, Ctx, Info) || EVResult.HasSideEffects || !EVResult.Val.isInt()) return ICEDiag(IK_NotICE, E->getBeginLoc()); |