[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/
Richard Smith
richard at metafoo.co.uk
Mon Jan 23 21:46:40 PST 2012
On Sat, January 21, 2012 21:08, Francois Pichet wrote:
> 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.
r148784. This special case is to avoid emitting a note describing why the
expression isn't a constant expression, in the case where the note contains no
useful information other than its source location (which we instead use for
the primary diagnostic).
- Richard
More information about the cfe-commits
mailing list