[cfe-commits] r148439 - in /cfe/trunk: include/clang/Basic/ include/clang/Sema/ lib/Sema/ test/CXX/basic/basic.types/ test/CXX/expr/expr.const/ test/CXX/stmt.stmt/stmt.select/stmt.switch/ test/CodeGenCXX/ test/SemaCXX/
Francois Pichet
pichet2000 at gmail.com
Sat Jan 21 13:08:16 PST 2012
On Wed, Jan 18, 2012 at 6:55 PM, Richard Smith
<richard-llvm at metafoo.co.uk> wrote:
> Author: rsmith
> Date: Wed Jan 18 17:55:52 2012
> New Revision: 148439
>
> URL: http://llvm.org/viewvc/llvm-project?rev=148439&view=rev
> Log:
> constexpr: converted constant expression handling for enumerator values, case
> values and non-type template arguments of integral and enumeration types.
>
> This change causes some legal C++98 code to no longer compile in C++11 mode, by
> enforcing the C++11 rule that narrowing integral conversions are not permitted
> in the final implicit conversion sequence for the above cases.
>
> +ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
> + llvm::APSInt &Value,
> + CCEKind CCE) {
> + assert(LangOpts.CPlusPlus0x && "converted constant expression outside C++11");
> + assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
> +
> + if (checkPlaceholderForOverload(*this, From))
> + return ExprError();
> +
> + // C++11 [expr.const]p3 with proposed wording fixes:
> + // A converted constant expression of type T is a core constant expression,
> + // implicitly converted to a prvalue of type T, where the converted
> + // expression is a literal constant expression and the implicit conversion
> + // sequence contains only user-defined conversions, lvalue-to-rvalue
> + // conversions, integral promotions, and integral conversions other than
> + // narrowing conversions.
> + ImplicitConversionSequence ICS =
> + TryImplicitConversion(From, T,
> + /*SuppressUserConversions=*/false,
> + /*AllowExplicit=*/false,
> + /*InOverloadResolution=*/false,
> + /*CStyle=*/false,
> + /*AllowObjcWritebackConversion=*/false);
> + StandardConversionSequence *SCS = 0;
> + switch (ICS.getKind()) {
> + case ImplicitConversionSequence::StandardConversion:
> + if (!CheckConvertedConstantConversions(*this, ICS.Standard))
> + return Diag(From->getSourceRange().getBegin(),
> + diag::err_typecheck_converted_constant_expression_disallowed)
> + << From->getType() << From->getSourceRange() << T;
> + SCS = &ICS.Standard;
> + break;
> + case ImplicitConversionSequence::UserDefinedConversion:
> + // We are converting from class type to an integral or enumeration type, so
> + // the Before sequence must be trivial.
> + if (!CheckConvertedConstantConversions(*this, ICS.UserDefined.After))
> + return Diag(From->getSourceRange().getBegin(),
> + diag::err_typecheck_converted_constant_expression_disallowed)
> + << From->getType() << From->getSourceRange() << T;
> + SCS = &ICS.UserDefined.After;
> + break;
> + case ImplicitConversionSequence::AmbiguousConversion:
> + case ImplicitConversionSequence::BadConversion:
> + if (!DiagnoseMultipleUserDefinedConversion(From, T))
> + return Diag(From->getSourceRange().getBegin(),
> + diag::err_typecheck_converted_constant_expression)
> + << From->getType() << From->getSourceRange() << T;
> + return ExprError();
> +
> + case ImplicitConversionSequence::EllipsisConversion:
> + llvm_unreachable("ellipsis conversion in converted constant expression");
> + }
> +
> + ExprResult Result = PerformImplicitConversion(From, T, ICS, AA_Converting);
> + if (Result.isInvalid())
> + return Result;
> +
> + // Check for a narrowing implicit conversion.
> + APValue PreNarrowingValue;
> + switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue)) {
> + case NK_Variable_Narrowing:
> + // Implicit conversion to a narrower type, and the value is not a constant
> + // expression. We'll diagnose this in a moment.
> + case NK_Not_Narrowing:
> + break;
> +
> + case NK_Constant_Narrowing:
> + Diag(From->getSourceRange().getBegin(), diag::err_cce_narrowing)
> + << CCE << /*Constant*/1
> + << PreNarrowingValue.getAsString(Context, QualType()) << T;
> + break;
> +
> + case NK_Type_Narrowing:
> + Diag(From->getSourceRange().getBegin(), diag::err_cce_narrowing)
> + << CCE << /*Constant*/0 << From->getType() << T;
> + break;
> + }
> +
> + // Check the expression is a constant expression.
> + llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
> + Expr::EvalResult Eval;
> + Eval.Diag = &Notes;
> +
> + if (!Result.get()->EvaluateAsRValue(Eval, Context)) {
> + // The expression can't be folded, so we can't keep it at this position in
> + // the AST.
> + Result = ExprError();
> + } else if (Notes.empty()) {
> + // It's a constant expression.
> + Value = Eval.Val.getInt();
> + return Result;
> + }
> +
> + // It's not a constant expression. Produce an appropriate diagnostic.
> + if (Notes.size() == 1 &&
> + Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr)
> + Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
Hi Richard, Can you add a test case for this Diag? I commented out the
Diag line and all the clang tests still pass. It is not clear to me
what it is for.
I am looking at this code because I'll have to make some changes for
MSVC compatibility.
More information about the cfe-commits
mailing list