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. I am looking at this code because I'll have to make some changes for MSVC compatibility. _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
