[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