[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