On Wed, Nov 26, 2014 at 6:19 AM, Aaron Ballman <[email protected]> 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 > <[email protected]> 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@-2 {{must have its address taken}} > > +#endif > > +#if __cplusplus < 201103L > > + // expected-error@-5 {{internal linkage}} > > +#endif > > + int *q = &k; > > + A<q> c; > > #if __cplusplus < 201103L > > - // expected-error@-2 {{internal linkage}} > > - // expected-note@-5 {{here}} > > + // expected-error@-2 {{must have its address taken}} > > +#else > > + // expected-error@-4 {{constant expression}} > > + // expected-note@-5 {{read of non-constexpr}} > > + // expected-note@-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@-5 {{does not refer to any decl}} > > // expected-error@-5 {{does not refer to any decl}} > > // expected-error@-5 {{does not refer to any decl}} > > -#else > > +#elif __cplusplus <= 201402L > > // expected-error@-10 {{must be cast}} > > // ok > > // expected-error@-10 {{does not match}} > > // expected-error@-10 {{does not match}} > > +#else > > + // expected-error@-15 {{conversion from 'int' to 'int *' is not > allowed}} > > + // ok > > + // expected-error@-15 {{'float *' is not implicitly convertible to > 'int *'}} > > + // expected-error@-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@-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@-5 {{is not a pointer to member constant}} > > // expected-error@-5 {{cannot be converted}} > > // expected-error@-5 {{cannot be converted}} > > -#else > > +#elif __cplusplus <= 201402L > > // expected-error@-10 {{must be cast}} > > // ok > > // expected-error@-10 {{does not match}} > > // expected-error@-10 {{does not match}} > > +#else > > + // expected-error@-15 {{conversion from 'int' to 'int dr354::S::*' > is not allowed}} > > + // ok > > + // expected-error@-15 {{'float dr354::S::*' is not implicitly > convertible to 'int dr354::S::*'}} > > + // expected-error@-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 > > [email protected] > > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
