From 52e624f3ecbe1e44d92e28b2b7506796974db697 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 21 Dec 2016 21:42:57 +0000 Subject: [PATCH] Perform type-checking for a converted constant expression in a template argument even if the expression is value-dependent (we need to suppress the final portion of the narrowing check, but the rest of the checking can still be done eagerly). This affects template template argument validity and partial ordering under p0522r0. llvm-svn: 290276 --- clang/include/clang/Sema/Overload.h | 6 ++++- clang/lib/Sema/SemaInit.cpp | 3 ++- clang/lib/Sema/SemaOverload.cpp | 23 +++++++++++++++++++ clang/lib/Sema/SemaTemplate.cpp | 14 +++++------ .../SemaTemplate/temp_arg_nontype_cxx1z.cpp | 4 ++-- 5 files changed, 39 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 7c6699aca01d..03c6a3e75b61 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -121,7 +121,11 @@ namespace clang { /// A narrowing conversion, because a non-constant-expression variable might /// have got narrowed. - NK_Variable_Narrowing + NK_Variable_Narrowing, + + /// Cannot tell whether this is a narrowing conversion because the + /// expression is value-dependent. + NK_Dependent_Narrowing, }; /// StandardConversionSequence - represents a standard conversion diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 5bb5518c58b9..8ab14b2a63f1 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6816,7 +6816,7 @@ InitializationSequence::Perform(Sema &S, CurInit = CurInitExprRes; if (Step->Kind == SK_ConversionSequenceNoNarrowing && - S.getLangOpts().CPlusPlus && !CurInit.get()->isValueDependent()) + S.getLangOpts().CPlusPlus) DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(), CurInit.get()); @@ -8070,6 +8070,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue, ConstantType)) { case NK_Not_Narrowing: + case NK_Dependent_Narrowing: // No narrowing occurred. return; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 2129729dab9f..fb378b86af75 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -329,6 +329,11 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) { llvm::APSInt IntConstantValue; const Expr *Initializer = IgnoreNarrowingConversion(Converted); + + // If it's value-dependent, we can't tell whether it's narrowing. + if (Initializer->isValueDependent()) + return NK_Dependent_Narrowing; + if (Initializer && Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { // Convert the integer to the floating type. @@ -362,6 +367,11 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, Ctx.getFloatingTypeOrder(FromType, ToType) == 1) { // FromType is larger than ToType. const Expr *Initializer = IgnoreNarrowingConversion(Converted); + + // If it's value-dependent, we can't tell whether it's narrowing. + if (Initializer->isValueDependent()) + return NK_Dependent_Narrowing; + if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) { // Constant! assert(ConstantValue.isFloat()); @@ -403,6 +413,11 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, // Not all values of FromType can be represented in ToType. llvm::APSInt InitializerValue; const Expr *Initializer = IgnoreNarrowingConversion(Converted); + + // If it's value-dependent, we can't tell whether it's narrowing. + if (Initializer->isValueDependent()) + return NK_Dependent_Narrowing; + if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { // Such conversions on variables are always narrowing. return NK_Variable_Narrowing; @@ -5289,6 +5304,9 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, QualType PreNarrowingType; switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue, PreNarrowingType)) { + case NK_Dependent_Narrowing: + // Implicit conversion to a narrower type, but the expression is + // value-dependent so we can't tell whether it's actually narrowing. 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. @@ -5307,6 +5325,11 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, break; } + if (Result.get()->isValueDependent()) { + Value = APValue(); + return Result; + } + // Check the expression is a constant expression. SmallVector Notes; Expr::EvalResult Eval; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9d4029a91247..80567c309c5e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5059,13 +5059,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } 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. @@ -5075,6 +5068,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (ArgResult.isInvalid()) return ExprError(); + // For a value-dependent argument, CheckConvertedConstantExpression is + // permitted (and expected) to be unable to determine a value. + if (ArgResult.get()->isValueDependent()) { + Converted = TemplateArgument(Arg); + return Arg; + } + QualType CanonParamType = Context.getCanonicalType(ParamType); // Convert the APValue to a TemplateArgument. diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp index 59b05a14d3f6..3219258572aa 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -122,13 +122,13 @@ namespace DeduceDifferentType { int a_exp = a<3>(A<3>()); template struct B {}; - template int b(B

); // expected-note {{does not have the same type}} expected-note {{not implicitly convertible}} + template int b(B

); // expected-error {{value of type 'int *' is not implicitly convertible to 'decltype(nullptr)'}} int b_imp = b(B()); // expected-error {{no matching function}} int b_exp = b(B()); // expected-error {{no matching function}} struct X { constexpr operator int() { return 0; } } x; template struct C {}; - template int c(C); // expected-note {{does not have the same type}} expected-note {{not implicitly convertible}} + template int c(C); // expected-error {{value of type 'int' is not implicitly convertible to 'DeduceDifferentType::X &'}} int c_imp = c(C()); // expected-error {{no matching function}} int c_exp = c(C()); // expected-error {{no matching function}}