diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-04 09:53:13 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-04 09:53:13 +0000 |
commit | 282e7e66748cc6dd14d6f7f2cb52e5373c531e61 (patch) | |
tree | 65a943e4a9c8a0534b580dcbbbcb6791451b5a56 /lib/Sema/SemaExpr.cpp | |
parent | f39aec17b89f8f0dd78e78c50ad2fa08f12272e3 (diff) |
In C++11 mode, when an integral constant expression is desired and we have a
value of class type, look for a unique conversion operator converting to
integral or unscoped enumeration type and use that. Implements [expr.const]p5.
Sema::VerifyIntegerConstantExpression now performs the conversion and returns
the converted result. Some important callers of Expr::isIntegralConstantExpr
have been switched over to using it (including all of those required for C++11
conformance); this switch brings a side-benefit of improved diagnostics and, in
several cases, simpler code. However, some language extensions and attributes
have not been moved across and will not perform implicit conversions on
constant expressions of literal class type where an ICE is required.
In passing, fix static_assert to perform a contextual conversion to bool on its
argument.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149776 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 106 |
1 files changed, 77 insertions, 29 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3d8758e94e..3056156951 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8544,11 +8544,11 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, } else { // The conditional expression is required to be a constant expression. llvm::APSInt condEval(32); - SourceLocation ExpLoc; - if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc)) - return ExprError(Diag(ExpLoc, - diag::err_typecheck_choose_expr_requires_constant) - << CondExpr->getSourceRange()); + ExprResult CondICE = VerifyIntegerConstantExpression(CondExpr, &condEval, + PDiag(diag::err_typecheck_choose_expr_requires_constant), false); + if (CondICE.isInvalid()) + return ExprError(); + CondExpr = CondICE.take(); // If the condition is > zero, then the AST type is the same as the LSHExpr. Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr; @@ -9120,16 +9120,61 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, return isInvalid; } -bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result, - unsigned DiagID, bool AllowFold) { +ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, + llvm::APSInt *Result) { + return VerifyIntegerConstantExpression(E, Result, + PDiag(diag::err_expr_not_ice) << LangOpts.CPlusPlus); +} + +ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + PartialDiagnostic NotIceDiag, + bool AllowFold, + PartialDiagnostic FoldDiag) { + SourceLocation DiagLoc = E->getSourceRange().getBegin(); + + if (getLangOptions().CPlusPlus0x) { + // C++11 [expr.const]p5: + // If an expression of literal class type is used in a context where an + // integral constant expression is required, then that class type shall + // have a single non-explicit conversion function to an integral or + // unscoped enumeration type + ExprResult Converted; + if (NotIceDiag.getDiagID()) { + Converted = ConvertToIntegralOrEnumerationType( + DiagLoc, E, + PDiag(diag::err_ice_not_integral), + PDiag(diag::err_ice_incomplete_type), + PDiag(diag::err_ice_explicit_conversion), + PDiag(diag::note_ice_conversion_here), + PDiag(diag::err_ice_ambiguous_conversion), + PDiag(diag::note_ice_conversion_here), + PDiag(0), + /*AllowScopedEnumerations*/ false); + } else { + // The caller wants to silently enquire whether this is an ICE. Don't + // produce any diagnostics if it isn't. + Converted = ConvertToIntegralOrEnumerationType( + DiagLoc, E, PDiag(), PDiag(), PDiag(), PDiag(), + PDiag(), PDiag(), PDiag(), false); + } + if (Converted.isInvalid()) + return Converted; + E = Converted.take(); + if (!E->getType()->isIntegralOrUnscopedEnumerationType()) + return ExprError(); + } else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { + // An ICE must be of integral or unscoped enumeration type. + if (NotIceDiag.getDiagID()) + Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); + return ExprError(); + } + // Circumvent ICE checking in C++11 to avoid evaluating the expression twice // in the non-ICE case. - if (!getLangOptions().CPlusPlus0x) { - if (E->isIntegerConstantExpr(Context)) { - if (Result) - *Result = E->EvaluateKnownConstInt(Context); - return false; - } + if (!getLangOptions().CPlusPlus0x && E->isIntegerConstantExpr(Context)) { + if (Result) + *Result = E->EvaluateKnownConstInt(Context); + return Owned(E); } Expr::EvalResult EvalResult; @@ -9147,36 +9192,39 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result, if (Folded && getLangOptions().CPlusPlus0x && Notes.empty()) { if (Result) *Result = EvalResult.Val.getInt(); - return false; + return Owned(E); + } + + // If our only note is the usual "invalid subexpression" note, just point + // the caret at its location rather than producing an essentially + // redundant note. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); } if (!Folded || !AllowFold) { - if (DiagID) - Diag(E->getSourceRange().getBegin(), DiagID) << E->getSourceRange(); - else - Diag(E->getSourceRange().getBegin(), diag::err_expr_not_ice) - << E->getSourceRange() << LangOpts.CPlusPlus; - - // We only show the notes if they're not the usual "invalid subexpression" - // or if they are actually in a subexpression. - if (Notes.size() != 1 || - Notes[0].second.getDiagID() != diag::note_invalid_subexpr_in_const_expr - || Notes[0].first != E->IgnoreParens()->getExprLoc()) { + if (NotIceDiag.getDiagID()) { + Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); for (unsigned I = 0, N = Notes.size(); I != N; ++I) Diag(Notes[I].first, Notes[I].second); } - return true; + return ExprError(); } - Diag(E->getSourceRange().getBegin(), diag::ext_expr_not_ice) - << E->getSourceRange() << LangOpts.CPlusPlus; + if (FoldDiag.getDiagID()) + Diag(DiagLoc, FoldDiag) << E->getSourceRange(); + else + Diag(DiagLoc, diag::ext_expr_not_ice) + << E->getSourceRange() << LangOpts.CPlusPlus; for (unsigned I = 0, N = Notes.size(); I != N; ++I) Diag(Notes[I].first, Notes[I].second); if (Result) *Result = EvalResult.Val.getInt(); - return false; + return Owned(E); } namespace { |