On Sat, January 21, 2012 21:08, Francois Pichet wrote: > On Wed, Jan 18, 2012 at 6:55 PM, Richard Smith > <[email protected]> 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 _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
