r222807 - [c++1z] Most of N4268 (allow constant evaluation for non-type template arguments).
Richard Smith
richard at metafoo.co.uk
Wed Nov 26 11:38:11 PST 2014
On Wed, Nov 26, 2014 at 6:19 AM, Aaron Ballman <aaron at aaronballman.com>
wrote:
> This appears to have broken one of the bots:
> http://bb.pgr.jp/builders/ninja-x64-msvc-RA-centos6/builds/8280
Thanks, should be fixed in r222848.
>
> ~Aaron
>
> On Tue, Nov 25, 2014 at 10:26 PM, Richard Smith
> <richard-llvm at metafoo.co.uk> wrote:
> > Author: rsmith
> > Date: Tue Nov 25 21:26:53 2014
> > New Revision: 222807
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=222807&view=rev
> > Log:
> > [c++1z] Most of N4268 (allow constant evaluation for non-type template
> arguments).
> >
> > We don't yet support pointer-to-member template arguments that have
> undergone
> > pointer-to-member conversions, mostly because we don't have a mangling
> for them yet.
> >
> > Added:
> > cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
> > Modified:
> > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > cfe/trunk/include/clang/Sema/Sema.h
> > cfe/trunk/lib/Sema/SemaExprCXX.cpp
> > cfe/trunk/lib/Sema/SemaOverload.cpp
> > cfe/trunk/lib/Sema/SemaTemplate.cpp
> > cfe/trunk/test/CXX/drs/dr0xx.cpp
> > cfe/trunk/test/CXX/drs/dr1xx.cpp
> > cfe/trunk/test/CXX/drs/dr2xx.cpp
> > cfe/trunk/test/CXX/drs/dr3xx.cpp
> > cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
> > cfe/trunk/www/cxx_status.html
> >
> > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Nov 25
> 21:26:53 2014
> > @@ -64,6 +64,9 @@ def err_typecheck_converted_constant_exp
> > "value of type %0 is not implicitly convertible to %1">;
> > def err_typecheck_converted_constant_expression_disallowed : Error<
> > "conversion from %0 to %1 is not allowed in a converted constant
> expression">;
> > +def err_typecheck_converted_constant_expression_indirect : Error<
> > + "conversion from %0 to %1 in converted constant expression would "
> > + "bind reference to a temporary">;
> > def err_expr_not_cce : Error<
> > "%select{case value|enumerator value|non-type template argument|array
> size}0 "
> > "is not a constant expression">;
> > @@ -3293,6 +3296,10 @@ def err_template_arg_wrongtype_null_cons
> > def err_deduced_non_type_template_arg_type_mismatch : Error<
> > "deduced non-type template argument does not have the same type as
> the "
> > "its corresponding template parameter%diff{ ($ vs $)|}0,1">;
> > +def err_non_type_template_arg_subobject : Error<
> > + "non-type template argument refers to subobject '%0'">;
> > +def err_non_type_template_arg_addr_label_diff : Error<
> > + "template argument / label address difference / what did you
> expect?">;
> > def err_template_arg_not_convertible : Error<
> > "non-type template argument of type %0 cannot be converted to a value
> "
> > "of type %1">;
> > @@ -3344,6 +3351,9 @@ def err_template_arg_not_object_or_func
> > "non-type template argument does not refer to an object or function">;
> > def err_template_arg_not_pointer_to_member_form : Error<
> > "non-type template argument is not a pointer to member constant">;
> > +def err_template_arg_member_ptr_base_derived_not_supported : Error<
> > + "sorry, non-type template argument of pointer-to-member type %1 that
> refers "
> > + "to member %q0 of a different class is not supported yet">;
> > def ext_template_arg_extra_parens : ExtWarn<
> > "address non-type template argument cannot be surrounded by
> parentheses">;
> > def warn_cxx98_compat_template_arg_extra_parens : Warning<
> >
> > Modified: cfe/trunk/include/clang/Sema/Sema.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/Sema.h (original)
> > +++ cfe/trunk/include/clang/Sema/Sema.h Tue Nov 25 21:26:53 2014
> > @@ -2148,6 +2148,8 @@ public:
> > };
> > ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
> > llvm::APSInt &Value,
> CCEKind CCE);
> > + ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
> > + APValue &Value, CCEKind
> CCE);
> >
> > /// \brief Abstract base class used to perform a contextual implicit
> > /// conversion from an expression to any type passing a filter.
> >
> > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Nov 25 21:26:53 2014
> > @@ -2780,10 +2780,29 @@ Sema::PerformImplicitConversion(Expr *Fr
> > // Perform the second implicit conversion
> > switch (SCS.Second) {
> > case ICK_Identity:
> > - // If both sides are functions (or pointers/references to them),
> there could
> > - // be incompatible exception declarations.
> > - if (CheckExceptionSpecCompatibility(From, ToType))
> > - return ExprError();
> > + // C++ [except.spec]p5:
> > + // [For] assignment to and initialization of pointers to
> functions,
> > + // pointers to member functions, and references to functions: the
> > + // target entity shall allow at least the exceptions allowed by
> the
> > + // source value in the assignment or initialization.
> > + switch (Action) {
> > + case AA_Assigning:
> > + case AA_Initializing:
> > + // Note, function argument passing and returning are
> initialization.
> > + case AA_Passing:
> > + case AA_Returning:
> > + case AA_Sending:
> > + case AA_Passing_CFAudited:
> > + if (CheckExceptionSpecCompatibility(From, ToType))
> > + return ExprError();
> > + break;
> > +
> > + case AA_Casting:
> > + case AA_Converting:
> > + // Casts and implicit conversions are not initialization, so are
> not
> > + // checked for exception specification mismatches.
> > + break;
> > + }
> > // Nothing else to do.
> > break;
> >
> >
> > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Nov 25 21:26:53 2014
> > @@ -4894,41 +4894,51 @@ static bool CheckConvertedConstantConver
> > // conversions are fine.
> > switch (SCS.Second) {
> > case ICK_Identity:
> > + case ICK_NoReturn_Adjustment:
> > case ICK_Integral_Promotion:
> > - case ICK_Integral_Conversion:
> > - case ICK_Zero_Event_Conversion:
> > + case ICK_Integral_Conversion: // Narrowing conversions are checked
> elsewhere.
> > return true;
> >
> > case ICK_Boolean_Conversion:
> > // Conversion from an integral or unscoped enumeration type to bool
> is
> > - // classified as ICK_Boolean_Conversion, but it's also an integral
> > - // conversion, so it's permitted in a converted constant expression.
> > + // classified as ICK_Boolean_Conversion, but it's also arguably an
> integral
> > + // conversion, so we allow it in a converted constant expression.
> > + //
> > + // FIXME: Per core issue 1407, we should not allow this, but that
> breaks
> > + // a lot of popular code. We should at least add a warning for this
> > + // (non-conforming) extension.
> > return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() &&
> > SCS.getToType(2)->isBooleanType();
> >
> > + case ICK_Pointer_Conversion:
> > + case ICK_Pointer_Member:
> > + // C++1z: null pointer conversions and null member pointer
> conversions are
> > + // only permitted if the source type is std::nullptr_t.
> > + return SCS.getFromType()->isNullPtrType();
> > +
> > + case ICK_Floating_Promotion:
> > + case ICK_Complex_Promotion:
> > + case ICK_Floating_Conversion:
> > + case ICK_Complex_Conversion:
> > case ICK_Floating_Integral:
> > + case ICK_Compatible_Conversion:
> > + case ICK_Derived_To_Base:
> > + case ICK_Vector_Conversion:
> > + case ICK_Vector_Splat:
> > case ICK_Complex_Real:
> > + case ICK_Block_Pointer_Conversion:
> > + case ICK_TransparentUnionConversion:
> > + case ICK_Writeback_Conversion:
> > + case ICK_Zero_Event_Conversion:
> > return false;
> >
> > case ICK_Lvalue_To_Rvalue:
> > case ICK_Array_To_Pointer:
> > case ICK_Function_To_Pointer:
> > - case ICK_NoReturn_Adjustment:
> > + llvm_unreachable("found a first conversion kind in Second");
> > +
> > case ICK_Qualification:
> > - case ICK_Compatible_Conversion:
> > - case ICK_Vector_Conversion:
> > - case ICK_Vector_Splat:
> > - case ICK_Derived_To_Base:
> > - case ICK_Pointer_Conversion:
> > - case ICK_Pointer_Member:
> > - case ICK_Block_Pointer_Conversion:
> > - case ICK_Writeback_Conversion:
> > - case ICK_Floating_Promotion:
> > - case ICK_Complex_Promotion:
> > - case ICK_Complex_Conversion:
> > - case ICK_Floating_Conversion:
> > - case ICK_TransparentUnionConversion:
> > - llvm_unreachable("unexpected second conversion kind");
> > + llvm_unreachable("found a third conversion kind in Second");
> >
> > case ICK_Num_Conversion_Kinds:
> > break;
> > @@ -4940,67 +4950,71 @@ static bool CheckConvertedConstantConver
> > /// CheckConvertedConstantExpression - Check that the expression From
> is a
> > /// converted constant expression of type T, perform the conversion and
> produce
> > /// the converted expression, per C++11 [expr.const]p3.
> > -ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType
> T,
> > - llvm::APSInt &Value,
> > - CCEKind CCE) {
> > - assert(LangOpts.CPlusPlus11 && "converted constant expression outside
> C++11");
> > - assert(T->isIntegralOrEnumerationType() && "unexpected converted
> const type");
> > +static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
> > + QualType T, APValue
> &Value,
> > + Sema::CCEKind CCE,
> > + bool RequireInt) {
> > + assert(S.getLangOpts().CPlusPlus11 &&
> > + "converted constant expression outside C++11");
> >
> > - if (checkPlaceholderForOverload(*this, From))
> > + if (checkPlaceholderForOverload(S, 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.
> > + // C++1z [expr.const]p3:
> > + // A converted constant expression of type T is an expression,
> > + // implicitly converted to type T, where the converted
> > + // expression is a constant expression and the implicit conversion
> > + // sequence contains only [... list of conversions ...].
> > ImplicitConversionSequence ICS =
> > - TryImplicitConversion(From, T,
> > + TryCopyInitialization(S, From, T,
> > /*SuppressUserConversions=*/false,
> > - /*AllowExplicit=*/false,
> > /*InOverloadResolution=*/false,
> > - /*CStyle=*/false,
> > - /*AllowObjcWritebackConversion=*/false);
> > + /*AllowObjcWritebackConversion=*/false,
> > + /*AllowExplicit=*/false);
> > StandardConversionSequence *SCS = nullptr;
> > switch (ICS.getKind()) {
> > case ImplicitConversionSequence::StandardConversion:
> > - if (!CheckConvertedConstantConversions(*this, ICS.Standard))
> > - return Diag(From->getLocStart(),
> > -
> 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->getLocStart(),
> > -
> diag::err_typecheck_converted_constant_expression_disallowed)
> > - << From->getType() << From->getSourceRange() << T;
> > + // We are converting to a non-class type, so the Before sequence
> > + // must be trivial.
> > SCS = &ICS.UserDefined.After;
> > break;
> > case ImplicitConversionSequence::AmbiguousConversion:
> > case ImplicitConversionSequence::BadConversion:
> > - if (!DiagnoseMultipleUserDefinedConversion(From, T))
> > - return Diag(From->getLocStart(),
> > - diag::err_typecheck_converted_constant_expression)
> > - << From->getType() << From->getSourceRange() << T;
> > + if (!S.DiagnoseMultipleUserDefinedConversion(From, T))
> > + return S.Diag(From->getLocStart(),
> > + 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);
> > + // Check that we would only use permitted conversions.
> > + if (!CheckConvertedConstantConversions(S, *SCS)) {
> > + return S.Diag(From->getLocStart(),
> > +
> diag::err_typecheck_converted_constant_expression_disallowed)
> > + << From->getType() << From->getSourceRange() << T;
> > + }
> > + // [...] and where the reference binding (if any) binds directly.
> > + if (SCS->ReferenceBinding && !SCS->DirectBinding) {
> > + return S.Diag(From->getLocStart(),
> > +
> diag::err_typecheck_converted_constant_expression_indirect)
> > + << From->getType() << From->getSourceRange() << T;
> > + }
> > +
> > + ExprResult Result =
> > + S.PerformImplicitConversion(From, T, ICS, Sema::AA_Converting);
> > if (Result.isInvalid())
> > return Result;
> >
> > // Check for a narrowing implicit conversion.
> > APValue PreNarrowingValue;
> > QualType PreNarrowingType;
> > - switch (SCS->getNarrowingKind(Context, Result.get(),
> PreNarrowingValue,
> > + switch (SCS->getNarrowingKind(S.Context, Result.get(),
> PreNarrowingValue,
> > PreNarrowingType)) {
> > case NK_Variable_Narrowing:
> > // Implicit conversion to a narrower type, and the value is not a
> constant
> > @@ -5009,13 +5023,13 @@ ExprResult Sema::CheckConvertedConstantE
> > break;
> >
> > case NK_Constant_Narrowing:
> > - Diag(From->getLocStart(), diag::ext_cce_narrowing)
> > + S.Diag(From->getLocStart(), diag::ext_cce_narrowing)
> > << CCE << /*Constant*/1
> > - << PreNarrowingValue.getAsString(Context, PreNarrowingType) << T;
> > + << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) <<
> T;
> > break;
> >
> > case NK_Type_Narrowing:
> > - Diag(From->getLocStart(), diag::ext_cce_narrowing)
> > + S.Diag(From->getLocStart(), diag::ext_cce_narrowing)
> > << CCE << /*Constant*/0 << From->getType() << T;
> > break;
> > }
> > @@ -5025,12 +5039,15 @@ ExprResult Sema::CheckConvertedConstantE
> > Expr::EvalResult Eval;
> > Eval.Diag = &Notes;
> >
> > - if (!Result.get()->EvaluateAsRValue(Eval, Context) ||
> !Eval.Val.isInt()) {
> > + if ((T->isReferenceType()
> > + ? !Result.get()->EvaluateAsLValue(Eval, S.Context)
> > + : !Result.get()->EvaluateAsRValue(Eval, S.Context)) ||
> > + (RequireInt && !Eval.Val.isInt())) {
> > // The expression can't be folded, so we can't keep it at this
> position in
> > // the AST.
> > Result = ExprError();
> > } else {
> > - Value = Eval.Val.getInt();
> > + Value = Eval.Val;
> >
> > if (Notes.empty()) {
> > // It's a constant expression.
> > @@ -5041,16 +5058,34 @@ ExprResult Sema::CheckConvertedConstantE
> > // 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;
> > + S.Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
> > else {
> > - Diag(From->getLocStart(), diag::err_expr_not_cce)
> > + S.Diag(From->getLocStart(), diag::err_expr_not_cce)
> > << CCE << From->getSourceRange();
> > for (unsigned I = 0; I < Notes.size(); ++I)
> > - Diag(Notes[I].first, Notes[I].second);
> > + S.Diag(Notes[I].first, Notes[I].second);
> > }
> > - return Result;
> > + return ExprError();
> > }
> >
> > +ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType
> T,
> > + APValue &Value,
> CCEKind CCE) {
> > + return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE,
> false);
> > +}
> > +
> > +ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType
> T,
> > + llvm::APSInt &Value,
> > + CCEKind CCE) {
> > + assert(T->isIntegralOrEnumerationType() && "unexpected converted
> const type");
> > +
> > + APValue V;
> > + auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE,
> true);
> > + if (!R.isInvalid())
> > + Value = V.getInt();
> > + return R;
> > +}
> > +
> > +
> > /// dropPointerConversions - If the given standard conversion sequence
> > /// involves any pointer conversions, remove them. This may change
> > /// the result type of the conversion sequence.
> >
> > Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Nov 25 21:26:53 2014
> > @@ -4759,13 +4759,111 @@ ExprResult Sema::CheckTemplateArgument(N
> > return Arg;
> > }
> >
> > + QualType ParamType = InstantiatedParamType;
> > + if (getLangOpts().CPlusPlus1z) {
> > + // FIXME: We can do some limited checking for a value-dependent but
> not
> > + // type-dependent argument.
> > + if (Arg->isValueDependent()) {
> > + Converted = TemplateArgument(Arg);
> > + return Arg;
> > + }
> > +
> > + // C++1z [temp.arg.nontype]p1:
> > + // A template-argument for a non-type template parameter shall be
> > + // a converted constant expression of the type of the
> template-parameter.
> > + APValue Value;
> > + ExprResult ArgResult = CheckConvertedConstantExpression(
> > + Arg, ParamType, Value, CCEK_TemplateArg);
> > + if (ArgResult.isInvalid())
> > + return ExprError();
> > +
> > + // Convert the APValue to a TemplateArgument.
> > + switch (Value.getKind()) {
> > + case APValue::Uninitialized:
> > + assert(ParamType->isNullPtrType());
> > + Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
> > + break;
> > + case APValue::Int:
> > + assert(ParamType->isIntegralOrEnumerationType());
> > + Converted = TemplateArgument(Context, Value.getInt(), ParamType);
> > + break;
> > + case APValue::MemberPointer: {
> > + assert(ParamType->isMemberPointerType());
> > +
> > + // FIXME: We need TemplateArgument representation and mangling
> for these.
> > + if (!Value.getMemberPointerPath().empty()) {
> > + Diag(Arg->getLocStart(),
> > +
> diag::err_template_arg_member_ptr_base_derived_not_supported)
> > + << Value.getMemberPointerDecl() << ParamType
> > + << Arg->getSourceRange();
> > + return ExprError();
> > + }
> > +
> > + auto *VD = const_cast<ValueDecl*>(Value.getMemberPointerDecl());
> > + Converted = VD ? TemplateArgument(VD, ParamType)
> > + : TemplateArgument(ParamType, /*isNullPtr*/true);
> > + break;
> > + }
> > + case APValue::LValue: {
> > + // For a non-type template-parameter of pointer or reference
> type,
> > + // the value of the constant expression shall not refer to
> > + assert(ParamType->isPointerType() ||
> ParamType->isReferenceType());
> > + // -- a temporary object
> > + // -- a string literal
> > + // -- the result of a typeid expression, or
> > + // -- a predefind __func__ variable
> > + if (auto *E = Value.getLValueBase().dyn_cast<const Expr*>()) {
> > + if (isa<CXXUuidofExpr>(E)) {
> > + Converted = TemplateArgument(const_cast<Expr*>(E));
> > + break;
> > + }
> > + Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
> > + << Arg->getSourceRange();
> > + return ExprError();
> > + }
> > + auto *VD = const_cast<ValueDecl *>(
> > + Value.getLValueBase().dyn_cast<const ValueDecl *>());
> > + // -- a subobject
> > + if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
> > + VD && VD->getType()->isArrayType() &&
> > + Value.getLValuePath()[0].ArrayIndex == 0 &&
> > + !Value.isLValueOnePastTheEnd() && ParamType->isPointerType())
> {
> > + // Per defect report (no number yet):
> > + // ... other than a pointer to the first element of a
> complete array
> > + // object.
> > + } else if (!Value.hasLValuePath() || Value.getLValuePath().size()
> ||
> > + Value.isLValueOnePastTheEnd()) {
> > + Diag(StartLoc, diag::err_non_type_template_arg_subobject)
> > + << Value.getAsString(Context, ParamType);
> > + return ExprError();
> > + }
> > + assert((VD || ParamType->isPointerType()) &&
> > + "null reference should not be a constant expression");
> > + Converted = VD ? TemplateArgument(VD, ParamType)
> > + : TemplateArgument(ParamType, /*isNullPtr*/true);
> > + break;
> > + }
> > + case APValue::AddrLabelDiff:
> > + return Diag(StartLoc,
> diag::err_non_type_template_arg_addr_label_diff);
> > + case APValue::Float:
> > + case APValue::ComplexInt:
> > + case APValue::ComplexFloat:
> > + case APValue::Vector:
> > + case APValue::Array:
> > + case APValue::Struct:
> > + case APValue::Union:
> > + llvm_unreachable("invalid kind for template argument");
> > + }
> > +
> > + return ArgResult.get();
> > + }
> > +
> > // C++ [temp.arg.nontype]p5:
> > // The following conversions are performed on each expression used
> > // as a non-type template-argument. If a non-type
> > // template-argument cannot be converted to the type of the
> > // corresponding template-parameter then the program is
> > // ill-formed.
> > - QualType ParamType = InstantiatedParamType;
> > if (ParamType->isIntegralOrEnumerationType()) {
> > // C++11:
> > // -- for a non-type template-parameter of integral or
> >
> > Modified: cfe/trunk/test/CXX/drs/dr0xx.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr0xx.cpp?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/drs/dr0xx.cpp (original)
> > +++ cfe/trunk/test/CXX/drs/dr0xx.cpp Tue Nov 25 21:26:53 2014
> > @@ -521,17 +521,28 @@ namespace dr48 { // dr48: yes
> > }
> >
> > namespace dr49 { // dr49: yes
> > - template<int*> struct A {}; // expected-note {{here}}
> > + template<int*> struct A {}; // expected-note 0-2{{here}}
> > int k;
> > #if __has_feature(cxx_constexpr)
> > constexpr
> > #endif
> > - int *const p = &k;
> > + int *const p = &k; // expected-note 0-2{{here}}
> > A<&k> a;
> > - A<p> b; // expected-error {{must have its address taken}}
> > + A<p> b;
> > +#if __cplusplus <= 201402L
> > + // expected-error at -2 {{must have its address taken}}
> > +#endif
> > +#if __cplusplus < 201103L
> > + // expected-error at -5 {{internal linkage}}
> > +#endif
> > + int *q = &k;
> > + A<q> c;
> > #if __cplusplus < 201103L
> > - // expected-error at -2 {{internal linkage}}
> > - // expected-note at -5 {{here}}
> > + // expected-error at -2 {{must have its address taken}}
> > +#else
> > + // expected-error at -4 {{constant expression}}
> > + // expected-note at -5 {{read of non-constexpr}}
> > + // expected-note at -7 {{declared here}}
> > #endif
> > }
> >
> > @@ -995,6 +1006,10 @@ namespace dr92 { // dr92: yes
> > g(q); // expected-error {{is not superset}}
> > }
> >
> > + // Prior to C++17, this is OK because the exception specification is
> not
> > + // considered in this context. In C++17, we *do* perform an implicit
> > + // conversion (which performs initialization), but we convert to the
> type of
> > + // the template parameter, which does not include the exception
> specification.
> > template<void() throw()> struct X {};
> > X<&f> xp; // ok
> > }
> >
> > Modified: cfe/trunk/test/CXX/drs/dr1xx.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/drs/dr1xx.cpp (original)
> > +++ cfe/trunk/test/CXX/drs/dr1xx.cpp Tue Nov 25 21:26:53 2014
> > @@ -4,8 +4,8 @@
> > // RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify
> -fexceptions -fcxx-exceptions -pedantic-errors
> >
> > namespace dr100 { // dr100: yes
> > - template<const char *> struct A {}; // expected-note {{declared here}}
> > - template<const char (&)[4]> struct B {}; // expected-note {{declared
> here}}
> > + template<const char *> struct A {}; // expected-note 0-1{{declared
> here}}
> > + template<const char (&)[4]> struct B {}; // expected-note
> 0-1{{declared here}}
> > A<"foo"> a; // expected-error {{does not refer to any declaration}}
> > B<"bar"> b; // expected-error {{does not refer to any declaration}}
> > }
> >
> > Modified: cfe/trunk/test/CXX/drs/dr2xx.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr2xx.cpp?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/drs/dr2xx.cpp (original)
> > +++ cfe/trunk/test/CXX/drs/dr2xx.cpp Tue Nov 25 21:26:53 2014
> > @@ -991,12 +991,11 @@ namespace dr289 { // dr289: yes
> > namespace dr294 { // dr294: no
> > void f() throw(int);
> > int main() {
> > - // FIXME: we reject this for the wrong reason, because we don't
> implement
> > - // dr87 yet.
> > - (void)static_cast<void (*)() throw()>(f); // expected-error {{not
> superset}}
> > - void (*p)() throw() = f; // expected-error {{not superset}}
> > -
> > + (void)static_cast<void (*)() throw()>(f); // FIXME: ill-formed
> > (void)static_cast<void (*)() throw(int)>(f); // FIXME: ill-formed
> > +
> > + void (*p)() throw() = f; // expected-error {{not superset}}
> > + void (*q)() throw(int) = f;
> > }
> > }
> >
> >
> > Modified: cfe/trunk/test/CXX/drs/dr3xx.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr3xx.cpp?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/drs/dr3xx.cpp (original)
> > +++ cfe/trunk/test/CXX/drs/dr3xx.cpp Tue Nov 25 21:26:53 2014
> > @@ -705,7 +705,7 @@ namespace dr354 { // dr354: yes c++11
> > // FIXME: Should we allow this in C++98 too?
> > struct S {};
> >
> > - template<int*> struct ptr {}; // expected-note +{{here}}
> > + template<int*> struct ptr {}; // expected-note 0-4{{here}}
> > ptr<0> p0;
> > ptr<(int*)0> p1;
> > ptr<(float*)0> p2;
> > @@ -715,11 +715,16 @@ namespace dr354 { // dr354: yes c++11
> > // expected-error at -5 {{does not refer to any decl}}
> > // expected-error at -5 {{does not refer to any decl}}
> > // expected-error at -5 {{does not refer to any decl}}
> > -#else
> > +#elif __cplusplus <= 201402L
> > // expected-error at -10 {{must be cast}}
> > // ok
> > // expected-error at -10 {{does not match}}
> > // expected-error at -10 {{does not match}}
> > +#else
> > + // expected-error at -15 {{conversion from 'int' to 'int *' is not
> allowed}}
> > + // ok
> > + // expected-error at -15 {{'float *' is not implicitly convertible to
> 'int *'}}
> > + // expected-error at -15 {{'int dr354::S::*' is not implicitly
> convertible to 'int *'}}
> > #endif
> >
> > template<int*> int both();
> > @@ -732,7 +737,7 @@ namespace dr354 { // dr354: yes c++11
> > // expected-note at -6 {{candidate}}
> > #endif
> >
> > - template<int S::*> struct ptr_mem {}; // expected-note +{{here}}
> > + template<int S::*> struct ptr_mem {}; // expected-note 0-4{{here}}
> > ptr_mem<0> m0;
> > ptr_mem<(int S::*)0> m1;
> > ptr_mem<(float S::*)0> m2;
> > @@ -742,11 +747,16 @@ namespace dr354 { // dr354: yes c++11
> > // expected-error at -5 {{is not a pointer to member constant}}
> > // expected-error at -5 {{cannot be converted}}
> > // expected-error at -5 {{cannot be converted}}
> > -#else
> > +#elif __cplusplus <= 201402L
> > // expected-error at -10 {{must be cast}}
> > // ok
> > // expected-error at -10 {{does not match}}
> > // expected-error at -10 {{does not match}}
> > +#else
> > + // expected-error at -15 {{conversion from 'int' to 'int dr354::S::*'
> is not allowed}}
> > + // ok
> > + // expected-error at -15 {{'float dr354::S::*' is not implicitly
> convertible to 'int dr354::S::*'}}
> > + // expected-error at -15 {{'int *' is not implicitly convertible to
> 'int dr354::S::*'}}
> > #endif
> > }
> >
> >
> > Modified: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp (original)
> > +++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp Tue Nov 25 21:26:53 2014
> > @@ -131,14 +131,14 @@ namespace IncompleteClassTypeAddr {
> > namespace UndefinedBehavior {
> > void f(int n) {
> > switch (n) {
> > - case (int)4.4e9: // expected-error {{constant expression}}
> expected-note {{value 4.4E+9 is outside the range of representable values
> of type 'int'}} expected-note {{previous case defined here}}
> > + case (int)4.4e9: // expected-error {{constant expression}}
> expected-note {{value 4.4E+9 is outside the range of representable values
> of type 'int'}}
> > case (int)0x80000000u: // ok
> > case (int)10000000000ll: // expected-note {{here}}
> > case (unsigned int)10000000000ll: // expected-error {{duplicate
> case value}}
> > case (int)(unsigned)(long long)4.4e9: // ok
> > - case (int)(float)1e300: // expected-error {{constant expression}}
> expected-note {{value 1.0E+300 is outside the range of representable values
> of type 'float'}} expected-error {{duplicate case value '2147483647'}}
> expected-note {{previous case defined here}}
> > + case (int)(float)1e300: // expected-error {{constant expression}}
> expected-note {{value 1.0E+300 is outside the range of representable values
> of type 'float'}}
> > case (int)((float)1e37 / 1e30): // ok
> > - case (int)(__fp16)65536: // expected-error {{constant expression}}
> expected-note {{value 65536 is outside the range of representable values of
> type '__fp16'}} expected-error {{duplicate case value '2147483647'}}
> > + case (int)(__fp16)65536: // expected-error {{constant expression}}
> expected-note {{value 65536 is outside the range of representable values of
> type '__fp16'}}
> > break;
> > }
> > }
> >
> > Added: cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp?rev=222807&view=auto
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp (added)
> > +++ cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp Tue Nov 25
> 21:26:53 2014
> > @@ -0,0 +1,112 @@
> > +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
> > +
> > +template<typename T, T val> struct A {};
> > +
> > +template<typename T, typename U> constexpr bool is_same = false; //
> expected-note +{{here}}
> > +template<typename T> constexpr bool is_same<T, T> = true;
> > +
> > +namespace String {
> > + A<const char*, "test"> a; // expected-error {{does not refer to any
> declaration}}
> > + A<const char (&)[5], "test"> b; // expected-error {{does not refer to
> any declaration}}
> > +}
> > +
> > +namespace Array {
> > + char arr[3];
> > + char x;
> > + A<const char*, arr> a;
> > + A<const char(&)[3], arr> b;
> > + A<const char*, &arr[0]> c;
> > + A<const char*, &arr[1]> d; // expected-error {{refers to subobject
> '&arr[1]'}}
> > + A<const char*, (&arr)[0]> e;
> > + A<const char*, &x> f;
> > + A<const char*, &(&x)[0]> g;
> > + A<const char*, &(&x)[1]> h; // expected-error {{refers to subobject
> '&x + 1'}}
> > + A<const char*, 0> i; // expected-error {{not allowed in a converted
> constant}}
> > + A<const char*, nullptr> j;
> > +}
> > +
> > +namespace Function {
> > + void f();
> > + void g() noexcept;
> > + void h();
> > + void h(int);
> > + template<typename...T> void i(T...);
> > + typedef A<void (*)(), f> a;
> > + typedef A<void (*)(), &f> a;
> > + typedef A<void (*)(), g> b;
> > + typedef A<void (*)(), &g> b;
> > + typedef A<void (*)(), h> c;
> > + typedef A<void (*)(), &h> c;
> > + typedef A<void (*)(), i> d;
> > + typedef A<void (*)(), &i> d;
> > + typedef A<void (*)(), i<>> d;
> > + typedef A<void (*)(), i<int>> e; // expected-error {{is not
> implicitly convertible}}
> > +
> > + typedef A<void (*)(), 0> x; // expected-error {{not allowed in a
> converted constant}}
> > + typedef A<void (*)(), nullptr> y;
> > +}
> > +
> > +void Func() {
> > + A<const char*, __func__> a; // expected-error {{does not refer to any
> declaration}}
> > +}
> > +
> > +namespace LabelAddrDiff {
> > + void f() {
> > + a: b: A<int, __builtin_constant_p(true) ? (long)&&b - (long)&&a :
> 0> s; // expected-error {{label address difference}}
> > + };
> > +}
> > +
> > +namespace Temp {
> > + struct S { int n; };
> > + constexpr S &addr(S &&s) { return s; }
> > + A<S &, addr({})> a; // expected-error {{constant}} expected-note
> 2{{temporary}}
> > + A<S *, &addr({})> b; // expected-error {{constant}} expected-note
> 2{{temporary}}
> > + A<int &, addr({}).n> c; // expected-error {{constant}} expected-note
> 2{{temporary}}
> > + A<int *, &addr({}).n> d; // expected-error {{constant}} expected-note
> 2{{temporary}}
> > +}
> > +
> > +namespace std { struct type_info; }
> > +
> > +namespace RTTI {
> > + A<const std::type_info&, typeid(int)> a; // expected-error {{does not
> refer to any declaration}}
> > + A<const std::type_info*, &typeid(int)> b; // expected-error {{does
> not refer to any declaration}}
> > +}
> > +
> > +namespace PtrMem {
> > + struct B { int b; };
> > + struct C : B {};
> > + struct D : B {};
> > + struct E : C, D { int e; };
> > +
> > + constexpr int B::*b = &B::b;
> > + constexpr int C::*cb = b;
> > + constexpr int D::*db = b;
> > + constexpr int E::*ecb = cb; // expected-note +{{here}}
> > + constexpr int E::*edb = db; // expected-note +{{here}}
> > +
> > + constexpr int E::*e = &E::e;
> > + constexpr int D::*de = (int D::*)e;
> > + constexpr int C::*ce = (int C::*)e;
> > + constexpr int B::*bde = (int B::*)de; // expected-note +{{here}}
> > + constexpr int B::*bce = (int B::*)ce; // expected-note +{{here}}
> > +
> > + // FIXME: This should all be accepted, but we don't yet have a
> representation
> > + // nor mangling for this form of template argument.
> > + using Ab = A<int B::*, b>;
> > + using Ab = A<int B::*, &B::b>;
> > + using Abce = A<int B::*, bce>; // expected-error {{not supported}}
> > + using Abde = A<int B::*, bde>; // expected-error {{not supported}}
> > + static_assert(!is_same<Ab, Abce>, ""); // expected-error
> {{undeclared}} expected-error {{must be a type}}
> > + static_assert(!is_same<Ab, Abde>, ""); // expected-error
> {{undeclared}} expected-error {{must be a type}}
> > + static_assert(!is_same<Abce, Abde>, ""); // expected-error
> 2{{undeclared}} expected-error {{must be a type}}
> > + static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>,
> ""); // expected-error {{undeclared}} expected-error {{not supported}}
> > +
> > + using Ae = A<int E::*, e>;
> > + using Ae = A<int E::*, &E::e>;
> > + using Aecb = A<int E::*, ecb>; // expected-error {{not supported}}
> > + using Aedb = A<int E::*, edb>; // expected-error {{not supported}}
> > + static_assert(!is_same<Ae, Aecb>, ""); // expected-error
> {{undeclared}} expected-error {{must be a type}}
> > + static_assert(!is_same<Ae, Aedb>, ""); // expected-error
> {{undeclared}} expected-error {{must be a type}}
> > + static_assert(!is_same<Aecb, Aedb>, ""); // expected-error
> 2{{undeclared}} expected-error {{must be a type}}
> > + static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>,
> ""); // expected-error {{undeclared}} expected-error {{not supported}}
> > +}
> >
> > Modified: cfe/trunk/www/cxx_status.html
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=222807&r1=222806&r2=222807&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/www/cxx_status.html (original)
> > +++ cfe/trunk/www/cxx_status.html Tue Nov 25 21:26:53 2014
> > @@ -533,7 +533,7 @@ as the draft C++1z standard evolves.</p>
> > <!-- Rapperswil papers -->
> > <tr>
> > <td>Disabling trigraph expansion by default</td>
> > - <td><a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3981.html
> ">N3981</a></td>
> > + <td><a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4086.html
> ">N4086</a></td>
> > <td class="full" align="center">Clang 3.5</td>
> > </tr>
> > <tr>
> > @@ -546,6 +546,11 @@ as the draft C++1z standard evolves.</p>
> > <td><a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4051.html
> ">N4051</a></td>
> > <td class="full" align="center">Clang 3.5</td>
> > </tr>
> > + <tr>
> > + <td>New <tt>auto</tt> rules for direct-list-initialization
> > + <td><a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3922.html
> ">N3922</a></td>
> > + <td class="no" align="center">No</td>
> > + </tr>
> > <!-- Urbana papers -->
> > <tr>
> > <td>Fold expressions</td>
> > @@ -567,6 +572,11 @@ as the draft C++1z standard evolves.</p>
> > <td><!--<a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4266.html
> ">-->N4266<!--</a>--></td>
> > <td class="svn" align="center">SVN</td>
> > </tr>
> > + <tr>
> > + <td>Allow constant evaluation for all non-type template
> arguments</td>
> > + <td><!--<a href="
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4268.html
> ">-->N4268<!--</a>--></td>
> > + <td class="svn" align="center">SVN</td>
> > + </tr>
> > </table>
> >
> > <h2 id="ts">Technical specifications and standing documents</h2>
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141126/c070490b/attachment.html>
More information about the cfe-commits
mailing list