diff options
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 65 |
1 files changed, 38 insertions, 27 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index fc3c5aac01..5d61406959 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1756,18 +1756,16 @@ static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc, if (!CD->isTrivial() || !CD->isDefaultConstructor()) return false; - if (!CD->isConstexpr()) { + // Value-initialization does not call a trivial default constructor, so such a + // call is a core constant expression whether or not the constructor is + // constexpr. + if (!CD->isConstexpr() && !IsValueInitialization) { if (Info.getLangOpts().CPlusPlus0x) { - // Value-initialization does not call a trivial default constructor, so - // such a call is a core constant expression whether or not the - // constructor is constexpr. - if (!IsValueInitialization) { - // FIXME: If DiagDecl is an implicitly-declared special member function, - // we should be much more explicit about why it's not constexpr. - Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1) - << /*IsConstexpr*/0 << /*IsConstructor*/1 << CD; - Info.Note(CD->getLocation(), diag::note_declared_at); - } + // FIXME: If DiagDecl is an implicitly-declared special member function, + // we should be much more explicit about why it's not constexpr. + Info.CCEDiag(Loc, diag::note_constexpr_invalid_function, 1) + << /*IsConstexpr*/0 << /*IsConstructor*/1 << CD; + Info.Note(CD->getLocation(), diag::note_declared_at); } else { Info.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr); } @@ -5944,24 +5942,12 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(ASTContext &Ctx, return false; } - Expr::EvalResult Result; - llvm::SmallVector<PartialDiagnosticAt, 8> Diags; - Result.Diag = &Diags; - EvalInfo Info(Ctx, Result); - - bool IsICE = EvaluateAsRValue(Info, E, Result.Val); - if (!Diags.empty()) { - IsICE = false; - if (Loc) *Loc = Diags[0].first; - } else if (!IsICE && Loc) { - *Loc = E->getExprLoc(); - } - - if (!IsICE) + APValue Result; + if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc)) return false; - assert(Result.Val.isInt() && "pointer cast to int is not an ICE"); - if (Value) *Value = Result.Val.getInt(); + assert(Result.isInt() && "pointer cast to int is not an ICE"); + if (Value) *Value = Result.getInt(); return true; } @@ -5988,3 +5974,28 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, ASTContext &Ctx, llvm_unreachable("ICE cannot be evaluated!"); return true; } + +bool Expr::isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result, + SourceLocation *Loc) const { + // We support this checking in C++98 mode in order to diagnose compatibility + // issues. + assert(Ctx.getLangOptions().CPlusPlus); + + Expr::EvalStatus Status; + llvm::SmallVector<PartialDiagnosticAt, 8> Diags; + Status.Diag = &Diags; + EvalInfo Info(Ctx, Status); + + APValue Scratch; + bool IsConstExpr = ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch); + + if (!Diags.empty()) { + IsConstExpr = false; + if (Loc) *Loc = Diags[0].first; + } else if (!IsConstExpr) { + // FIXME: This shouldn't happen. + if (Loc) *Loc = getExprLoc(); + } + + return IsConstExpr; +} |