[clang] e97e985 - [c++20] For P0732R2: permit class template argument deduction for non-type template parameters.
Nico Weber via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 27 17:07:59 PDT 2020
gcc points out that DTST is unused in
+ if (auto *DTST =
dyn_cast<DeducedTemplateSpecializationType>(DeducedT)) {
Should it be used? Or should we delete the lhs of that assignment?
On Wed, Oct 21, 2020 at 6:03 PM Richard Smith via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
>
> Author: Richard Smith
> Date: 2020-10-21T15:03:22-07:00
> New Revision: e97e9851b227e98e39c27c4c8f5558e331cde8b4
>
> URL:
> https://github.com/llvm/llvm-project/commit/e97e9851b227e98e39c27c4c8f5558e331cde8b4
> DIFF:
> https://github.com/llvm/llvm-project/commit/e97e9851b227e98e39c27c4c8f5558e331cde8b4.diff
>
> LOG: [c++20] For P0732R2: permit class template argument deduction for
> non-type template parameters.
>
> Added:
> clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p2.cpp
> clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-cxx20.cpp
>
> Modified:
> clang/lib/Sema/SemaTemplate.cpp
> clang/lib/Sema/SemaTemplateDeduction.cpp
> clang/lib/Sema/SemaType.cpp
> clang/test/SemaTemplate/deduction.cpp
> clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
>
> Removed:
>
>
>
>
> ################################################################################
> diff --git a/clang/lib/Sema/SemaTemplate.cpp
> b/clang/lib/Sema/SemaTemplate.cpp
> index 8bff982d66be..d23ad9f7d91d 100644
> --- a/clang/lib/Sema/SemaTemplate.cpp
> +++ b/clang/lib/Sema/SemaTemplate.cpp
> @@ -23,6 +23,7 @@
> #include "clang/Basic/Stack.h"
> #include "clang/Basic/TargetInfo.h"
> #include "clang/Sema/DeclSpec.h"
> +#include "clang/Sema/Initialization.h"
> #include "clang/Sema/Lookup.h"
> #include "clang/Sema/Overload.h"
> #include "clang/Sema/ParsedTemplate.h"
> @@ -6807,14 +6808,15 @@ ExprResult
> Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
> SourceLocation StartLoc = Arg->getBeginLoc();
>
> // If the parameter type somehow involves auto, deduce the type now.
> - if (getLangOpts().CPlusPlus17 && ParamType->isUndeducedType()) {
> + DeducedType *DeducedT = ParamType->getContainedDeducedType();
> + if (getLangOpts().CPlusPlus17 && DeducedT && !DeducedT->isDeduced()) {
> // During template argument deduction, we allow 'decltype(auto)' to
> // match an arbitrary dependent argument.
> // FIXME: The language rules don't say what happens in this case.
> // FIXME: We get an opaque dependent type out of decltype(auto) if the
> // expression is merely instantiation-dependent; is this enough?
> if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) {
> - auto *AT = dyn_cast<AutoType>(ParamType);
> + auto *AT = dyn_cast<AutoType>(DeducedT);
> if (AT && AT->isDecltypeAuto()) {
> Converted = TemplateArgument(Arg);
> return Arg;
> @@ -6828,14 +6830,26 @@ ExprResult
> Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
> Expr *DeductionArg = Arg;
> if (auto *PE = dyn_cast<PackExpansionExpr>(DeductionArg))
> DeductionArg = PE->getPattern();
> - if (DeduceAutoType(
> - Context.getTrivialTypeSourceInfo(ParamType,
> Param->getLocation()),
> - DeductionArg, ParamType, Depth,
> - // We do not check constraints right now because the
> - // immediately-declared constraint of the auto type is also an
> - // associated constraint, and will be checked along with the
> other
> - // associated constraints after checking the template
> argument list.
> - /*IgnoreConstraints=*/true) == DAR_Failed) {
> + TypeSourceInfo *TSI =
> + Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation());
> + if (auto *DTST =
> dyn_cast<DeducedTemplateSpecializationType>(DeducedT)) {
> + InitializedEntity Entity =
> + InitializedEntity::InitializeTemplateParameter(ParamType,
> Param);
> + InitializationKind Kind = InitializationKind::CreateForInit(
> + DeductionArg->getBeginLoc(), /*DirectInit*/false, DeductionArg);
> + Expr *Inits[1] = {DeductionArg};
> + ParamType =
> + DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind,
> Inits);
> + if (ParamType.isNull())
> + return ExprError();
> + } else if (DeduceAutoType(
> + TSI, DeductionArg, ParamType, Depth,
> + // We do not check constraints right now because the
> + // immediately-declared constraint of the auto type is
> also
> + // an associated constraint, and will be checked along
> with
> + // the other associated constraints after checking the
> + // template argument list.
> + /*IgnoreConstraints=*/true) == DAR_Failed) {
> Diag(Arg->getExprLoc(),
> diag::err_non_type_template_parm_type_deduction_failure)
> << Param->getDeclName() << Param->getType() << Arg->getType()
> @@ -6870,9 +6884,9 @@ ExprResult
> Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
> // FIXME: If the argument type contains 'auto', we carry on and fail
> the
> // type check in order to force specific types to be more specialized
> than
> // 'auto'. It's not clear how partial ordering with 'auto' is
> supposed to
> - // work.
> + // work. Similarly for CTAD, when comparing 'A<x>' against 'A'.
> if ((ParamType->isDependentType() || Arg->isTypeDependent()) &&
> - !Arg->getType()->getContainedAutoType()) {
> + !Arg->getType()->getContainedDeducedType()) {
> Converted = TemplateArgument(Arg);
> return Arg;
> }
>
> diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp
> b/clang/lib/Sema/SemaTemplateDeduction.cpp
> index 1c20ca619138..886377108e3f 100644
> --- a/clang/lib/Sema/SemaTemplateDeduction.cpp
> +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
> @@ -1615,14 +1615,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
> return Sema::TDK_Success;
> }
> } else if (!Param->isDependentType()) {
> - CanQualType ParamUnqualType = CanParam.getUnqualifiedType(),
> - ArgUnqualType = CanArg.getUnqualifiedType();
> - bool Success =
> - (TDF & TDF_AllowCompatibleFunctionType)
> - ? S.isSameOrCompatibleFunctionType(ParamUnqualType,
> ArgUnqualType)
> - : ParamUnqualType == ArgUnqualType;
> - if (Success)
> + if (!(TDF & TDF_SkipNonDependent)) {
> + CanQualType ParamUnqualType = CanParam.getUnqualifiedType(),
> + ArgUnqualType = CanArg.getUnqualifiedType();
> + bool Success =
> + (TDF & TDF_AllowCompatibleFunctionType)
> + ? S.isSameOrCompatibleFunctionType(ParamUnqualType,
> ArgUnqualType)
> + : ParamUnqualType == ArgUnqualType;
> + if (Success)
> + return Sema::TDK_Success;
> + } else {
> return Sema::TDK_Success;
> + }
> }
>
> switch (Param->getTypeClass()) {
>
> diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
> index 4d156634bf48..1ba1869e0fe5 100644
> --- a/clang/lib/Sema/SemaType.cpp
> +++ b/clang/lib/Sema/SemaType.cpp
> @@ -3375,8 +3375,9 @@ static QualType
> GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
> Error = 7; // Exception declaration
> break;
> case DeclaratorContext::TemplateParamContext:
> - if (isa<DeducedTemplateSpecializationType>(Deduced))
> - Error = 19; // Template parameter
> + if (isa<DeducedTemplateSpecializationType>(Deduced) &&
> + !SemaRef.getLangOpts().CPlusPlus20)
> + Error = 19; // Template parameter (until C++20)
> else if (!SemaRef.getLangOpts().CPlusPlus17)
> Error = 8; // Template parameter (until C++17)
> break;
>
> diff --git
> a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p2.cpp
> b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p2.cpp
> new file mode 100644
> index 000000000000..8468731a3cb0
> --- /dev/null
> +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p2.cpp
> @@ -0,0 +1,23 @@
> +// RUN: %clang_cc1 -std=c++17 -verify=expected,cxx17 %s
> +// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20 %s
> +
> +template<typename T> struct A { constexpr A(T) {} }; // expected-note
> 1+{{here}}
> +
> +A a = 0;
> +A b(0);
> +A c = A(0);
> +A d = A{0};
> +auto *p = new A(0);
> +A *q = new A(0); // expected-error {{cannot form pointer to deduced class
> template specialization type}}
> +
> +struct B {
> + operator A() { // expected-error {{argument deduction not allowed in
> conversion function type}}
> + return A(0);
> + }
> +};
> +
> +void f(A a); // expected-error {{argument deduction not allowed in
> function prototype}}
> +A f(); // expected-error {{argument deduction not allowed in function
> return type}}
> +
> +template<A a> // cxx17-error {{argument deduction not allowed in template
> parameter}}
> +void f();
>
> diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-cxx20.cpp
> b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-cxx20.cpp
> new file mode 100644
> index 000000000000..d6d2ad742d0e
> --- /dev/null
> +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-cxx20.cpp
> @@ -0,0 +1,23 @@
> +// RUN: %clang_cc1 -std=c++20 %s -verify
> +
> +using size_t = __SIZE_TYPE__;
> +
> +namespace CTAD {
> + template<typename T> struct A { constexpr A(T) {} };
> + template<A a> using DeducedA = decltype(a);
> +
> + using ATest1 = DeducedA<A(0)>;
> + using ATest1 = A<int>; // expected-note {{previous}}
> + using ATest1 = void; // expected-error {{
> diff erent}}
> +
> + using ATest2 = DeducedA<A(0.0)>;
> + using ATest2 = A<double>;
> +
> + template <size_t N> struct B {
> + constexpr B(const char (&r)[N]) { __builtin_memcpy(text, r, N); }
> + char text[N];
> + };
> +
> + template<B b> constexpr const char *str() { return b.text; }
> + static_assert(__builtin_strcmp("hello world", str<"hello world">()) ==
> 0);
> +}
>
> diff --git a/clang/test/SemaTemplate/deduction.cpp
> b/clang/test/SemaTemplate/deduction.cpp
> index a068bcaea048..b9a1f0dccb24 100644
> --- a/clang/test/SemaTemplate/deduction.cpp
> +++ b/clang/test/SemaTemplate/deduction.cpp
> @@ -312,6 +312,13 @@ namespace nullptr_deduction {
> f(X<nullptr_t, nullptr>()); // expected-note {{instantiation of}}
> }
>
> + template<template<typename T, T> class X, typename T, int *P>
> + void f0(X<T, P>) {} // expected-note {{deduced non-type template
> argument does not have the same type as the corresponding template
> parameter ('nullptr_t' vs 'int *')}}
> + void h0() {
> + f0(X<int*, nullptr>());
> + f0(X<nullptr_t, nullptr>()); // expected-error {{no matching
> function}}
> + }
> +
> template<template<typename T, T> class X, typename T, typename U, int
> *P>
> void f1(X<T, P>, X<U, P>) {} // expected-note 2{{values of
> conflicting types}}
> void h() {
>
> diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
> b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
> index d0ace9b2b2b5..1d9fefb6cbe5 100644
> --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
> +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
> @@ -124,8 +124,7 @@ namespace StableAddress {
> // FIXME: Deduction guide not needed with P1816R0.
> template<size_t N> str(const char (&)[N]) -> str<N>;
>
> - // FIXME: Explicit size not needed.
> - template<str<15> s> constexpr int sum() {
> + template<str s> constexpr int sum() {
> int n = 0;
> for (char c : s.arr)
> n += c;
> @@ -184,3 +183,21 @@ namespace Diags {
> template<A a> struct X { static_assert(a.n == a.m); }; //
> expected-error {{static_assert failed due to requirement 'Diags::A{1, 2}.n
> == Diags::A{1, 2}.m'}}
> template struct X<A{1, 2}>; // expected-note {{in instantiation of
> template class 'Diags::X<{1, 2}>' requested here}}
> }
> +
> +namespace CTADPartialOrder {
> + template<int> struct A {};
> + template<typename T, typename U, A a> struct X; // expected-note
> {{declared here}}
> + template<typename T, A a> struct X<T, int, a> { static constexpr int n
> = 1; }; // expected-note {{matches}}
> + template<typename T, A a> struct X<T *, int, a> { static constexpr int
> n = 2; };
> + template<typename T, A a> struct X<T, T, a> { static constexpr int n =
> 3; }; // expected-note {{matches}}
> +
> + A<0> a;
> + static_assert(X<void, int, a>::n == 1);
> + static_assert(X<int*, int, a>::n == 2);
> + static_assert(X<void, void, a>::n == 3);
> + static_assert(X<int, int, a>::n == -1); // expected-error {{ambiguous}}
> + static_assert(X<int*, void, a>::n == 2); // expected-error {{undefined}}
> +
> + template<typename T, A<0> a> struct X<T, T, a> { static constexpr int n
> = 4; };
> + static_assert(X<float, float, a>::n == 4);
> +}
>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20201027/6566f753/attachment-0001.html>
More information about the cfe-commits
mailing list