[clang] [clang] CTAD alias: Fix missing template arg packs during the transformation (PR #92535)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/92535 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema] Fix an out-of-bounds crash when diagnosing bad conversion for a function with a parameter pack. (PR #92721)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/92721 None >From 2aa2caf15282d28e9fda99d51776d842d3d57e95 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sun, 19 May 2024 22:47:14 +0200 Subject: [PATCH] [Sema] Fix an out-of-bounds crash when diagnosing bad conversion for a function with a parameter pack. --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/SemaOverload.cpp | 10 -- clang/test/Misc/diag-overload-cand-ranges.cpp | 8 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index be4cded276321..de3d258ae578a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -573,6 +573,8 @@ Bug Fixes in This Version - Clang now correctly disallows VLA type compound literals, e.g. ``(int[size]){}``, as the C standard mandates. (#GH89835) +- Fix an out-of-bounds crash when diagnosing bad conversion for a function with a parameter pack. + Bug Fixes to Compiler Builtins ^^ diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 2eb25237a0de6..73a175f724402 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -11298,8 +11298,14 @@ static void DiagnoseBadConversion(Sema , OverloadCandidate *Cand, Expr *FromExpr = Conv.Bad.FromExpr; QualType FromTy = Conv.Bad.getFromType(); QualType ToTy = Conv.Bad.getToType(); - SourceRange ToParamRange = - !isObjectArgument ? Fn->getParamDecl(I)->getSourceRange() : SourceRange(); + SourceRange ToParamRange; + if (!isObjectArgument) { +if (I < Fn->getNumParams()) + ToParamRange = Fn->getParamDecl(I)->getSourceRange(); +else + // parameter pack case. + ToParamRange = Fn->parameters().back()->getSourceRange(); + } if (FromTy == S.Context.OverloadTy) { assert(FromExpr && "overload set argument came from implicit argument?"); diff --git a/clang/test/Misc/diag-overload-cand-ranges.cpp b/clang/test/Misc/diag-overload-cand-ranges.cpp index 080ca484d4b74..06d638d9b719c 100644 --- a/clang/test/Misc/diag-overload-cand-ranges.cpp +++ b/clang/test/Misc/diag-overload-cand-ranges.cpp @@ -70,3 +70,11 @@ template class Type1 {}; template void Function1(int zz, Type1 , int ww) {} void Function() { Function1(33, Type1<-42>(), 66); } + +// CHECK: error: no matching function for call to 'b' +// CHECK: :{[[@LINE+1]]:41-[[@LINE+1]]:45}: note: {{.*}} no known conversion from 'int' to 'ForwardClass' for 3rd argument +template void b(T, U...); +class ForwardClass; +void NoCrash() { + b(1, 1, 0); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][AST] Fix end location of DeclarationNameInfo on instantiated methods (PR #92654)
https://github.com/hokein approved this pull request. nit: add a note in `clang/docs/ReleaseNotes.rst` https://github.com/llvm/llvm-project/pull/92654 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: Fix missing template arg packs during the transformation (PR #92535)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/92535 clang rejects some valid code (see testcases) because of an incorrect transformed deduction guides. This patch fixes it. We miss the template argument packs during the transformation (`auto (type-parameter-0-0...) -> Foo<>`). In `TreeTransform::TransformTemplateArguments `, we have a logic of handling template argument packs which were originally added to support CTAD alias, it doesn't seem to be needed, we need to unpack them. >From 21ff4048fdee4f76d7d73ae9f2bfaf18614a4a3b Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 17 May 2024 14:12:04 +0200 Subject: [PATCH] [clang] CTAD alias: Fix missing template arg packs during the transformation. --- clang/lib/Sema/TreeTransform.h | 8 clang/test/AST/ast-dump-ctad-alias.cpp | 20 clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 5 + 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b10e5ba65eb1c..f9fec21bf5bb6 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4818,14 +4818,6 @@ bool TreeTransform::TransformTemplateArguments( TemplateArgumentLoc In = *First; if (In.getArgument().getKind() == TemplateArgument::Pack) { - // When building the deduction guides, we rewrite the argument packs - // instead of unpacking. - if (getSema().CodeSynthesisContexts.back().Kind == - Sema::CodeSynthesisContext::BuildingDeductionGuides) { -if (getDerived().TransformTemplateArgument(In, Out, Uneval)) - return true; -continue; - } // Unpack argument packs, which we translate them into separate // arguments. // FIXME: We could do much better if we could guarantee that the diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index 7fe6c05621eee..9382558393e4c 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -48,3 +48,23 @@ Out2::AInner t(1.0); // CHECK-NEXT: | |-TemplateArgument type 'double' // CHECK-NEXT: | | `-BuiltinType {{.*}} 'double' // CHECK-NEXT: | `-ParmVarDecl {{.*}} 'double' + +template +struct Foo { + Foo(T1...); +}; + +template +using AFoo = Foo; +AFoo a(1, 2); +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (type-parameter-0-0...) -> Foo' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0...' pack +// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (int, int) -> Foo' implicit_instantiation + +template +using BFoo = Foo; +BFoo b2(1.0, 2.0); +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (type-parameter-0-0, type-parameter-0-0) -> Foo' +// CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'type-parameter-0-0' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' +// CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (double, double) -> Foo' implicit_instantiation diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 7c186dc379c7b..479b0e3606721 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -173,6 +173,11 @@ template using AFoo = Foo; auto b = AFoo{}; +AFoo a(1, 2); + +template +using BFoo = Foo; +BFoo b2(1.0, 2.0); } // namespace test13 namespace test14 { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
@@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +// Scalar types are bitwise clonable. +static_assert(__is_bitwise_cloneable(int)); +static_assert(__is_bitwise_cloneable(int*)); +// array +static_assert(__is_bitwise_cloneable(int[10])); + +// non-scalar types. +static_assert(!__is_bitwise_cloneable(int&)); + + +struct Forward; // expected-note 2{{forward declaration of 'Forward'}} +static_assert(!__is_bitwise_cloneable(Forward)); // expected-error {{incomplete type 'Forward' used in type trait expression}} + +struct Foo { int a; }; +static_assert(__is_bitwise_cloneable(Foo)); + +struct DynamicClass { virtual int Foo(); }; +static_assert(__is_bitwise_cloneable(DynamicClass)); + +struct Bar { int& b; }; // trivially copyable +static_assert(__is_trivially_copyable(Bar)); +static_assert(__is_bitwise_cloneable(Bar)); hokein wrote: Because of the reference member `int & b`. Reference types are currently excluded in bitwise-cloneable types (references are just alias, and they cannot be reset once initialized). https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: Emit a more descriptive diagnostic message when is_deducible constraint is evaluated to false. (PR #92389)
hokein wrote: Thanks @mizvekov for the quick fix. https://github.com/llvm/llvm-project/pull/92389 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: Emit a more descriptive diagnostic message when is_deducible constraint is evaluated to false. (PR #92389)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/92389 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: Emit a more descriptive diagnostic message when is_deducible constraint is evaluated to false. (PR #92389)
@@ -111,7 +111,7 @@ struct Foo { template using Bar = Foo; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \ - // expected-note {{because '__is_deducible}} + // expected-note {{can not deduce template arguments for 'Bar' from the type 'Foo'}} hokein wrote: ah, this was left when I adjusted the message. Done. https://github.com/llvm/llvm-project/pull/92389 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: Emit a more descriptive diagnostic message when is_deducible constraint is evaluated to false. (PR #92389)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/92389 >From ada7f47eae6ef66a51cdeb91ab5aca0e188e5704 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 16 May 2024 14:05:57 +0200 Subject: [PATCH] [clang] CTAD alias: Emit a more descriptive diagnostic message when is_deducible constraint is evaluated to false. Fixes https://github.com/llvm/llvm-project/issues/92225 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaConcept.cpp | 7 +++ clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 7 +++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e648b503ac034..93fd5c16989da 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3003,6 +3003,8 @@ def note_single_arg_concept_specialization_constraint_evaluated_to_false : Note< "%select{and|because}0 %1 does not satisfy %2">; def note_atomic_constraint_evaluated_to_false_elaborated : Note< "%select{and|because}0 '%1' (%2 %3 %4) evaluated to false">; +def note_is_deducible_constraint_evaluated_to_false : Note< + "cannot deduce template arguments for %0 from %1">; def err_constrained_virtual_method : Error< "virtual function cannot have a requires clause">; def err_trailing_requires_clause_on_deduction_guide : Error< diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 7bfec4e11f7aa..202dd86c67f62 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1162,6 +1162,13 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema , break; } return; + } else if (auto *TTE = dyn_cast(SubstExpr); + TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) { +assert(TTE->getNumArgs() == 2); +S.Diag(SubstExpr->getSourceRange().getBegin(), + diag::note_is_deducible_constraint_evaluated_to_false) +<< TTE->getArg(0)->getType() << TTE->getArg(1)->getType(); +return; } S.Diag(SubstExpr->getSourceRange().getBegin(), diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 7c186dc379c7b..21b2b8bff5002 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -111,7 +111,7 @@ struct Foo { template using Bar = Foo; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \ - // expected-note {{because '__is_deducible}} + // expected-note {{cannot deduce template arguments for 'Bar' from 'Foo'}} Bar s = {{1}}; // expected-error {{no viable constructor or deduction guide }} @@ -138,7 +138,7 @@ template struct Foo { T c; }; template using AFoo = Foo; // expected-note {{candidate template ignored: could not match 'Foo' against 'int'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \ -// expected-note {{because '__is_deducible(AFoo, Foo)' evaluated to false}} \ +// expected-note {{cannot deduce template arguments for 'AFoo' from 'Foo'}} \ // expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}} @@ -196,10 +196,9 @@ template struct Foo { Foo(T); }; template using AFoo = Foo; template concept False = false; -// FIXME: emit a more descriptive diagnostic for "__is_deducible" constraint failure. template using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ - // expected-note {{because '__is_deducible(BFoo, Foo)' evaluated to false}} \ + // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo'}} \ // expected-note {{candidate template ignored: could not match 'Foo' against 'int *'}} int i = 0; AFoo a1(); // OK, deduce Foo ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: Emit a more descriptive diagnostic message when is_deducible constraint is evaluated to false. (PR #92389)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/92389 Fixes https://github.com/llvm/llvm-project/issues/92225 >From 20294489121be7a68519280da8e144c2b9be398c Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 16 May 2024 14:05:57 +0200 Subject: [PATCH] [clang] CTAD alias: Emit a more descriptive diagnostic message when is_deducible constraint is evaluated to false. Fixes https://github.com/llvm/llvm-project/issues/92225 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaConcept.cpp | 7 +++ clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 6 +++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e648b503ac034..04bf6ed2c52f5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3003,6 +3003,8 @@ def note_single_arg_concept_specialization_constraint_evaluated_to_false : Note< "%select{and|because}0 %1 does not satisfy %2">; def note_atomic_constraint_evaluated_to_false_elaborated : Note< "%select{and|because}0 '%1' (%2 %3 %4) evaluated to false">; +def note_is_deducible_constraint_evaluated_to_false : Note< + "cannot deduce template arguments of %0 from %1">; def err_constrained_virtual_method : Error< "virtual function cannot have a requires clause">; def err_trailing_requires_clause_on_deduction_guide : Error< diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 7bfec4e11f7aa..202dd86c67f62 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1162,6 +1162,13 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema , break; } return; + } else if (auto *TTE = dyn_cast(SubstExpr); + TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) { +assert(TTE->getNumArgs() == 2); +S.Diag(SubstExpr->getSourceRange().getBegin(), + diag::note_is_deducible_constraint_evaluated_to_false) +<< TTE->getArg(0)->getType() << TTE->getArg(1)->getType(); +return; } S.Diag(SubstExpr->getSourceRange().getBegin(), diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 7c186dc379c7b..f7367d01bc2eb 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -111,7 +111,7 @@ struct Foo { template using Bar = Foo; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \ - // expected-note {{because '__is_deducible}} + // expected-note {{can not deduce template arguments for 'Bar' from the type 'Foo'}} Bar s = {{1}}; // expected-error {{no viable constructor or deduction guide }} @@ -138,7 +138,7 @@ template struct Foo { T c; }; template using AFoo = Foo; // expected-note {{candidate template ignored: could not match 'Foo' against 'int'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \ -// expected-note {{because '__is_deducible(AFoo, Foo)' evaluated to false}} \ +// expected-note {{cannot deduce template arguments for 'AFoo' from 'Foo'}} \ // expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}} @@ -199,7 +199,7 @@ template concept False = false; // FIXME: emit a more descriptive diagnostic for "__is_deducible" constraint failure. template using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ - // expected-note {{because '__is_deducible(BFoo, Foo)' evaluated to false}} \ + // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo'}} \ // expected-note {{candidate template ignored: could not match 'Foo' against 'int *'}} int i = 0; AFoo a1(); // OK, deduce Foo ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AST] RecursiveASTVisitor: Don't traverse the alias deduction guides in the default mode. (PR #91454)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/91454 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Fix CXXNewExpr end source location for 'new struct S' (PR #92266)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/92266 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Fix CXXNewExpr end source location for 'new struct S' (PR #92266)
@@ -583,3 +583,8 @@ void NonADLCall3() { f(x); } } // namespace test_adl_call_three + hokein wrote: nit: wrap the code within `namespace GH35300 { ...}`. https://github.com/llvm/llvm-project/pull/92266 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Fix CXXNewExpr end source location for 'new struct S' (PR #92266)
https://github.com/hokein approved this pull request. thanks, still good. https://github.com/llvm/llvm-project/pull/92266 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AST] RecursiveASTVisitor: Don't traverse the alias deduction guides in the default mode. (PR #91454)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/91454 >From e560fe2bf2d4bdc07a71682aa4d3a4bee8730b80 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 8 May 2024 12:11:10 +0200 Subject: [PATCH 1/2] [AST] RecursiveASTVisitor: Don't traverse the alias deduction guides in default mode. --- clang/include/clang/AST/RecursiveASTVisitor.h | 28 -- .../DeductionGuide.cpp| 89 +++ 2 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index f9b145b4e86a5..2517189c95300 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -736,13 +736,27 @@ bool RecursiveASTVisitor::TraverseDecl(Decl *D) { // As a syntax visitor, by default we want to ignore declarations for // implicit declarations (ones not typed explicitly by the user). - if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) { -// For an implicit template type parameter, its type constraints are not -// implicit and are not represented anywhere else. We still need to visit -// them. -if (auto *TTPD = dyn_cast(D)) - return TraverseTemplateTypeParamDeclConstraints(TTPD); -return true; + if (!getDerived().shouldVisitImplicitCode()) { +if (D->isImplicit()) { + // For an implicit template type parameter, its type constraints are not + // implicit and are not represented anywhere else. We still need to visit + // them. + if (auto *TTPD = dyn_cast(D)) +return TraverseTemplateTypeParamDeclConstraints(TTPD); + return true; +} + +// Deduction guides for alias templates are always synthesized, so they +// should not be traversed unless shouldVisitImplicitCode() returns true. +// +// It's important to note that checking the implicit bit is not efficient +// for the alias case. For deduction guides synthesized from explicit +// user-defined deduction guides, we must maintain the explicit bit to +// ensure correct overload resolution. +if (auto *FTD = dyn_cast(D)) + if (llvm::isa_and_present( + FTD->getDeclName().getCXXDeductionGuideTemplate())) +return true; } switch (D->getKind()) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp new file mode 100644 index 0..abfdbaea4a615 --- /dev/null +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp @@ -0,0 +1,89 @@ +//===- unittest/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "TestVisitor.h" +#include + +using namespace clang; + +namespace { + +class DeductionGuideVisitor +: public ExpectedLocationVisitor { +public: + DeductionGuideVisitor(bool ShouldVisitImplicitCode) + : ShouldVisitImplicitCode(ShouldVisitImplicitCode) {} + bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { +std::string Storage; +llvm::raw_string_ostream Stream(Storage); +D->print(Stream); +Match(Stream.str(),D->getLocation()); +return true; + } + + bool shouldVisitTemplateInstantiations() const { +return false; + } + + bool shouldVisitImplicitCode() const { +return ShouldVisitImplicitCode; + } + bool ShouldVisitImplicitCode; +}; + +TEST(RecursiveASTVisitor, DeductionGuideNonImplicitMode) { + DeductionGuideVisitor Visitor(/*ShouldVisitImplicitCode*/ false); + // Verify that the synthezied deduction guide for alias is not visited in + // RAV's implicit mode. + Visitor.ExpectMatch("Foo(T) -> Foo", 11, 1); + Visitor.DisallowMatch("Bar(type-parameter-0-0) -> Foo", 14, 1); + EXPECT_TRUE(Visitor.runOver( +R"cpp( +template +concept False = true; + +template +struct Foo { + Foo(T); +}; + +template requires False +Foo(T) -> Foo; + +template +using Bar = Foo; +Bar s(1); + )cpp" + , DeductionGuideVisitor::Lang_CXX2a)); +} + +TEST(RecursiveASTVisitor, DeductionGuideImplicitMode) { + DeductionGuideVisitor Visitor(/*ShouldVisitImplicitCode*/ true); + Visitor.ExpectMatch("Foo(T) -> Foo", 11, 1); + Visitor.ExpectMatch("Bar(type-parameter-0-0) -> Foo", 14, 1); + EXPECT_TRUE(Visitor.runOver( +R"cpp( +template +concept False = true; + +template +struct Foo { + Foo(T); +}; + +template requires False +Foo(T) -> Foo; + +template +using Bar = Foo; +Bar s(1); + )cpp" + , DeductionGuideVisitor::Lang_CXX2a)); +} + +} // end anonymous namespace >From
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
@@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +// Scalar types are bitwise clonable. +static_assert(__is_bitwise_cloneable(int)); +static_assert(__is_bitwise_cloneable(int*)); +// array +static_assert(__is_bitwise_cloneable(int[10])); + +// non-scalar types. +static_assert(!__is_bitwise_cloneable(int&)); + + +struct Forward; // expected-note 2{{forward declaration of 'Forward'}} +static_assert(!__is_bitwise_cloneable(Forward)); // expected-error {{incomplete type 'Forward' used in type trait expression}} + +struct Foo { int a; }; +static_assert(__is_bitwise_cloneable(Foo)); + +struct DynamicClass { virtual int Foo(); }; +static_assert(__is_bitwise_cloneable(DynamicClass)); + +struct Bar { int& b; }; // trivially copyable +static_assert(__is_trivially_copyable(Bar)); +static_assert(__is_bitwise_cloneable(Bar)); hokein wrote: This is a tricky bit. The question arises: should we consider all trivially copyable types to be bitwise cloneable? My inclination is to say yes. Since memcpy is `safe` on all trivially copyable types, it's probably a good idea to ensure that bitwise_clonable covers as many types as possible. https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
@@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +// Scalar types are bitwise clonable. +static_assert(__is_bitwise_cloneable(int)); +static_assert(__is_bitwise_cloneable(int*)); +// array +static_assert(__is_bitwise_cloneable(int[10])); + +// non-scalar types. +static_assert(!__is_bitwise_cloneable(int&)); + + +struct Forward; // expected-note 2{{forward declaration of 'Forward'}} +static_assert(!__is_bitwise_cloneable(Forward)); // expected-error {{incomplete type 'Forward' used in type trait expression}} + +struct Foo { int a; }; +static_assert(__is_bitwise_cloneable(Foo)); + +struct DynamicClass { virtual int Foo(); }; +static_assert(__is_bitwise_cloneable(DynamicClass)); hokein wrote: Done. https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
@@ -2718,6 +2718,36 @@ bool QualType::isTriviallyCopyableType(const ASTContext ) const { /*IsCopyConstructible=*/false); } +bool QualType::isBitwiseCloneableType(const ASTContext & Context) const { + QualType CanonicalType = getCanonicalType(); + if (CanonicalType->isIncompleteType() || CanonicalType->isDependentType()) +return false; + // Trivially copyable types are bitwise clonable, e.g. scalar types. + if (CanonicalType.isTriviallyCopyableType(Context)) +return true; + + if (CanonicalType->isArrayType()) +return Context.getBaseElementType(CanonicalType) +.isBitwiseCloneableType(Context); + + if (const auto *RD = CanonicalType->getAsCXXRecordDecl()) { +for (auto Base : RD->bases()) + if (!Base.getType().isBitwiseCloneableType(Context)) +return false; +for (auto VBase : RD->vbases()) + if (!VBase.getType().isBitwiseCloneableType(Context)) +return false; + +for (auto *const Field : RD->fields()) { + QualType T = Context.getBaseElementType(Field->getType()); hokein wrote: Switched to `isBitwiseCloneableType(Field->getType())`. https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
@@ -2718,6 +2718,36 @@ bool QualType::isTriviallyCopyableType(const ASTContext ) const { /*IsCopyConstructible=*/false); } +bool QualType::isBitwiseCloneableType(const ASTContext & Context) const { + QualType CanonicalType = getCanonicalType(); + if (CanonicalType->isIncompleteType() || CanonicalType->isDependentType()) +return false; + // Trivially copyable types are bitwise clonable, e.g. scalar types. + if (CanonicalType.isTriviallyCopyableType(Context)) +return true; + + if (CanonicalType->isArrayType()) +return Context.getBaseElementType(CanonicalType) +.isBitwiseCloneableType(Context); + + if (const auto *RD = CanonicalType->getAsCXXRecordDecl()) { +for (auto Base : RD->bases()) + if (!Base.getType().isBitwiseCloneableType(Context)) hokein wrote: Good point, added a FIXME (we could use an extra bit in the class definition class to cache the result). https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
https://github.com/hokein commented: thanks for the review. https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
@@ -3958,6 +3958,50 @@ Note that the `size` argument must be a compile time constant. Note that this intrinsic cannot yet be called in a ``constexpr`` context. +``__is_bitwise_cloneable`` +- + +A type trait is used to check whether a type can be safely copied by memcpy. + +**Syntax**: + +.. code-block:: c++ + + bool __is_bitwise_cloneable(Type) + +** Example of Use**: + +.. code-block:: c++ + + // Return a cloned object of the given default instance. + Foo* Clone(const Foo* default_instance, char* buffer, unsigned size) { +if constexpr __is_bitwise_cloneable(decltype(*default_instance)) { + // Fast path via memcopy, without calling class constructor. + memcpy(buffer, default_instance, size); + // Explicitly start the lifetime of the cloned object. + return __builtin_start_object_lifetime(reinterpret_cast(buffer)); +} +// Fallback the operator new, which invoke the class constructor. +return new(buffer) Foo(*default_instance); + } + +**Description**: + +It is common for library owners to perform memcpy/memmove on types that aren't +trivally copyable for performance reason. However, according to the C++ standard, hokein wrote: Done. https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/86512 >From 10d06e728d836f4aaad7dbf1a6b06b57e4092bb1 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 25 Mar 2024 15:10:51 +0100 Subject: [PATCH 1/3] [clang] Implement a bitwise_copyable builtin type trait. This patch implements a `__is_bitwise_copyable` builtin in clang. The bitwise copyable types act as the trivially copyable types, but they support a wider range of types (e.g. classes with virtual methods) -- their underlying types can be safely copied by `memcopy` or `memmove`, the clang compiler guarantees that both source and destination objects have the same *object* representations after the copy operation, and the lifetime of the destination object implicitly starts. A particular use case of this builtin is to clone an object via memcopy (without running the constructor): ``` Message* clone(const Message* src, char* buffer, int size) { if constexpr __is_bitwise_copyable(Message) { // bitwise copy to buffer, and implicitly create objects at the buffer __builtin_memcpy(buffer, src, size); return std::launder(reinterpret_cast(buffer)); } // Fallback the operator new, which calls the constructor to start the lifetime. return new(buffer) Message(src); } ``` Note that the definition of bitwise copyable is not tied to the Rule Of Five, so users of this builtin must guarantee that program semantic constraints are satisfied, e.g. no double resource deallocations. Context: https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy --- clang/include/clang/AST/Type.h| 12 + clang/include/clang/Basic/TokenKinds.def | 1 + clang/lib/AST/Type.cpp| 23 clang/lib/Sema/SemaExprCXX.cpp| 4 +++ .../SemaCXX/builtin-is-bitwise-copyable.cpp | 26 +++ 5 files changed, 66 insertions(+) create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-copyable.cpp diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index e6643469e0b33..ff60f1c4b3520 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1120,6 +1120,18 @@ class QualType { /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext ) const; + /// Return true if this is a bitwise copyable type. + /// + /// This is an extension in clang: bitwise copyable types act as trivially + /// copyable types, underlying bytes of bitwise copyable type can be safely + /// copied by memcpy or memmove. Clang guarantees that both source and + /// destination objects have the same **object** representations after the + /// copy, and the lifetime of the destination object implicitly starts. + /// + /// bitwise copyable types cover a wider range of types, e.g. classes with + /// virtual methods. + bool isBitwiseCopyableType(const ASTContext ) const; + /// Return true if this is a trivially copyable type bool isTriviallyCopyConstructibleType(const ASTContext ) const; diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d7..ce2298543fac6 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -527,6 +527,7 @@ TYPE_TRAIT_2(__is_pointer_interconvertible_base_of, IsPointerInterconvertibleBas #include "clang/Basic/TransformTypeTraits.def" // Clang-only C++ Type Traits +TYPE_TRAIT_1(__is_bitwise_copyable, IsBitwiseCopyable, KEYCXX) TYPE_TRAIT_1(__is_trivially_relocatable, IsTriviallyRelocatable, KEYCXX) TYPE_TRAIT_1(__is_trivially_equality_comparable, IsTriviallyEqualityComparable, KEYCXX) TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e31741cd44240..5c0b89545a92b 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2731,6 +2731,29 @@ bool QualType::isTriviallyCopyableType(const ASTContext ) const { /*IsCopyConstructible=*/false); } +bool QualType::isBitwiseCopyableType(const ASTContext & Context) const { + QualType CanonicalType = getCanonicalType(); + if (CanonicalType->isIncompleteType() || CanonicalType->isDependentType()) +return false; + // Trivially copyable types are bitwise copyable, e.g. scalar types. + if (CanonicalType.isTriviallyCopyableType(Context)) +return true; + + if (CanonicalType->isArrayType()) +return Context.getBaseElementType(CanonicalType) +.isBitwiseCopyableType(Context); + + if (const auto *RD = CanonicalType->getAsCXXRecordDecl()) { +for (auto *const Field : RD->fields()) { + QualType T = Context.getBaseElementType(Field->getType()); + if (!T.isBitwiseCopyableType(Context)) +return false; +} +return true; + } + return false; +} + bool QualType::isTriviallyCopyConstructibleType( const
[clang] [clang-tools-extra] [clang] Fix CXXNewExpr end source location for 'new struct S' (PR #92266)
@@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s hokein wrote: For ast-dump lit tests, we usually place them in `clang/test/AST/` dir with name `ast-dump*.cpp` (or we can add it to the existing `ast-dump-expr.cpp`). https://github.com/llvm/llvm-project/pull/92266 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Fix CXXNewExpr end source location for 'new struct S' (PR #92266)
https://github.com/hokein approved this pull request. thanks, this looks good to me, a small nit. https://github.com/llvm/llvm-project/pull/92266 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Fix CXXNewExpr end source location for 'new struct S' (PR #92266)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/92266 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/89358 >From 659cf5b5c1216ab9f6a8dbb63b4f93de41cd173d Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 19 Apr 2024 10:54:12 +0200 Subject: [PATCH 1/2] [clang] CTAD: implement the missing IsDeducible constraint for alias templates. Fixes https://github.com/llvm/llvm-project/issues/85192 Fixes https://github.com/llvm/llvm-project/issues/84492 - rebase to main - add release note for __is_deducible - implement diagnostics for bad argument types for __is_deducible Don't expose __is_deducible trait. Refine the implementation of hiding __is_deducible type trait. Apply approach 3. --- clang/include/clang/Basic/TokenKinds.def | 3 + clang/include/clang/Sema/Sema.h | 9 ++ clang/lib/Basic/TypeTraits.cpp | 10 +++ clang/lib/Sema/SemaExprCXX.cpp | 10 ++- clang/lib/Sema/SemaTemplate.cpp | 82 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 86 clang/test/AST/ast-dump-ctad-alias.cpp | 20 +++-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 27 -- clang/test/SemaTemplate/deduction-guide.cpp | 16 ++-- clang/www/cxx_status.html| 4 +- 10 files changed, 238 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d7..b5a0e9df9f7ae 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -538,6 +538,9 @@ TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32b..66d5e2d4a4ade 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9492,6 +9492,15 @@ class Sema final : public SemaBase { ArrayRef TemplateArgs, sema::TemplateDeductionInfo ); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo ); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo , diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index 4dbf678dc395b..8d6794223ccaf 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/Support/ErrorHandling.h" #include +#include using namespace clang; static constexpr const char *TypeTraitNames[] = { @@ -81,6 +82,15 @@ const char *clang::getTraitName(UnaryExprOrTypeTrait T) { const char *clang::getTraitSpelling(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); + if (T == BTT_IsDeducible) { +// The __is_deducible is an internal-only type trait. To hide it from +// external users, we define it with an empty spelling name, preventing the +// clang parser from recognizing its token kind. +// However, other components such as the AST dump still require the real +// type trait name. Therefore, we return the real name when needed. +assert(std::strlen(TypeTraitSpellings[T]) == 0); +return "__is_deducible"; + } return TypeTraitSpellings[T]; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 34e12078a8c92..e4601f7d6c47d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6143,7 +6143,15 @@ static bool EvaluateBinaryTypeTrait(Sema , TypeTrait BTT, const TypeSourceI return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } -default: llvm_unreachable("not a BTT"); + case BTT_IsDeducible: { +const auto *TSTToBeDeduced = cast(LhsT); +sema::TemplateDeductionInfo Info(KeyLoc); +return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: +llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/89358 >From 659cf5b5c1216ab9f6a8dbb63b4f93de41cd173d Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 19 Apr 2024 10:54:12 +0200 Subject: [PATCH 1/2] [clang] CTAD: implement the missing IsDeducible constraint for alias templates. Fixes https://github.com/llvm/llvm-project/issues/85192 Fixes https://github.com/llvm/llvm-project/issues/84492 - rebase to main - add release note for __is_deducible - implement diagnostics for bad argument types for __is_deducible Don't expose __is_deducible trait. Refine the implementation of hiding __is_deducible type trait. Apply approach 3. --- clang/include/clang/Basic/TokenKinds.def | 3 + clang/include/clang/Sema/Sema.h | 9 ++ clang/lib/Basic/TypeTraits.cpp | 10 +++ clang/lib/Sema/SemaExprCXX.cpp | 10 ++- clang/lib/Sema/SemaTemplate.cpp | 82 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 86 clang/test/AST/ast-dump-ctad-alias.cpp | 20 +++-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 27 -- clang/test/SemaTemplate/deduction-guide.cpp | 16 ++-- clang/www/cxx_status.html| 4 +- 10 files changed, 238 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d7..b5a0e9df9f7ae 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -538,6 +538,9 @@ TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32b..66d5e2d4a4ade 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9492,6 +9492,15 @@ class Sema final : public SemaBase { ArrayRef TemplateArgs, sema::TemplateDeductionInfo ); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo ); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo , diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index 4dbf678dc395b..8d6794223ccaf 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/Support/ErrorHandling.h" #include +#include using namespace clang; static constexpr const char *TypeTraitNames[] = { @@ -81,6 +82,15 @@ const char *clang::getTraitName(UnaryExprOrTypeTrait T) { const char *clang::getTraitSpelling(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); + if (T == BTT_IsDeducible) { +// The __is_deducible is an internal-only type trait. To hide it from +// external users, we define it with an empty spelling name, preventing the +// clang parser from recognizing its token kind. +// However, other components such as the AST dump still require the real +// type trait name. Therefore, we return the real name when needed. +assert(std::strlen(TypeTraitSpellings[T]) == 0); +return "__is_deducible"; + } return TypeTraitSpellings[T]; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 34e12078a8c92..e4601f7d6c47d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6143,7 +6143,15 @@ static bool EvaluateBinaryTypeTrait(Sema , TypeTrait BTT, const TypeSourceI return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } -default: llvm_unreachable("not a BTT"); + case BTT_IsDeducible: { +const auto *TSTToBeDeduced = cast(LhsT); +sema::TemplateDeductionInfo Info(KeyLoc); +return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: +llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/89358 >From 659cf5b5c1216ab9f6a8dbb63b4f93de41cd173d Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 19 Apr 2024 10:54:12 +0200 Subject: [PATCH 1/2] [clang] CTAD: implement the missing IsDeducible constraint for alias templates. Fixes https://github.com/llvm/llvm-project/issues/85192 Fixes https://github.com/llvm/llvm-project/issues/84492 - rebase to main - add release note for __is_deducible - implement diagnostics for bad argument types for __is_deducible Don't expose __is_deducible trait. Refine the implementation of hiding __is_deducible type trait. Apply approach 3. --- clang/include/clang/Basic/TokenKinds.def | 3 + clang/include/clang/Sema/Sema.h | 9 ++ clang/lib/Basic/TypeTraits.cpp | 10 +++ clang/lib/Sema/SemaExprCXX.cpp | 10 ++- clang/lib/Sema/SemaTemplate.cpp | 82 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 86 clang/test/AST/ast-dump-ctad-alias.cpp | 20 +++-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 27 -- clang/test/SemaTemplate/deduction-guide.cpp | 16 ++-- clang/www/cxx_status.html| 4 +- 10 files changed, 238 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d7..b5a0e9df9f7ae 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -538,6 +538,9 @@ TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32b..66d5e2d4a4ade 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9492,6 +9492,15 @@ class Sema final : public SemaBase { ArrayRef TemplateArgs, sema::TemplateDeductionInfo ); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo ); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo , diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index 4dbf678dc395b..8d6794223ccaf 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/Support/ErrorHandling.h" #include +#include using namespace clang; static constexpr const char *TypeTraitNames[] = { @@ -81,6 +82,15 @@ const char *clang::getTraitName(UnaryExprOrTypeTrait T) { const char *clang::getTraitSpelling(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); + if (T == BTT_IsDeducible) { +// The __is_deducible is an internal-only type trait. To hide it from +// external users, we define it with an empty spelling name, preventing the +// clang parser from recognizing its token kind. +// However, other components such as the AST dump still require the real +// type trait name. Therefore, we return the real name when needed. +assert(std::strlen(TypeTraitSpellings[T]) == 0); +return "__is_deducible"; + } return TypeTraitSpellings[T]; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 34e12078a8c92..e4601f7d6c47d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6143,7 +6143,15 @@ static bool EvaluateBinaryTypeTrait(Sema , TypeTrait BTT, const TypeSourceI return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } -default: llvm_unreachable("not a BTT"); + case BTT_IsDeducible: { +const auto *TSTToBeDeduced = cast(LhsT); +sema::TemplateDeductionInfo Info(KeyLoc); +return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: +llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/89358 >From 659cf5b5c1216ab9f6a8dbb63b4f93de41cd173d Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 19 Apr 2024 10:54:12 +0200 Subject: [PATCH 1/2] [clang] CTAD: implement the missing IsDeducible constraint for alias templates. Fixes https://github.com/llvm/llvm-project/issues/85192 Fixes https://github.com/llvm/llvm-project/issues/84492 - rebase to main - add release note for __is_deducible - implement diagnostics for bad argument types for __is_deducible Don't expose __is_deducible trait. Refine the implementation of hiding __is_deducible type trait. Apply approach 3. --- clang/include/clang/Basic/TokenKinds.def | 3 + clang/include/clang/Sema/Sema.h | 9 ++ clang/lib/Basic/TypeTraits.cpp | 10 +++ clang/lib/Sema/SemaExprCXX.cpp | 10 ++- clang/lib/Sema/SemaTemplate.cpp | 82 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 86 clang/test/AST/ast-dump-ctad-alias.cpp | 20 +++-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 27 -- clang/test/SemaTemplate/deduction-guide.cpp | 16 ++-- clang/www/cxx_status.html| 4 +- 10 files changed, 238 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d7..b5a0e9df9f7ae 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -538,6 +538,9 @@ TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6a414aa57f32b..66d5e2d4a4ade 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9492,6 +9492,15 @@ class Sema final : public SemaBase { ArrayRef TemplateArgs, sema::TemplateDeductionInfo ); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo ); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo , diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index 4dbf678dc395b..8d6794223ccaf 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/Support/ErrorHandling.h" #include +#include using namespace clang; static constexpr const char *TypeTraitNames[] = { @@ -81,6 +82,15 @@ const char *clang::getTraitName(UnaryExprOrTypeTrait T) { const char *clang::getTraitSpelling(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); + if (T == BTT_IsDeducible) { +// The __is_deducible is an internal-only type trait. To hide it from +// external users, we define it with an empty spelling name, preventing the +// clang parser from recognizing its token kind. +// However, other components such as the AST dump still require the real +// type trait name. Therefore, we return the real name when needed. +assert(std::strlen(TypeTraitSpellings[T]) == 0); +return "__is_deducible"; + } return TypeTraitSpellings[T]; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 34e12078a8c92..e4601f7d6c47d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6143,7 +6143,15 @@ static bool EvaluateBinaryTypeTrait(Sema , TypeTrait BTT, const TypeSourceI return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } -default: llvm_unreachable("not a BTT"); + case BTT_IsDeducible: { +const auto *TSTToBeDeduced = cast(LhsT); +sema::TemplateDeductionInfo Info(KeyLoc); +return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: +llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -2774,6 +2775,41 @@ Expr *transformRequireClause(Sema , FunctionTemplateDecl *FTD, return E.getAs(); } +// Build the associated constraints for the alias deduction guides. +// C++ [over.match.class.deduct]p3.3: +// The associated constraints ([temp.constr.decl]) are the conjunction of the +// associated constraints of g and a constraint that is satisfied if and only +// if the arguments of A are deducible (see below) from the return type. +Expr * +buildAssociatedConstraints(Sema , TypeAliasTemplateDecl *AliasTemplate, + FunctionTemplateDecl *FTD, + llvm::ArrayRef TransformedArgs, + QualType ReturnType) { + auto = SemaRef.Context; hokein wrote: Oops, it looks like I forgot to push one commit. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
hokein wrote: Thanks for the review. > I'll approve that modulo nit but i think we want > > * An issue to keep track of the duplication in > `FinishTemplateArgumentDeduction` Filed #92224. > * A follow up PR to improve diagnostics Filed #92225, and assigned to myself. Will do it. > Thanks! https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/89358 >From 20947c1a34fae3593a98dba125e5d70d652c7190 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 19 Apr 2024 10:54:12 +0200 Subject: [PATCH 1/2] [clang] CTAD: implement the missing IsDeducible constraint for alias templates. Fixes https://github.com/llvm/llvm-project/issues/85192 Fixes https://github.com/llvm/llvm-project/issues/84492 - rebase to main - add release note for __is_deducible - implement diagnostics for bad argument types for __is_deducible Don't expose __is_deducible trait. Refine the implementation of hiding __is_deducible type trait. Apply approach 3. --- clang/include/clang/Basic/TokenKinds.def | 3 + clang/include/clang/Sema/Sema.h | 9 ++ clang/lib/Basic/TypeTraits.cpp | 10 +++ clang/lib/Sema/SemaExprCXX.cpp | 10 ++- clang/lib/Sema/SemaTemplate.cpp | 82 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 86 clang/test/AST/ast-dump-ctad-alias.cpp | 20 +++-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 27 -- clang/test/SemaTemplate/deduction-guide.cpp | 16 ++-- clang/www/cxx_status.html| 4 +- 10 files changed, 238 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d7..b5a0e9df9f7ae 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -538,6 +538,9 @@ TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4efd3878e861b..8cee7ab2c7b4e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9597,6 +9597,15 @@ class Sema final : public SemaBase { ArrayRef TemplateArgs, sema::TemplateDeductionInfo ); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo ); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo , diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index 4dbf678dc395b..8d6794223ccaf 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/Support/ErrorHandling.h" #include +#include using namespace clang; static constexpr const char *TypeTraitNames[] = { @@ -81,6 +82,15 @@ const char *clang::getTraitName(UnaryExprOrTypeTrait T) { const char *clang::getTraitSpelling(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); + if (T == BTT_IsDeducible) { +// The __is_deducible is an internal-only type trait. To hide it from +// external users, we define it with an empty spelling name, preventing the +// clang parser from recognizing its token kind. +// However, other components such as the AST dump still require the real +// type trait name. Therefore, we return the real name when needed. +assert(std::strlen(TypeTraitSpellings[T]) == 0); +return "__is_deducible"; + } return TypeTraitSpellings[T]; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c181092113e1f..1cd912e3863d8 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6142,7 +6142,15 @@ static bool EvaluateBinaryTypeTrait(Sema , TypeTrait BTT, const TypeSourceI return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } -default: llvm_unreachable("not a BTT"); + case BTT_IsDeducible: { +const auto *TSTToBeDeduced = cast(LhsT); +sema::TemplateDeductionInfo Info(KeyLoc); +return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: +llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not
[clang] [clang-tools-extra] [Clang] Retain the angle loci for invented template parameters of constraints (PR #92104)
https://github.com/hokein approved this pull request. Thanks! https://github.com/llvm/llvm-project/pull/92104 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -2774,6 +2775,41 @@ Expr *transformRequireClause(Sema , FunctionTemplateDecl *FTD, return E.getAs(); } +// Build the associated constraints for the alias deduction guides. +// C++ [over.match.class.deduct]p3.3: +// The associated constraints ([temp.constr.decl]) are the conjunction of the +// associated constraints of g and a constraint that is satisfied if and only +// if the arguments of A are deducible (see below) from the return type. +Expr * +buildAssociatedConstraints(Sema , TypeAliasTemplateDecl *AliasTemplate, + FunctionTemplateDecl *FTD, + llvm::ArrayRef TransformedArgs, + QualType ReturnType) { + auto = SemaRef.Context; hokein wrote: Done. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -6116,6 +6116,17 @@ static bool EvaluateBinaryTypeTrait(Sema , TypeTrait BTT, const TypeSourceI tok::kw___is_pointer_interconvertible_base_of); return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); + } + case BTT_IsDeducible: { +if (const auto *TSTToBeDeduced = +LhsT->getAs()) { + sema::TemplateDeductionInfo Info(KeyLoc); + return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; +} +assert("Expect to see DeducedTemplateSpecializationType!"); hokein wrote: Switched to `cast`. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -27,7 +27,8 @@ enum TypeTrait { , #define TYPE_TRAIT_2(Spelling, Name, Key) BTT_##Name, #include "clang/Basic/TokenKinds.def" - BTT_Last = UTT_Last // BTT_Last == last BTT_XX in the enum. + BTT_Last = UTT_Last hokein wrote: Reverted the change. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -18,6 +18,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" hokein wrote: Done. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -190,13 +196,15 @@ template struct Foo { Foo(T); }; template using AFoo = Foo; template concept False = false; -template using BFoo = AFoo; +template +using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ + // expected-note {{because '__is_deducible(BFoo, Foo)' evaluated to false}} \ hokein wrote: I'd prefer to do it in a follow up (this patch is quite large already). Added a FIXME. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/89358 >From 20947c1a34fae3593a98dba125e5d70d652c7190 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 19 Apr 2024 10:54:12 +0200 Subject: [PATCH] [clang] CTAD: implement the missing IsDeducible constraint for alias templates. Fixes https://github.com/llvm/llvm-project/issues/85192 Fixes https://github.com/llvm/llvm-project/issues/84492 - rebase to main - add release note for __is_deducible - implement diagnostics for bad argument types for __is_deducible Don't expose __is_deducible trait. Refine the implementation of hiding __is_deducible type trait. Apply approach 3. --- clang/include/clang/Basic/TokenKinds.def | 3 + clang/include/clang/Sema/Sema.h | 9 ++ clang/lib/Basic/TypeTraits.cpp | 10 +++ clang/lib/Sema/SemaExprCXX.cpp | 10 ++- clang/lib/Sema/SemaTemplate.cpp | 82 +-- clang/lib/Sema/SemaTemplateDeduction.cpp | 86 clang/test/AST/ast-dump-ctad-alias.cpp | 20 +++-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 27 -- clang/test/SemaTemplate/deduction-guide.cpp | 16 ++-- clang/www/cxx_status.html| 4 +- 10 files changed, 238 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 56c4b17f769d7..b5a0e9df9f7ae 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -538,6 +538,9 @@ TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary, KEYCXX) +// IsDeducible is only used internally by clang for CTAD implementation and +// is not exposed to users. +TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4efd3878e861b..8cee7ab2c7b4e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9597,6 +9597,15 @@ class Sema final : public SemaBase { ArrayRef TemplateArgs, sema::TemplateDeductionInfo ); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo ); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo , diff --git a/clang/lib/Basic/TypeTraits.cpp b/clang/lib/Basic/TypeTraits.cpp index 4dbf678dc395b..8d6794223ccaf 100644 --- a/clang/lib/Basic/TypeTraits.cpp +++ b/clang/lib/Basic/TypeTraits.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/TypeTraits.h" #include "llvm/Support/ErrorHandling.h" #include +#include using namespace clang; static constexpr const char *TypeTraitNames[] = { @@ -81,6 +82,15 @@ const char *clang::getTraitName(UnaryExprOrTypeTrait T) { const char *clang::getTraitSpelling(TypeTrait T) { assert(T <= TT_Last && "invalid enum value!"); + if (T == BTT_IsDeducible) { +// The __is_deducible is an internal-only type trait. To hide it from +// external users, we define it with an empty spelling name, preventing the +// clang parser from recognizing its token kind. +// However, other components such as the AST dump still require the real +// type trait name. Therefore, we return the real name when needed. +assert(std::strlen(TypeTraitSpellings[T]) == 0); +return "__is_deducible"; + } return TypeTraitSpellings[T]; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c181092113e1f..1cd912e3863d8 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6142,7 +6142,15 @@ static bool EvaluateBinaryTypeTrait(Sema , TypeTrait BTT, const TypeSourceI return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); } -default: llvm_unreachable("not a BTT"); + case BTT_IsDeducible: { +const auto *TSTToBeDeduced = cast(LhsT); +sema::TemplateDeductionInfo Info(KeyLoc); +return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: +llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not
[clang] [clang] CTAD alias: fix the transformation for the require-clause expr (PR #90961)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/90961 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: fix the transformation for the require-clause expr (PR #90961)
hokein wrote: I'm merging it now (happy to address any post-comments). https://github.com/llvm/llvm-project/pull/90961 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: fix the transformation for the require-clause expr (PR #90961)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/90961 >From 0bdb18c0ffc37b38e81487b45e0e00e4480473aa Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 3 May 2024 11:04:21 +0200 Subject: [PATCH 1/2] [clang] CTAD alias: refine the transformation for the require-clause expr. In the clang AST, constraint nodes are deliberately not instantiated unless they are actively being evaluated. Consequently, occurrences of template parameters in the require-clause expression have a subtle "depth" difference compared to normal occurrences in place contexts, such as function parameters. When transforming the require-clause, we must take this distinction into account. The existing implementation overlooks this consideration. This patch is to rewrite the implementation of the require-clause transformation to address this issue. --- clang/lib/Sema/SemaTemplate.cpp | 147 +-- clang/test/AST/ast-dump-ctad-alias.cpp | 40 + clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 68 + 3 files changed, 242 insertions(+), 13 deletions(-) create mode 100644 clang/test/AST/ast-dump-ctad-alias.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0e7bd8dd89573..88becbdba6449 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2758,31 +2758,151 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { return false; } +unsigned getTemplateParameterDepth(NamedDecl *TemplateParam) { + if (auto *TTP = dyn_cast(TemplateParam)) +return TTP->getDepth(); + if (auto *TTP = dyn_cast(TemplateParam)) +return TTP->getDepth(); + if (auto *NTTP = dyn_cast(TemplateParam)) +return NTTP->getDepth(); + llvm_unreachable("Unhandled template parameter types"); +} + NamedDecl *transformTemplateParameter(Sema , DeclContext *DC, NamedDecl *TemplateParam, MultiLevelTemplateArgumentList , - unsigned NewIndex) { + unsigned NewIndex, unsigned NewDepth) { if (auto *TTP = dyn_cast(TemplateParam)) -return transformTemplateTypeParam(SemaRef, DC, TTP, Args, TTP->getDepth(), +return transformTemplateTypeParam(SemaRef, DC, TTP, Args, NewDepth, NewIndex); if (auto *TTP = dyn_cast(TemplateParam)) return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, - TTP->getDepth()); + NewDepth); if (auto *NTTP = dyn_cast(TemplateParam)) return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, - NTTP->getDepth()); + NewDepth); llvm_unreachable("Unhandled template parameter types"); } -Expr *transformRequireClause(Sema , FunctionTemplateDecl *FTD, - llvm::ArrayRef TransformedArgs) { - Expr *RC = FTD->getTemplateParameters()->getRequiresClause(); +// Transform the require-clause of F if any. +// The return result is expected to be the require-clause for the synthesized +// alias deduction guide. +Expr *transformRequireClause( +Sema , FunctionTemplateDecl *F, +TypeAliasTemplateDecl *AliasTemplate, +ArrayRef DeduceResults) { + Expr *RC = F->getTemplateParameters()->getRequiresClause(); if (!RC) return nullptr; + + auto = SemaRef.Context; + LocalInstantiationScope Scope(SemaRef); + + // In the clang AST, constraint nodes are deliberately not instantiated unless + // they are actively being evaluated. Consequently, occurrences of template + // parameters in the require-clause expression have a subtle "depth" + // difference compared to normal occurrences in places, such as function + // parameters. When transforming the require-clause, we must take this + // distinction into account: + // + // 1) In the transformed require-clause, occurrences of template parameters + // must use the "uninstantiated" depth; + // 2) When substituting on the require-clause expr of the underlying + // deduction guide, we must use the entire set of template argument lists; + // + // It's important to note that we're performing this transformation on an + // *instantiated* AliasTemplate. + + // For 1), if the alias template is nested within a class template, we + // calcualte the 'uninstantiated' depth by adding the substitution level back. + unsigned AdjustDepth = 0; + if (auto *PrimaryTemplate = AliasTemplate->getInstantiatedFromMemberTemplate()) +AdjustDepth = PrimaryTemplate->getTemplateDepth(); + + // We rebuild all template parameters with the uninstantiated depth, and + // build template arguments refer to them. + SmallVector AdjustedAliasTemplateArgs; + + for (auto *TP : *AliasTemplate->getTemplateParameters()) { +// Rebuild any internal references to
[clang] 2b38688 - Reland: [clang] Use getDefaultArgRange instead of getDefaultArg to retrieve
Author: Haojian Wu Date: 2024-05-11T22:07:21+02:00 New Revision: 2b386888b78327db4906b12401e1a89438471548 URL: https://github.com/llvm/llvm-project/commit/2b386888b78327db4906b12401e1a89438471548 DIFF: https://github.com/llvm/llvm-project/commit/2b386888b78327db4906b12401e1a89438471548.diff LOG: Reland: [clang] Use getDefaultArgRange instead of getDefaultArg to retrieve source location in `ConvertConstructorToDeductionGuideTransform`. The commit fec471649fffaa3ec44e17801e5c9605825e58bb was reverted by accident in 7415524b45392651969374c067041daa82dc89e7. Reland it with a testcase. Added: Modified: clang/lib/Sema/SemaTemplate.cpp clang/test/SemaTemplate/ctad.cpp Removed: diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 82badb2efb5cf..0e7bd8dd89573 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2679,7 +2679,7 @@ struct ConvertConstructorToDeductionGuideTransform { // placeholder to indicate there is a default argument. QualType ParamTy = NewDI->getType(); NewDefArg = new (SemaRef.Context) - OpaqueValueExpr(OldParam->getDefaultArg()->getBeginLoc(), + OpaqueValueExpr(OldParam->getDefaultArgRange().getBegin(), ParamTy.getNonLValueExprType(SemaRef.Context), ParamTy->isLValueReferenceType() ? VK_LValue : ParamTy->isRValueReferenceType() ? VK_XValue diff --git a/clang/test/SemaTemplate/ctad.cpp b/clang/test/SemaTemplate/ctad.cpp index ec144d4f44ba8..e981ea8d5ecfb 100644 --- a/clang/test/SemaTemplate/ctad.cpp +++ b/clang/test/SemaTemplate/ctad.cpp @@ -54,3 +54,18 @@ template struct Y { Y(T); }; template struct Y ; Y y(1); } + +namespace NoCrashOnGettingDefaultArgLoc { +template +class A { + A(int = 1); // expected-note {{candidate template ignored: couldn't infer template argumen}} +}; +class C : A { + using A::A; +}; +template +class D : C { // expected-note {{candidate function template not viable: requires 1 argument}} + using C::C; +}; +D abc; // expected-error {{no viable constructor or deduction guide}} +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD alias: fix the transformation for the require-clause expr (PR #90961)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/90961 >From 9cc438e2def2fa98af71ba79eb82e033f3d5905a Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 3 May 2024 11:04:21 +0200 Subject: [PATCH] [clang] CTAD alias: refine the transformation for the require-clause expr. In the clang AST, constraint nodes are deliberately not instantiated unless they are actively being evaluated. Consequently, occurrences of template parameters in the require-clause expression have a subtle "depth" difference compared to normal occurrences in place contexts, such as function parameters. When transforming the require-clause, we must take this distinction into account. The existing implementation overlooks this consideration. This patch is to rewrite the implementation of the require-clause transformation to address this issue. --- clang/lib/Sema/SemaTemplate.cpp | 147 +-- clang/test/AST/ast-dump-ctad-alias.cpp | 40 + clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 68 + 3 files changed, 242 insertions(+), 13 deletions(-) create mode 100644 clang/test/AST/ast-dump-ctad-alias.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 480c0103ae335..1b0b8542164d6 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2758,31 +2758,151 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { return false; } +unsigned getTemplateParameterDepth(NamedDecl *TemplateParam) { + if (auto *TTP = dyn_cast(TemplateParam)) +return TTP->getDepth(); + if (auto *TTP = dyn_cast(TemplateParam)) +return TTP->getDepth(); + if (auto *NTTP = dyn_cast(TemplateParam)) +return NTTP->getDepth(); + llvm_unreachable("Unhandled template parameter types"); +} + NamedDecl *transformTemplateParameter(Sema , DeclContext *DC, NamedDecl *TemplateParam, MultiLevelTemplateArgumentList , - unsigned NewIndex) { + unsigned NewIndex, unsigned NewDepth) { if (auto *TTP = dyn_cast(TemplateParam)) -return transformTemplateTypeParam(SemaRef, DC, TTP, Args, TTP->getDepth(), +return transformTemplateTypeParam(SemaRef, DC, TTP, Args, NewDepth, NewIndex); if (auto *TTP = dyn_cast(TemplateParam)) return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, - TTP->getDepth()); + NewDepth); if (auto *NTTP = dyn_cast(TemplateParam)) return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, - NTTP->getDepth()); + NewDepth); llvm_unreachable("Unhandled template parameter types"); } -Expr *transformRequireClause(Sema , FunctionTemplateDecl *FTD, - llvm::ArrayRef TransformedArgs) { - Expr *RC = FTD->getTemplateParameters()->getRequiresClause(); +// Transform the require-clause of F if any. +// The return result is expected to be the require-clause for the synthesized +// alias deduction guide. +Expr *transformRequireClause( +Sema , FunctionTemplateDecl *F, +TypeAliasTemplateDecl *AliasTemplate, +ArrayRef DeduceResults) { + Expr *RC = F->getTemplateParameters()->getRequiresClause(); if (!RC) return nullptr; + + auto = SemaRef.Context; + LocalInstantiationScope Scope(SemaRef); + + // In the clang AST, constraint nodes are deliberately not instantiated unless + // they are actively being evaluated. Consequently, occurrences of template + // parameters in the require-clause expression have a subtle "depth" + // difference compared to normal occurrences in places, such as function + // parameters. When transforming the require-clause, we must take this + // distinction into account: + // + // 1) In the transformed require-clause, occurrences of template parameters + // must use the "uninstantiated" depth; + // 2) When substituting on the require-clause expr of the underlying + // deduction guide, we must use the entire set of template argument lists; + // + // It's important to note that we're performing this transformation on an + // *instantiated* AliasTemplate. + + // For 1), if the alias template is nested within a class template, we + // calcualte the 'uninstantiated' depth by adding the substitution level back. + unsigned AdjustDepth = 0; + if (auto *PrimaryTemplate = AliasTemplate->getInstantiatedFromMemberTemplate()) +AdjustDepth = PrimaryTemplate->getTemplateDepth(); + + // We rebuild all template parameters with the uninstantiated depth, and + // build template arguments refer to them. + SmallVector AdjustedAliasTemplateArgs; + + for (auto *TP : *AliasTemplate->getTemplateParameters()) { +// Rebuild any internal references to earlier
[clang] [clang] CTAD alias: fix the transformation for the require-clause expr (PR #90961)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/90961 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AST] Print the separator "," for template arguments in ConceptReference::print (PR #91750)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/91750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AST] Print the separator "," for template arguments in ConceptReference::print (PR #91750)
@@ -24,6 +24,7 @@ add_clang_unittest(ASTTests CommentLexer.cpp CommentParser.cpp CommentTextTest.cpp + ConceptPrinterTest.cpp hokein wrote: Done (we're not required to update gn build files, and there's a bot that can automate the porting). https://github.com/llvm/llvm-project/pull/91750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AST] Print the separator "," for template arguments in ConceptReference::print (PR #91750)
@@ -106,9 +106,15 @@ void ConceptReference::print(llvm::raw_ostream , ConceptName.printName(OS, Policy); if (hasExplicitTemplateArgs()) { OS << "<"; +bool First = true; // FIXME: Find corresponding parameter for argument -for (auto : ArgsAsWritten->arguments()) +for (auto : ArgsAsWritten->arguments()) { + if (First) +First = false; + else +OS << ", "; hokein wrote: Thanks! I wasn't aware we have such a helpful utility. https://github.com/llvm/llvm-project/pull/91750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AST] Print the separator "," for template arguments in ConceptReference::print (PR #91750)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/91750 >From e7b23e02e9b4c98d9e24dd1debcdefada7a16004 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 10 May 2024 16:31:20 +0200 Subject: [PATCH 1/2] [AST] Print the separator , for template arguments in ConceptReference::print --- clang/lib/AST/ASTConcept.cpp | 8 ++- clang/unittests/AST/CMakeLists.txt | 1 + clang/unittests/AST/ConceptPrinterTest.cpp | 57 ++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 clang/unittests/AST/ConceptPrinterTest.cpp diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index b3ec99448b3e1..6bef68fc87eea 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -106,9 +106,15 @@ void ConceptReference::print(llvm::raw_ostream , ConceptName.printName(OS, Policy); if (hasExplicitTemplateArgs()) { OS << "<"; +bool First = true; // FIXME: Find corresponding parameter for argument -for (auto : ArgsAsWritten->arguments()) +for (auto : ArgsAsWritten->arguments()) { + if (First) +First = false; + else +OS << ", "; ArgLoc.getArgument().print(Policy, OS, /*IncludeType*/ false); +} OS << ">"; } } diff --git a/clang/unittests/AST/CMakeLists.txt b/clang/unittests/AST/CMakeLists.txt index 54765e36db008..29d2b39cff8b1 100644 --- a/clang/unittests/AST/CMakeLists.txt +++ b/clang/unittests/AST/CMakeLists.txt @@ -24,6 +24,7 @@ add_clang_unittest(ASTTests CommentLexer.cpp CommentParser.cpp CommentTextTest.cpp + ConceptPrinterTest.cpp DataCollectionTest.cpp DeclPrinterTest.cpp DeclTest.cpp diff --git a/clang/unittests/AST/ConceptPrinterTest.cpp b/clang/unittests/AST/ConceptPrinterTest.cpp new file mode 100644 index 0..bd1f6bbfa5658 --- /dev/null +++ b/clang/unittests/AST/ConceptPrinterTest.cpp @@ -0,0 +1,57 @@ +//===- unittests/AST/ConceptPrinterTest.cpp --- Concept printer tests -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "ASTPrint.h" +#include "clang/AST/ASTConcept.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/SmallString.h" +#include "gtest/gtest.h" + +using namespace clang; +using namespace ast_matchers; +using namespace tooling; + +namespace { + +static void PrintConceptReference(raw_ostream , const ASTContext *Context, + const ConceptSpecializationExpr *T, + PrintingPolicyAdjuster PolicyAdjuster) { + assert(T && T->getConceptReference() && + "Expected non-null concept reference"); + + PrintingPolicy Policy = Context->getPrintingPolicy(); + if (PolicyAdjuster) +PolicyAdjuster(Policy); + T->getConceptReference()->print(Out, Policy); +} + +::testing::AssertionResult +PrintedConceptMatches(StringRef Code, const std::vector , + const StatementMatcher , + StringRef ExpectedPrinted) { + return PrintedNodeMatches( + Code, Args, NodeMatch, ExpectedPrinted, "", PrintConceptReference); +} +const internal::VariadicDynCastAllOfMatcher +conceptSpecializationExpr; +} // unnamed namespace + +TEST(ConceptPrinter, ConceptReference) { + std::string Code = R"cpp( +template concept D = true; +template +requires D +void g(T); + )cpp"; + auto Matcher = conceptSpecializationExpr().bind("id"); + + ASSERT_TRUE(PrintedConceptMatches(Code, {"-std=c++20"}, Matcher, "D")); +} >From 251fd97fbf87d0c0fbe35f646058d3f9534c05a7 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 10 May 2024 17:40:55 +0200 Subject: [PATCH 2/2] address review comments. --- clang/lib/AST/ASTConcept.cpp | 8 +++- llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index 6bef68fc87eea..0387fc9f6aec2 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/PrettyPrinter.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringExtras.h" using namespace clang; @@ -106,13 +107,10 @@ void ConceptReference::print(llvm::raw_ostream , ConceptName.printName(OS, Policy); if (hasExplicitTemplateArgs()) { OS << "<"; -bool First = true; +llvm::ListSeparator Sep(", "); // FIXME: Find corresponding parameter for argument for (auto : ArgsAsWritten->arguments()) { - if (First) -First = false; - else -
[clang] [AST] Print the separator "," for template arguments in ConceptReference::print (PR #91750)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/91750 None >From e7b23e02e9b4c98d9e24dd1debcdefada7a16004 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 10 May 2024 16:31:20 +0200 Subject: [PATCH] [AST] Print the separator , for template arguments in ConceptReference::print --- clang/lib/AST/ASTConcept.cpp | 8 ++- clang/unittests/AST/CMakeLists.txt | 1 + clang/unittests/AST/ConceptPrinterTest.cpp | 57 ++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 clang/unittests/AST/ConceptPrinterTest.cpp diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index b3ec99448b3e1..6bef68fc87eea 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -106,9 +106,15 @@ void ConceptReference::print(llvm::raw_ostream , ConceptName.printName(OS, Policy); if (hasExplicitTemplateArgs()) { OS << "<"; +bool First = true; // FIXME: Find corresponding parameter for argument -for (auto : ArgsAsWritten->arguments()) +for (auto : ArgsAsWritten->arguments()) { + if (First) +First = false; + else +OS << ", "; ArgLoc.getArgument().print(Policy, OS, /*IncludeType*/ false); +} OS << ">"; } } diff --git a/clang/unittests/AST/CMakeLists.txt b/clang/unittests/AST/CMakeLists.txt index 54765e36db008..29d2b39cff8b1 100644 --- a/clang/unittests/AST/CMakeLists.txt +++ b/clang/unittests/AST/CMakeLists.txt @@ -24,6 +24,7 @@ add_clang_unittest(ASTTests CommentLexer.cpp CommentParser.cpp CommentTextTest.cpp + ConceptPrinterTest.cpp DataCollectionTest.cpp DeclPrinterTest.cpp DeclTest.cpp diff --git a/clang/unittests/AST/ConceptPrinterTest.cpp b/clang/unittests/AST/ConceptPrinterTest.cpp new file mode 100644 index 0..bd1f6bbfa5658 --- /dev/null +++ b/clang/unittests/AST/ConceptPrinterTest.cpp @@ -0,0 +1,57 @@ +//===- unittests/AST/ConceptPrinterTest.cpp --- Concept printer tests -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "ASTPrint.h" +#include "clang/AST/ASTConcept.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/SmallString.h" +#include "gtest/gtest.h" + +using namespace clang; +using namespace ast_matchers; +using namespace tooling; + +namespace { + +static void PrintConceptReference(raw_ostream , const ASTContext *Context, + const ConceptSpecializationExpr *T, + PrintingPolicyAdjuster PolicyAdjuster) { + assert(T && T->getConceptReference() && + "Expected non-null concept reference"); + + PrintingPolicy Policy = Context->getPrintingPolicy(); + if (PolicyAdjuster) +PolicyAdjuster(Policy); + T->getConceptReference()->print(Out, Policy); +} + +::testing::AssertionResult +PrintedConceptMatches(StringRef Code, const std::vector , + const StatementMatcher , + StringRef ExpectedPrinted) { + return PrintedNodeMatches( + Code, Args, NodeMatch, ExpectedPrinted, "", PrintConceptReference); +} +const internal::VariadicDynCastAllOfMatcher +conceptSpecializationExpr; +} // unnamed namespace + +TEST(ConceptPrinter, ConceptReference) { + std::string Code = R"cpp( +template concept D = true; +template +requires D +void g(T); + )cpp"; + auto Matcher = conceptSpecializationExpr().bind("id"); + + ASSERT_TRUE(PrintedConceptMatches(Code, {"-std=c++20"}, Matcher, "D")); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Revise the transformation of CTAD parameters of nested class templates (PR #91628)
@@ -2583,11 +2580,27 @@ struct ConvertConstructorToDeductionGuideTransform { //-- The types of the function parameters are those of the constructor. for (auto *OldParam : TL.getParams()) { - ParmVarDecl *NewParam = - transformFunctionTypeParam(OldParam, Args, MaterializedTypedefs); - if (NestedPattern && NewParam) + ParmVarDecl *NewParam = OldParam; + // Given + // template struct C { + // template struct D { + // template D(U, V); + // }; + // }; + // First, transform all the references to template parameters that are + // defined outside of the surrounding class template. That is T in the + // above example. + if (NestedPattern) { NewParam = transformFunctionTypeParam(NewParam, OuterInstantiationArgs, MaterializedTypedefs); +if (!NewParam) + return QualType(); + } + // Then, transform all the references to template parameters that are + // defined at the class template and the constructor. In this example, + // they're U and V, respectively. + NewParam = + transformFunctionTypeParam(NewParam, Args, MaterializedTypedefs); hokein wrote: We have the same pattern on Line 2438-2452 in this file, where we perform a substitution of `OuterInstantiationArgs` on a new transformed parameter decl, I think we should probably fix it as well. https://github.com/llvm/llvm-project/pull/91628 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Revise the transformation of CTAD parameters of nested class templates (PR #91628)
@@ -84,3 +84,17 @@ nested_init_list::concept_fail nil_invalid{1, ""}; // expected-note@#INIT_LIST_INNER_INVALID {{candidate template ignored: substitution failure [with F = const char *]: constraints not satisfied for class template 'concept_fail' [with F = const char *]}} // expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not viable: requires 1 argument, but 2 were provided}} // expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not viable: requires 0 arguments, but 2 were provided}} + +namespace PR88142 { hokein wrote: nit: PR => GH https://github.com/llvm/llvm-project/pull/91628 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Revise the transformation of CTAD parameters of nested class templates (PR #91628)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/91628 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Revise the transformation of CTAD parameters of nested class templates (PR #91628)
https://github.com/hokein commented: The fix looks good to me, and thanks for the comprehensive explanation in the description. https://github.com/llvm/llvm-project/pull/91628 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein commented: Replied some review comments. I haven't updated the code yet (plan to do it after #90961) https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -3307,6 +3341,58 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, return ::DeduceTemplateArguments(*this, Partial, TemplateArgs, Info); } +TemplateDeductionResult +Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, hokein wrote: This function is public (the documentation and comments are in `Sema.h` header). https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -190,13 +196,15 @@ template struct Foo { Foo(T); }; template using AFoo = Foo; template concept False = false; -template using BFoo = AFoo; +template +using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ + // expected-note {{because '__is_deducible(BFoo, Foo)' evaluated to false}} \ hokein wrote: Do you think this is a blocker for landing this PR? The current state is acceptable to me, although not ideal. I plan to send out a follow-up patch to address it. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -27,7 +27,8 @@ enum TypeTrait { , #define TYPE_TRAIT_2(Spelling, Name, Key) BTT_##Name, #include "clang/Basic/TokenKinds.def" - BTT_Last = UTT_Last // BTT_Last == last BTT_XX in the enum. + BTT_Last = UTT_Last hokein wrote: oops, this is not intended. This was left when I reverted some changes. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
@@ -3239,6 +3239,40 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( return TemplateDeductionResult::Success; } +/// Complete template argument deduction for DeduceTemplateArgumentsFromType. +/// FIXME: this is mostly duplicated with the above two versions. Deduplicate +/// the three implementations. hokein wrote: It is in my TODO list, but its priority is currently low, so I don't anticipate addressing it in the near future. This seems like a good candidate for a "GoodFirst" issue, so I'm thinking we can file an issue in case someone wants to contribute. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AST] RecursiveASTVisitor: Don't traverse the alias deduction guides in the default mode. (PR #91454)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/91454 By default (`shouldVisitImplicitCode()` returns `false`), RAV should not traverse AST nodes that are not spelled in the source code. Deduction guides for alias templates are always synthesized, so they should not be traversed. This is usually done by checking the implicit bit of the Decl. However, this doesn't work deduction guides that are synthesized from explicit user-defined deduction guides, as we must maintain the explicit bit to ensure correct overload resolution. >From e560fe2bf2d4bdc07a71682aa4d3a4bee8730b80 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 8 May 2024 12:11:10 +0200 Subject: [PATCH] [AST] RecursiveASTVisitor: Don't traverse the alias deduction guides in default mode. --- clang/include/clang/AST/RecursiveASTVisitor.h | 28 -- .../DeductionGuide.cpp| 89 +++ 2 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index f9b145b4e86a5..2517189c95300 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -736,13 +736,27 @@ bool RecursiveASTVisitor::TraverseDecl(Decl *D) { // As a syntax visitor, by default we want to ignore declarations for // implicit declarations (ones not typed explicitly by the user). - if (!getDerived().shouldVisitImplicitCode() && D->isImplicit()) { -// For an implicit template type parameter, its type constraints are not -// implicit and are not represented anywhere else. We still need to visit -// them. -if (auto *TTPD = dyn_cast(D)) - return TraverseTemplateTypeParamDeclConstraints(TTPD); -return true; + if (!getDerived().shouldVisitImplicitCode()) { +if (D->isImplicit()) { + // For an implicit template type parameter, its type constraints are not + // implicit and are not represented anywhere else. We still need to visit + // them. + if (auto *TTPD = dyn_cast(D)) +return TraverseTemplateTypeParamDeclConstraints(TTPD); + return true; +} + +// Deduction guides for alias templates are always synthesized, so they +// should not be traversed unless shouldVisitImplicitCode() returns true. +// +// It's important to note that checking the implicit bit is not efficient +// for the alias case. For deduction guides synthesized from explicit +// user-defined deduction guides, we must maintain the explicit bit to +// ensure correct overload resolution. +if (auto *FTD = dyn_cast(D)) + if (llvm::isa_and_present( + FTD->getDeclName().getCXXDeductionGuideTemplate())) +return true; } switch (D->getKind()) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp new file mode 100644 index 0..abfdbaea4a615 --- /dev/null +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp @@ -0,0 +1,89 @@ +//===- unittest/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "TestVisitor.h" +#include + +using namespace clang; + +namespace { + +class DeductionGuideVisitor +: public ExpectedLocationVisitor { +public: + DeductionGuideVisitor(bool ShouldVisitImplicitCode) + : ShouldVisitImplicitCode(ShouldVisitImplicitCode) {} + bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { +std::string Storage; +llvm::raw_string_ostream Stream(Storage); +D->print(Stream); +Match(Stream.str(),D->getLocation()); +return true; + } + + bool shouldVisitTemplateInstantiations() const { +return false; + } + + bool shouldVisitImplicitCode() const { +return ShouldVisitImplicitCode; + } + bool ShouldVisitImplicitCode; +}; + +TEST(RecursiveASTVisitor, DeductionGuideNonImplicitMode) { + DeductionGuideVisitor Visitor(/*ShouldVisitImplicitCode*/ false); + // Verify that the synthezied deduction guide for alias is not visited in + // RAV's implicit mode. + Visitor.ExpectMatch("Foo(T) -> Foo", 11, 1); + Visitor.DisallowMatch("Bar(type-parameter-0-0) -> Foo", 14, 1); + EXPECT_TRUE(Visitor.runOver( +R"cpp( +template +concept False = true; + +template +struct Foo { + Foo(T); +}; + +template requires False +Foo(T) -> Foo; + +template +using Bar = Foo; +Bar s(1); + )cpp" + , DeductionGuideVisitor::Lang_CXX2a)); +} + +TEST(RecursiveASTVisitor, DeductionGuideImplicitMode) { +
[clang] [Coro] Relax a debug-info test (PR #91401)
https://github.com/hokein approved this pull request. https://github.com/llvm/llvm-project/pull/91401 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/90894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -261,6 +261,13 @@ AG ag = {1}; // CHECK: | `-BuiltinType {{.*}} 'int' // CHECK: `-ParmVarDecl {{.*}} 'int' +template +using BG = G; +BG bg(1.0); +// CHECK-LABEL: Dumping +// CHECK: FunctionTemplateDecl {{.*}} implicit +// CHECK: |-CXXDeductionGuideDecl {{.*}} 'auto (int) -> G' aggregate hokein wrote: > The line is a CHECK, not a CHECK-NEXT, so it could appear any number of lines > afterwards. Yeah, ideally it should be `CHECK-NEXT`, but we can't use it because of the ambiguity in the content of the above line (there are two other deduction guides emitting the same content), so I end up using the `CHECK: |-...`, it at least demonstrates that it is a child of something. https://github.com/llvm/llvm-project/pull/90894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
hokein wrote: > > I agree with you -- having a well-described diagnostic message is better > > and clearer. I'm happy to improve it once we settle on the final > > implementation approach (the current diagnostic because > > '__is_deducible(AFoo, Foo)' evaluated to false seems okay to me. GCC also > > emits similar diagnostics). > > Well, if we agree on that, the only thing to do for approach 3 is to deal > with "anonymous" traits in ast dump and similar, which seems to be a fairly > bounded effort! I was worried about the potential need to handle these issues in various places. However, thinking more about it today, I think we can address them locally in the `getTraitSpelling`, which seems like a more favorable approach. I've now updated the patch to implement approach 3. Please take a look. Note that I haven't addressed the diagnostic improvement part yet; I plan to handle that in a separate follow-up patch. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/89358 >From bf6acda6c7cb9a08b82b149c0df38d90e395f9e1 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 19 Apr 2024 10:54:12 +0200 Subject: [PATCH 1/4] [clang] CTAD: implement the missing IsDeducible constraint for alias templates. Fixes https://github.com/llvm/llvm-project/issues/85192 Fixes https://github.com/llvm/llvm-project/issues/84492 --- clang/include/clang/Basic/TokenKinds.def | 1 + clang/include/clang/Sema/Sema.h | 9 ++ clang/lib/Parse/ParseExprCXX.cpp | 16 ++-- clang/lib/Sema/SemaExprCXX.cpp| 11 +++ clang/lib/Sema/SemaTemplate.cpp | 70 --- clang/lib/Sema/SemaTemplateDeduction.cpp | 87 +++ clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 26 -- .../test/SemaCXX/type-traits-is-deducible.cpp | 47 ++ clang/www/cxx_status.html | 8 +- 9 files changed, 243 insertions(+), 32 deletions(-) create mode 100644 clang/test/SemaCXX/type-traits-is-deducible.cpp diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index a27fbed358a60..74102f4053968 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -537,6 +537,7 @@ TYPE_TRAIT_1(__is_referenceable, IsReferenceable, KEYCXX) TYPE_TRAIT_1(__can_pass_in_regs, CanPassInRegs, KEYCXX) TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) TYPE_TRAIT_2(__reference_constructs_from_temporary, ReferenceConstructsFromTemporary, KEYCXX) +TYPE_TRAIT_2(__is_deducible, IsDeducible, KEYCXX) // Embarcadero Expression Traits EXPRESSION_TRAIT(__is_lvalue_expr, IsLValueExpr, KEYCXX) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a80ac6dbc7613..6f9a31bbbaf60 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9597,6 +9597,15 @@ class Sema final : public SemaBase { ArrayRef TemplateArgs, sema::TemplateDeductionInfo ); + /// Deduce the template arguments of the given template from \p FromType. + /// Used to implement the IsDeducible constraint for alias CTAD per C++ + /// [over.match.class.deduct]p4. + /// + /// It only supports class or type alias templates. + TemplateDeductionResult + DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, + sema::TemplateDeductionInfo ); + TemplateDeductionResult DeduceTemplateArguments( TemplateParameterList *TemplateParams, ArrayRef Ps, ArrayRef As, sema::TemplateDeductionInfo , diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 0d2ad980696fc..af4e205eeff80 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -3906,14 +3906,18 @@ ExprResult Parser::ParseTypeTrait() { BalancedDelimiterTracker Parens(*this, tok::l_paren); if (Parens.expectAndConsume()) return ExprError(); - + TypeTrait TTKind = TypeTraitFromTokKind(Kind); SmallVector Args; do { // Parse the next type. -TypeResult Ty = ParseTypeName(/*SourceRange=*/nullptr, - getLangOpts().CPlusPlus - ? DeclaratorContext::TemplateTypeArg - : DeclaratorContext::TypeName); +TypeResult Ty = ParseTypeName( +/*SourceRange=*/nullptr, +getLangOpts().CPlusPlus +// For __is_deducible type trait, the first argument is a template +// specification type without template argument lists. +? (TTKind == BTT_IsDeducible ? DeclaratorContext::TemplateArg + : DeclaratorContext::TemplateTypeArg) +: DeclaratorContext::TypeName); if (Ty.isInvalid()) { Parens.skipToEnd(); return ExprError(); @@ -3937,7 +3941,7 @@ ExprResult Parser::ParseTypeTrait() { SourceLocation EndLoc = Parens.getCloseLocation(); - return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc); + return Actions.ActOnTypeTrait(TTKind, Loc, Args, EndLoc); } /// ParseArrayTypeTrait - Parse the built-in array type-trait diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c1cb03e4ec7ae..222e8babdfaaa 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6116,6 +6116,17 @@ static bool EvaluateBinaryTypeTrait(Sema , TypeTrait BTT, const TypeSourceI tok::kw___is_pointer_interconvertible_base_of); return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); + } + case BTT_IsDeducible: { +if (const auto *TSTToBeDeduced = +LhsT->getAs()) { + sema::TemplateDeductionInfo Info(KeyLoc); + return Self.DeduceTemplateArgumentsFromType( +
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , +TypeAliasTemplateDecl *AliasTemplate, +FunctionTemplateDecl *F, SourceLocation Loc) { + LocalInstantiationScope Scope(SemaRef); + Sema::InstantiatingTemplate BuildingDeductionGuides( + SemaRef, AliasTemplate->getLocation(), F, + Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); + if (BuildingDeductionGuides.isInvalid()) +return nullptr; + + auto = SemaRef.Context; + auto [Template, AliasRhsTemplateArgs] = + getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); + + auto RType = F->getTemplatedDecl()->getReturnType(); + // The (trailing) return type of the deduction guide. + const TemplateSpecializationType *FReturnType = + RType->getAs(); + if (const auto *InjectedCNT = RType->getAs()) +// implicitly-generated deduction guide. +FReturnType = InjectedCNT->getInjectedTST(); + else if (const auto *ET = RType->getAs()) +// explicit deduction guide. +FReturnType = ET->getNamedType()->getAs(); + assert(FReturnType && "expected to see a return type"); + // Deduce template arguments of the deduction guide f from the RHS of + // the alias. + // + // C++ [over.match.class.deduct]p3: ...For each function or function + // template f in the guides of the template named by the + // simple-template-id of the defining-type-id, the template arguments + // of the return type of f are deduced from the defining-type-id of A + // according to the process in [temp.deduct.type] with the exception + // that deduction does not fail if not all template arguments are + // deduced. + // + // + // template + // f(X, Y) -> f; + // + // template + // using alias = f; + // + // The RHS of alias is f, we deduced the template arguments of + // the return type of the deduction guide from it: Y->int, X->U + sema::TemplateDeductionInfo TDeduceInfo(Loc); + // Must initialize n elements, this is required by DeduceTemplateArguments. + SmallVector DeduceResults( + F->getTemplateParameters()->size()); + + // FIXME: DeduceTemplateArguments stops immediately at the first + // non-deducible template argument. However, this doesn't seem to casue + // issues for practice cases, we probably need to extend it to continue + // performing deduction for rest of arguments to align with the C++ + // standard. + SemaRef.DeduceTemplateArguments( + F->getTemplateParameters(), FReturnType->template_arguments(), + AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, + /*NumberOfArgumentsMustMatch=*/false); + + SmallVector DeducedArgs; + SmallVector NonDeducedTemplateParamsInFIndex; + // !!NOTE: DeduceResults respects the sequence of template parameters of + // the deduction guide f. + for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { +if (const auto = DeduceResults[Index]; !D.isNull()) // Deduced + DeducedArgs.push_back(D); +else + NonDeducedTemplateParamsInFIndex.push_back(Index); + } + auto DeducedAliasTemplateParams = + TemplateParamsReferencedInTemplateArgumentList( + AliasTemplate->getTemplateParameters()->asArray(), DeducedArgs); + // All template arguments null by default. + SmallVector TemplateArgsForBuildingFPrime( + F->getTemplateParameters()->size()); + + // Create a template parameter list for the synthesized deduction guide f'. + // + // C++ [over.match.class.deduct]p3.2: + // If f is a function template, f' is a function template whose template + // parameter list consists of all the template parameters of A + // (including their default template arguments) that appear in the above + // deductions or (recursively) in their default template arguments + SmallVector FPrimeTemplateParams; + // Store template arguments that refer to the newly-created template + // parameters, used for building `TemplateArgsForBuildingFPrime`. + SmallVector TransformedDeducedAliasArgs( + AliasTemplate->getTemplateParameters()->size()); + + for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) { +auto *TP = + AliasTemplate->getTemplateParameters()->getParam(AliasTemplateParamIdx); +// Rebuild any internal references to earlier parameters and reindex as +// we go. +MultiLevelTemplateArgumentList Args; +Args.setKind(TemplateSubstitutionKind::Rewrite); +Args.addOuterTemplateArguments(TransformedDeducedAliasArgs); +NamedDecl *NewParam = transformTemplateParameter( +SemaRef, AliasTemplate->getDeclContext(), TP, Args, +/*NewIndex=*/FPrimeTemplateParams.size()); +
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -261,6 +261,13 @@ AG ag = {1}; // CHECK: | `-BuiltinType {{.*}} 'int' // CHECK: `-ParmVarDecl {{.*}} 'int' +template +using BG = G; +BG bg(1.0); +// CHECK-LABEL: Dumping +// CHECK: FunctionTemplateDecl {{.*}} implicit +// CHECK: |-CXXDeductionGuideDecl {{.*}} 'auto (int) -> G' aggregate hokein wrote: While the test is not matching the AST structure, I think it is better and clearer to keep it, as it explicitly demonstrates the child relationship with the above line (`FunctionTemplateDecl`). https://github.com/llvm/llvm-project/pull/90894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/90894 >From 40365147f7aabeaaefd7e9bf6f2b96d6f7135992 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 3 May 2024 10:53:54 +0200 Subject: [PATCH 1/3] Refactor: Extract the core deduction-guide construction implementation from DeclareImplicitDeductionGuidesForTypeAlias We move the core implementation to a dedicate function, so that it can be reused in other places. --- clang/lib/Sema/SemaTemplate.cpp | 390 +--- 1 file changed, 203 insertions(+), 187 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 989f3995ca59913..b43c65874b04e5b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , +TypeAliasTemplateDecl *AliasTemplate, +FunctionTemplateDecl *F, SourceLocation Loc) { + LocalInstantiationScope Scope(SemaRef); + Sema::InstantiatingTemplate BuildingDeductionGuides( + SemaRef, AliasTemplate->getLocation(), F, + Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); + if (BuildingDeductionGuides.isInvalid()) +return nullptr; + + auto = SemaRef.Context; + auto [Template, AliasRhsTemplateArgs] = + getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); + + auto RType = F->getTemplatedDecl()->getReturnType(); + // The (trailing) return type of the deduction guide. + const TemplateSpecializationType *FReturnType = + RType->getAs(); + if (const auto *InjectedCNT = RType->getAs()) +// implicitly-generated deduction guide. +FReturnType = InjectedCNT->getInjectedTST(); + else if (const auto *ET = RType->getAs()) +// explicit deduction guide. +FReturnType = ET->getNamedType()->getAs(); + assert(FReturnType && "expected to see a return type"); + // Deduce template arguments of the deduction guide f from the RHS of + // the alias. + // + // C++ [over.match.class.deduct]p3: ...For each function or function + // template f in the guides of the template named by the + // simple-template-id of the defining-type-id, the template arguments + // of the return type of f are deduced from the defining-type-id of A + // according to the process in [temp.deduct.type] with the exception + // that deduction does not fail if not all template arguments are + // deduced. + // + // + // template + // f(X, Y) -> f; + // + // template + // using alias = f; + // + // The RHS of alias is f, we deduced the template arguments of + // the return type of the deduction guide from it: Y->int, X->U + sema::TemplateDeductionInfo TDeduceInfo(Loc); + // Must initialize n elements, this is required by DeduceTemplateArguments. + SmallVector DeduceResults( + F->getTemplateParameters()->size()); + + // FIXME: DeduceTemplateArguments stops immediately at the first + // non-deducible template argument. However, this doesn't seem to casue + // issues for practice cases, we probably need to extend it to continue + // performing deduction for rest of arguments to align with the C++ + // standard. + SemaRef.DeduceTemplateArguments( + F->getTemplateParameters(), FReturnType->template_arguments(), + AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, + /*NumberOfArgumentsMustMatch=*/false); + + SmallVector DeducedArgs; + SmallVector NonDeducedTemplateParamsInFIndex; + // !!NOTE: DeduceResults respects the sequence of template parameters of + // the deduction guide f. + for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { +if (const auto = DeduceResults[Index]; !D.isNull()) // Deduced + DeducedArgs.push_back(D); +else + NonDeducedTemplateParamsInFIndex.push_back(Index); + } + auto DeducedAliasTemplateParams = + TemplateParamsReferencedInTemplateArgumentList( + AliasTemplate->getTemplateParameters()->asArray(), DeducedArgs); + // All template arguments null by default. + SmallVector TemplateArgsForBuildingFPrime( + F->getTemplateParameters()->size()); + + // Create a template parameter list for the synthesized deduction guide f'. + // + // C++ [over.match.class.deduct]p3.2: + // If f is a function template, f' is a function template whose template + // parameter list consists of all the template parameters of A + // (including their default template arguments) that appear in the above + // deductions or (recursively) in their default template arguments + SmallVector FPrimeTemplateParams; + // Store template arguments that refer to the newly-created template + // parameters,
[clang] [clang-tools-extra] [clang] Don't preserve the typo expr in the recovery expr for invalid VarDecls (PR #90948)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/90948 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Don't preserve the typo expr in the recovery expr for invalid VarDecls (PR #90948)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/90948 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Don't preserve the typo expr in the recovery expr for invalid VarDecls (PR #90948)
@@ -13530,9 +13530,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } if (VDecl->isInvalidDecl()) { -CorrectDelayedTyposInExpr(Init, VDecl); +ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl); +std::vector SubExprs; hokein wrote: Switched to `SmallVector`. https://github.com/llvm/llvm-project/pull/90948 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang] Don't preserve the typo expr in the recovery expr for invalid VarDecls (PR #90948)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/90948 >From 2f29011bae5bf1b285c2ab1700c887d74eaec4b0 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 3 May 2024 10:06:39 +0200 Subject: [PATCH 1/2] [clang] Don't preserve the typo expr in the recovery expr for invalid VarDecls. With the commit d5308949cf884d8e4b971d51a8b4f73584c4adec, we now preserve the initializer for invalid decls with the recovery-expr. However there is a chance that the original init expr is a typo-expr, we should not preserve it in the final AST, as typo-expr is an internal AST nodes. We should use the one after the typo correction. This is spotted by a clangd hover crash on the testcase. --- clang-tools-extra/clangd/unittests/HoverTests.cpp | 13 + clang/lib/Sema/SemaDecl.cpp | 7 +-- clang/test/AST/ast-dump-recovery.cpp | 5 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 5ead74748f550c..28df24f34827c0 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -965,6 +965,19 @@ class Foo final {})cpp"; // Bindings are in theory public members of an anonymous struct. HI.AccessSpecifier = "public"; }}, + {// Don't crash on invalid decl with invalid init expr. + R"cpp( + Unknown [[^abc]] = invalid; + // error-ok + )cpp", + [](HoverInfo ) { + HI.Name = "abc"; + HI.Kind = index::SymbolKind::Variable; + HI.NamespaceScope = ""; + HI.Definition = "int abc = ()"; + HI.Type = "int"; + HI.AccessSpecifier = "public"; + }}, {// Extra info for function call. R"cpp( void fun(int arg_a, int _b) {}; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 19968452f0d566..169df60b56bb4b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13530,9 +13530,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } if (VDecl->isInvalidDecl()) { -CorrectDelayedTyposInExpr(Init, VDecl); +ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl); +std::vector SubExprs; +if (Res.isUsable()) + SubExprs.push_back(Res.get()); ExprResult Recovery = -CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), {Init}); +CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), SubExprs); if (Expr *E = Recovery.get()) VDecl->setInit(E); return; diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp index 77527743fe8577..a88dff471d9f04 100644 --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -419,6 +419,11 @@ void InitializerOfInvalidDecl() { // CHECK: VarDecl {{.*}} invalid InvalidDecl // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'ValidDecl' + + Unknown InvalidDeclWithInvalidInit = Invalid; + // CHECK: VarDecl {{.*}} invalid InvalidDeclWithInvalidInit + // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors + // CHECK-NOT:`-TypoExpr } void RecoverToAnInvalidDecl() { >From 06c30958b7bb2c664440e47bd2257e068f72c2b1 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 6 May 2024 20:16:05 +0200 Subject: [PATCH 2/2] address review comments. --- clang/lib/Sema/SemaDecl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 169df60b56bb4b..590f37837eb2df 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13531,7 +13531,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { if (VDecl->isInvalidDecl()) { ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl); -std::vector SubExprs; +SmallVector SubExprs; if (Res.isUsable()) SubExprs.push_back(Res.get()); ExprResult Recovery = ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , hokein wrote: > to clarify, in the actual fix you removed a whole bunch of code? https://github.com/llvm/llvm-project/commit/621899224aa7d59ab70675f6ff32b298b06a515a Yes, that's correct. The removed code is an incorrect implementation which will generate wrong deduction guides. https://github.com/llvm/llvm-project/pull/90894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++2a -verify -ast-dump -ast-dump-decl-types -ast-dump-filter "deduction guide" %s | FileCheck %s --strict-whitespace +// RUN: %clang_cc1 -std=c++2a -verify -ast-dump -ast-dump-decl-types -Wno-c++11-narrowing -ast-dump-filter "deduction guide" %s | FileCheck %s --strict-whitespace hokein wrote: Oh, yeah, this was to suppress the narrowing double=>int conversion warning on `BG bg = {1.0};`. I have changed the way to init the `bg` to get rid of this warning. https://github.com/llvm/llvm-project/pull/90894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -261,6 +261,13 @@ AG ag = {1}; // CHECK: | `-BuiltinType {{.*}} 'int' // CHECK: `-ParmVarDecl {{.*}} 'int' +template +using BG = G; +BG bg = {1.0}; +// CHECK-LABEL: Dumping +// CHECK: FunctionTemplateDecl hokein wrote: It is not possible to use the `CHECK-NEXT` here, as there are 3 deduction guides for BG, and each deduction guide has the same print content (which is `FunctionTemplateDecl 0x556b96b9da60 llvm-project/clang/test/SemaTemplate/deduction-guide.cpp:264:1, line:265:17> col:1 implicit `) https://github.com/llvm/llvm-project/pull/90894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , hokein wrote: I have restructured commits in this PR. It contains two commits: one for the NFC refactoring change, the other one is for the actual fix. I hope it would make the review easier. https://github.com/llvm/llvm-project/pull/90894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , +TypeAliasTemplateDecl *AliasTemplate, +FunctionTemplateDecl *F, SourceLocation Loc) { + LocalInstantiationScope Scope(SemaRef); + Sema::InstantiatingTemplate BuildingDeductionGuides( + SemaRef, AliasTemplate->getLocation(), F, + Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); + if (BuildingDeductionGuides.isInvalid()) +return nullptr; + + auto = SemaRef.Context; + auto [Template, AliasRhsTemplateArgs] = + getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); + + auto RType = F->getTemplatedDecl()->getReturnType(); + // The (trailing) return type of the deduction guide. + const TemplateSpecializationType *FReturnType = + RType->getAs(); + if (const auto *InjectedCNT = RType->getAs()) +// implicitly-generated deduction guide. +FReturnType = InjectedCNT->getInjectedTST(); + else if (const auto *ET = RType->getAs()) +// explicit deduction guide. +FReturnType = ET->getNamedType()->getAs(); + assert(FReturnType && "expected to see a return type"); + // Deduce template arguments of the deduction guide f from the RHS of + // the alias. + // + // C++ [over.match.class.deduct]p3: ...For each function or function + // template f in the guides of the template named by the + // simple-template-id of the defining-type-id, the template arguments + // of the return type of f are deduced from the defining-type-id of A + // according to the process in [temp.deduct.type] with the exception + // that deduction does not fail if not all template arguments are + // deduced. + // + // + // template + // f(X, Y) -> f; + // + // template + // using alias = f; + // + // The RHS of alias is f, we deduced the template arguments of + // the return type of the deduction guide from it: Y->int, X->U + sema::TemplateDeductionInfo TDeduceInfo(Loc); + // Must initialize n elements, this is required by DeduceTemplateArguments. + SmallVector DeduceResults( + F->getTemplateParameters()->size()); + + // FIXME: DeduceTemplateArguments stops immediately at the first + // non-deducible template argument. However, this doesn't seem to casue + // issues for practice cases, we probably need to extend it to continue + // performing deduction for rest of arguments to align with the C++ + // standard. + SemaRef.DeduceTemplateArguments( + F->getTemplateParameters(), FReturnType->template_arguments(), + AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, + /*NumberOfArgumentsMustMatch=*/false); + + SmallVector DeducedArgs; + SmallVector NonDeducedTemplateParamsInFIndex; + // !!NOTE: DeduceResults respects the sequence of template parameters of + // the deduction guide f. + for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { +if (const auto = DeduceResults[Index]; !D.isNull()) // Deduced + DeducedArgs.push_back(D); +else + NonDeducedTemplateParamsInFIndex.push_back(Index); + } + auto DeducedAliasTemplateParams = + TemplateParamsReferencedInTemplateArgumentList( + AliasTemplate->getTemplateParameters()->asArray(), DeducedArgs); + // All template arguments null by default. + SmallVector TemplateArgsForBuildingFPrime( + F->getTemplateParameters()->size()); + + // Create a template parameter list for the synthesized deduction guide f'. + // + // C++ [over.match.class.deduct]p3.2: + // If f is a function template, f' is a function template whose template + // parameter list consists of all the template parameters of A + // (including their default template arguments) that appear in the above + // deductions or (recursively) in their default template arguments + SmallVector FPrimeTemplateParams; + // Store template arguments that refer to the newly-created template + // parameters, used for building `TemplateArgsForBuildingFPrime`. + SmallVector TransformedDeducedAliasArgs( + AliasTemplate->getTemplateParameters()->size()); + + for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) { +auto *TP = + AliasTemplate->getTemplateParameters()->getParam(AliasTemplateParamIdx); +// Rebuild any internal references to earlier parameters and reindex as +// we go. +MultiLevelTemplateArgumentList Args; +Args.setKind(TemplateSubstitutionKind::Rewrite); +Args.addOuterTemplateArguments(TransformedDeducedAliasArgs); +NamedDecl *NewParam = transformTemplateParameter( +SemaRef, AliasTemplate->getDeclContext(), TP, Args, +/*NewIndex*/ FPrimeTemplateParams.size());
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/90894 >From 40365147f7aabeaaefd7e9bf6f2b96d6f7135992 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 3 May 2024 10:53:54 +0200 Subject: [PATCH 1/2] Refactor: Extract the core deduction-guide construction implementation from DeclareImplicitDeductionGuidesForTypeAlias We move the core implementation to a dedicate function, so that it can be reused in other places. --- clang/lib/Sema/SemaTemplate.cpp | 390 +--- 1 file changed, 203 insertions(+), 187 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 989f3995ca5991..b43c65874b04e5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , +TypeAliasTemplateDecl *AliasTemplate, +FunctionTemplateDecl *F, SourceLocation Loc) { + LocalInstantiationScope Scope(SemaRef); + Sema::InstantiatingTemplate BuildingDeductionGuides( + SemaRef, AliasTemplate->getLocation(), F, + Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); + if (BuildingDeductionGuides.isInvalid()) +return nullptr; + + auto = SemaRef.Context; + auto [Template, AliasRhsTemplateArgs] = + getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); + + auto RType = F->getTemplatedDecl()->getReturnType(); + // The (trailing) return type of the deduction guide. + const TemplateSpecializationType *FReturnType = + RType->getAs(); + if (const auto *InjectedCNT = RType->getAs()) +// implicitly-generated deduction guide. +FReturnType = InjectedCNT->getInjectedTST(); + else if (const auto *ET = RType->getAs()) +// explicit deduction guide. +FReturnType = ET->getNamedType()->getAs(); + assert(FReturnType && "expected to see a return type"); + // Deduce template arguments of the deduction guide f from the RHS of + // the alias. + // + // C++ [over.match.class.deduct]p3: ...For each function or function + // template f in the guides of the template named by the + // simple-template-id of the defining-type-id, the template arguments + // of the return type of f are deduced from the defining-type-id of A + // according to the process in [temp.deduct.type] with the exception + // that deduction does not fail if not all template arguments are + // deduced. + // + // + // template + // f(X, Y) -> f; + // + // template + // using alias = f; + // + // The RHS of alias is f, we deduced the template arguments of + // the return type of the deduction guide from it: Y->int, X->U + sema::TemplateDeductionInfo TDeduceInfo(Loc); + // Must initialize n elements, this is required by DeduceTemplateArguments. + SmallVector DeduceResults( + F->getTemplateParameters()->size()); + + // FIXME: DeduceTemplateArguments stops immediately at the first + // non-deducible template argument. However, this doesn't seem to casue + // issues for practice cases, we probably need to extend it to continue + // performing deduction for rest of arguments to align with the C++ + // standard. + SemaRef.DeduceTemplateArguments( + F->getTemplateParameters(), FReturnType->template_arguments(), + AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, + /*NumberOfArgumentsMustMatch=*/false); + + SmallVector DeducedArgs; + SmallVector NonDeducedTemplateParamsInFIndex; + // !!NOTE: DeduceResults respects the sequence of template parameters of + // the deduction guide f. + for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { +if (const auto = DeduceResults[Index]; !D.isNull()) // Deduced + DeducedArgs.push_back(D); +else + NonDeducedTemplateParamsInFIndex.push_back(Index); + } + auto DeducedAliasTemplateParams = + TemplateParamsReferencedInTemplateArgumentList( + AliasTemplate->getTemplateParameters()->asArray(), DeducedArgs); + // All template arguments null by default. + SmallVector TemplateArgsForBuildingFPrime( + F->getTemplateParameters()->size()); + + // Create a template parameter list for the synthesized deduction guide f'. + // + // C++ [over.match.class.deduct]p3.2: + // If f is a function template, f' is a function template whose template + // parameter list consists of all the template parameters of A + // (including their default template arguments) that appear in the above + // deductions or (recursively) in their default template arguments + SmallVector FPrimeTemplateParams; + // Store template arguments that refer to the newly-created template + // parameters,
[clang] [clang-tools-extra] [clang] Don't preserve the typo expr in the recovery expr for invalid VarDecls (PR #90948)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/90948 With the commit d5308949cf884d8e4b971d51a8b4f73584c4adec, we now preserve the initializer for invalid decls with the recovery-expr. However there is a chance that the original init expr is a typo-expr, we should not preserve it in the final AST, as typo-expr is an internal AST nodes. We should use the one after the typo correction. This is spotted by a clangd hover crash on the testcase. >From 2f29011bae5bf1b285c2ab1700c887d74eaec4b0 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 3 May 2024 10:06:39 +0200 Subject: [PATCH] [clang] Don't preserve the typo expr in the recovery expr for invalid VarDecls. With the commit d5308949cf884d8e4b971d51a8b4f73584c4adec, we now preserve the initializer for invalid decls with the recovery-expr. However there is a chance that the original init expr is a typo-expr, we should not preserve it in the final AST, as typo-expr is an internal AST nodes. We should use the one after the typo correction. This is spotted by a clangd hover crash on the testcase. --- clang-tools-extra/clangd/unittests/HoverTests.cpp | 13 + clang/lib/Sema/SemaDecl.cpp | 7 +-- clang/test/AST/ast-dump-recovery.cpp | 5 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 5ead74748f550c..28df24f34827c0 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -965,6 +965,19 @@ class Foo final {})cpp"; // Bindings are in theory public members of an anonymous struct. HI.AccessSpecifier = "public"; }}, + {// Don't crash on invalid decl with invalid init expr. + R"cpp( + Unknown [[^abc]] = invalid; + // error-ok + )cpp", + [](HoverInfo ) { + HI.Name = "abc"; + HI.Kind = index::SymbolKind::Variable; + HI.NamespaceScope = ""; + HI.Definition = "int abc = ()"; + HI.Type = "int"; + HI.AccessSpecifier = "public"; + }}, {// Extra info for function call. R"cpp( void fun(int arg_a, int _b) {}; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 19968452f0d566..169df60b56bb4b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13530,9 +13530,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } if (VDecl->isInvalidDecl()) { -CorrectDelayedTyposInExpr(Init, VDecl); +ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl); +std::vector SubExprs; +if (Res.isUsable()) + SubExprs.push_back(Res.get()); ExprResult Recovery = -CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), {Init}); +CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), SubExprs); if (Expr *E = Recovery.get()) VDecl->setInit(E); return; diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp index 77527743fe8577..a88dff471d9f04 100644 --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -419,6 +419,11 @@ void InitializerOfInvalidDecl() { // CHECK: VarDecl {{.*}} invalid InvalidDecl // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'ValidDecl' + + Unknown InvalidDeclWithInvalidInit = Invalid; + // CHECK: VarDecl {{.*}} invalid InvalidDeclWithInvalidInit + // CHECK-NEXT: `-RecoveryExpr {{.*}} '' contains-errors + // CHECK-NOT:`-TypoExpr } void RecoverToAnInvalidDecl() { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
@@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , hokein wrote: We just move the implementation from `DeclareImplicitDeductionGuidesForTypeAlias ` to a dedicated function, so that we can reuse it in the `DeclareAggregateDeductionGuideForTypeAlias`. The functional change of this commit is in `DeclareAggregateDeductionGuideForTypeAlias`, the previous implementation is incorrect, and we should use the one in `DeclareImplicitDeductionGuidesForTypeAlias`. https://github.com/llvm/llvm-project/pull/90894 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/90894 >From 67b790e8a0e3f86155c2569373ced29ddd61c16b Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 2 May 2024 21:06:15 +0200 Subject: [PATCH 1/2] [clang] CTAD: fix the aggregate deduction guide for alias templates. For alias templates, the way we construct their aggregate deduction guides is not following the standard way. We should do the same thing as we do for implicit deduction guides. This patch is mostly a refactoring change that pull the construct logic out from `DeclareImplicitDeductionGuidesForTypeAlias` and reuse it for building aggregate deduction guides. --- clang/lib/Sema/SemaTemplate.cpp | 451 +-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 14 + clang/test/SemaTemplate/deduction-guide.cpp | 9 +- 3 files changed, 227 insertions(+), 247 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 989f3995ca5991..c3dbb0d58e5bb5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , +TypeAliasTemplateDecl *AliasTemplate, +FunctionTemplateDecl *F, SourceLocation Loc) { + LocalInstantiationScope Scope(SemaRef); + Sema::InstantiatingTemplate BuildingDeductionGuides( + SemaRef, AliasTemplate->getLocation(), F, + Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); + if (BuildingDeductionGuides.isInvalid()) +return nullptr; + + auto = SemaRef.Context; + auto [Template, AliasRhsTemplateArgs] = + getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); + + auto RType = F->getTemplatedDecl()->getReturnType(); + // The (trailing) return type of the deduction guide. + const TemplateSpecializationType *FReturnType = + RType->getAs(); + if (const auto *InjectedCNT = RType->getAs()) +// implicitly-generated deduction guide. +FReturnType = InjectedCNT->getInjectedTST(); + else if (const auto *ET = RType->getAs()) +// explicit deduction guide. +FReturnType = ET->getNamedType()->getAs(); + assert(FReturnType && "expected to see a return type"); + // Deduce template arguments of the deduction guide f from the RHS of + // the alias. + // + // C++ [over.match.class.deduct]p3: ...For each function or function + // template f in the guides of the template named by the + // simple-template-id of the defining-type-id, the template arguments + // of the return type of f are deduced from the defining-type-id of A + // according to the process in [temp.deduct.type] with the exception + // that deduction does not fail if not all template arguments are + // deduced. + // + // + // template + // f(X, Y) -> f; + // + // template + // using alias = f; + // + // The RHS of alias is f, we deduced the template arguments of + // the return type of the deduction guide from it: Y->int, X->U + sema::TemplateDeductionInfo TDeduceInfo(Loc); + // Must initialize n elements, this is required by DeduceTemplateArguments. + SmallVector DeduceResults( + F->getTemplateParameters()->size()); + + // FIXME: DeduceTemplateArguments stops immediately at the first + // non-deducible template argument. However, this doesn't seem to casue + // issues for practice cases, we probably need to extend it to continue + // performing deduction for rest of arguments to align with the C++ + // standard. + SemaRef.DeduceTemplateArguments( + F->getTemplateParameters(), FReturnType->template_arguments(), + AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, + /*NumberOfArgumentsMustMatch=*/false); + + SmallVector DeducedArgs; + SmallVector NonDeducedTemplateParamsInFIndex; + // !!NOTE: DeduceResults respects the sequence of template parameters of + // the deduction guide f. + for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { +if (const auto = DeduceResults[Index]; !D.isNull()) // Deduced + DeducedArgs.push_back(D); +else + NonDeducedTemplateParamsInFIndex.push_back(Index); + } + auto DeducedAliasTemplateParams = + TemplateParamsReferencedInTemplateArgumentList( + AliasTemplate->getTemplateParameters()->asArray(), DeducedArgs); + // All template arguments null by default. + SmallVector TemplateArgsForBuildingFPrime( + F->getTemplateParameters()->size()); + + // Create a template parameter list for the synthesized deduction guide f'. + // + // C++ [over.match.class.deduct]p3.2: + // If f is a function template, f' is a function template whose template + // parameter list
[clang] [clang] CTAD: fix the aggregate deduction guide for alias templates. (PR #90894)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/90894 For alias templates, our current way of constructing their aggregate deduction guides deviates from the standard approach. We should align it with how we handle implicit deduction guides. This patch has a refactoring change which pulls the construction logic out from `DeclareImplicitDeductionGuidesForTypeAlia` and reusing it for building aggregate deduction guides. >From 67b790e8a0e3f86155c2569373ced29ddd61c16b Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 2 May 2024 21:06:15 +0200 Subject: [PATCH] [clang] CTAD: fix the aggregate deduction guide for alias templates. For alias templates, the way we construct their aggregate deduction guides is not following the standard way. We should do the same thing as we do for implicit deduction guides. This patch is mostly a refactoring change that pull the construct logic out from `DeclareImplicitDeductionGuidesForTypeAlias` and reuse it for building aggregate deduction guides. --- clang/lib/Sema/SemaTemplate.cpp | 451 +-- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 14 + clang/test/SemaTemplate/deduction-guide.cpp | 9 +- 3 files changed, 227 insertions(+), 247 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 989f3995ca5991..c3dbb0d58e5bb5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2803,7 +2803,207 @@ getRHSTemplateDeclAndArgs(Sema , TypeAliasTemplateDecl *AliasTemplate) { return {Template, AliasRhsTemplateArgs}; } -// Build deduction guides for a type alias template. +// Build deduction guides for a type alias template from the given underlying +// deduction guide F. +FunctionTemplateDecl * +BuildDeductionGuideForTypeAlias(Sema , +TypeAliasTemplateDecl *AliasTemplate, +FunctionTemplateDecl *F, SourceLocation Loc) { + LocalInstantiationScope Scope(SemaRef); + Sema::InstantiatingTemplate BuildingDeductionGuides( + SemaRef, AliasTemplate->getLocation(), F, + Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{}); + if (BuildingDeductionGuides.isInvalid()) +return nullptr; + + auto = SemaRef.Context; + auto [Template, AliasRhsTemplateArgs] = + getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); + + auto RType = F->getTemplatedDecl()->getReturnType(); + // The (trailing) return type of the deduction guide. + const TemplateSpecializationType *FReturnType = + RType->getAs(); + if (const auto *InjectedCNT = RType->getAs()) +// implicitly-generated deduction guide. +FReturnType = InjectedCNT->getInjectedTST(); + else if (const auto *ET = RType->getAs()) +// explicit deduction guide. +FReturnType = ET->getNamedType()->getAs(); + assert(FReturnType && "expected to see a return type"); + // Deduce template arguments of the deduction guide f from the RHS of + // the alias. + // + // C++ [over.match.class.deduct]p3: ...For each function or function + // template f in the guides of the template named by the + // simple-template-id of the defining-type-id, the template arguments + // of the return type of f are deduced from the defining-type-id of A + // according to the process in [temp.deduct.type] with the exception + // that deduction does not fail if not all template arguments are + // deduced. + // + // + // template + // f(X, Y) -> f; + // + // template + // using alias = f; + // + // The RHS of alias is f, we deduced the template arguments of + // the return type of the deduction guide from it: Y->int, X->U + sema::TemplateDeductionInfo TDeduceInfo(Loc); + // Must initialize n elements, this is required by DeduceTemplateArguments. + SmallVector DeduceResults( + F->getTemplateParameters()->size()); + + // FIXME: DeduceTemplateArguments stops immediately at the first + // non-deducible template argument. However, this doesn't seem to casue + // issues for practice cases, we probably need to extend it to continue + // performing deduction for rest of arguments to align with the C++ + // standard. + SemaRef.DeduceTemplateArguments( + F->getTemplateParameters(), FReturnType->template_arguments(), + AliasRhsTemplateArgs, TDeduceInfo, DeduceResults, + /*NumberOfArgumentsMustMatch=*/false); + + SmallVector DeducedArgs; + SmallVector NonDeducedTemplateParamsInFIndex; + // !!NOTE: DeduceResults respects the sequence of template parameters of + // the deduction guide f. + for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { +if (const auto = DeduceResults[Index]; !D.isNull()) // Deduced + DeducedArgs.push_back(D); +else + NonDeducedTemplateParamsInFIndex.push_back(Index); + } + auto DeducedAliasTemplateParams = + TemplateParamsReferencedInTemplateArgumentList( + AliasTemplate->getTemplateParameters()->asArray(), DeducedArgs);
[clang] [AST] Dump explicit template arguments for UnreslovedLookupExpr. (PR #90466)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/90466 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AST] Dump explicit template arguments for UnreslovedLookupExpr. (PR #90466)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/90466 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AST] Dump explicit template arguments for UnreslovedLookupExpr. (PR #90466)
@@ -107,3 +107,17 @@ auto FooFunc(C auto V) -> C decltype(auto) { } } + +namespace dump_unreslove_lookup_arguments { hokein wrote: ah, good catch. I moved to a generic place, ast-dump-templates.cpp. https://github.com/llvm/llvm-project/pull/90466 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AST] Dump explicit template arguments for UnreslovedLookupExpr. (PR #90466)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/90466 >From b584fab7f2283535d4a04bc55efec6ff508870de Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 29 Apr 2024 15:04:01 +0200 Subject: [PATCH 1/2] [AST] Dump explicit template arguments for UnreslovedLookupExpr. Having them dump is useful for ad-hoc debugging. --- clang/include/clang/AST/ASTNodeTraverser.h| 6 ++ clang/test/AST/ast-dump-concepts.cpp | 14 +++ ...dump-template-json-win32-mangler-crash.cpp | 88 +++ 3 files changed, 108 insertions(+) diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 216dc9eef08b62..cf7493ac37852b 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -844,6 +844,12 @@ class ASTNodeTraverser } } + void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr* E) { +if (E->hasExplicitTemplateArgs()) + for (auto Arg : E->template_arguments()) +Visit(Arg.getArgument()); + } + void VisitRequiresExpr(const RequiresExpr *E) { for (auto *D : E->getLocalParameters()) Visit(D); diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp index 5bb174e3548ed2..01064b76f6d462 100644 --- a/clang/test/AST/ast-dump-concepts.cpp +++ b/clang/test/AST/ast-dump-concepts.cpp @@ -107,3 +107,17 @@ auto FooFunc(C auto V) -> C decltype(auto) { } } + +namespace dump_unreslove_lookup_arguments { +template +constexpr bool C = true; + +template +requires(C) +// CHECK: ParenExpr {{.*}} '' lvalue +// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'C' +// CHECK-NEXT: `-TemplateArgument type 'T' +// CHECK-NEXT: `-TemplateTypeParmType {{.*}} 'T' +// CHECK-NEXT: `-TemplateTypeParm {{.*}} 'T' +struct Foo {}; +} diff --git a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp index cf740516db6f4b..5ac55d269dce48 100644 --- a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp +++ b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp @@ -1846,6 +1846,42 @@ int main() // CHECK-NEXT: "kind": "VarTemplateDecl", // CHECK-NEXT: "name": "is_const_v" // CHECK-NEXT: } +// CHECK-NEXT:], +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "TemplateArgument", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const _Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT:"id": "0x{{.*}}", +// CHECK-NEXT:"kind": "QualType", +// CHECK-NEXT:"type": { +// CHECK-NEXT: "qualType": "const _Ty" +// CHECK-NEXT:}, +// CHECK-NEXT:"qualifiers": "const", +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "isDependent": true, +// CHECK-NEXT: "isInstantiationDependent": true, +// CHECK-NEXT: "depth": 0, +// CHECK-NEXT: "index": 0, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmDecl", +// CHECK-NEXT: "name": "_Ty" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT:] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } // CHECK-NEXT:] // CHECK-NEXT: } // CHECK-NEXT: ] @@ -1900,6 +1936,32 @@ int main() // CHECK-NEXT: "kind": "VarTemplateDecl", // CHECK-NEXT: "name": "is_reference_v" // CHECK-NEXT: } +// CHECK-NEXT:], +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "TemplateArgument", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT:"id": "0x{{.*}}", +// CHECK-NEXT:"kind": "TemplateTypeParmType", +// CHECK-NEXT:"type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT:}, +// CHECK-NEXT:"isDependent": true, +// CHECK-NEXT:"isInstantiationDependent": true, +// CHECK-NEXT:"depth": 0, +// CHECK-NEXT:"index": 0, +//
[clang] [AST] Dump explicit template arguments for UnreslovedLookupExpr. (PR #90466)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/90466 >From b584fab7f2283535d4a04bc55efec6ff508870de Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 29 Apr 2024 15:04:01 +0200 Subject: [PATCH 1/2] [AST] Dump explicit template arguments for UnreslovedLookupExpr. Having them dump is useful for ad-hoc debugging. --- clang/include/clang/AST/ASTNodeTraverser.h| 6 ++ clang/test/AST/ast-dump-concepts.cpp | 14 +++ ...dump-template-json-win32-mangler-crash.cpp | 88 +++ 3 files changed, 108 insertions(+) diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 216dc9eef08b62..cf7493ac37852b 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -844,6 +844,12 @@ class ASTNodeTraverser } } + void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr* E) { +if (E->hasExplicitTemplateArgs()) + for (auto Arg : E->template_arguments()) +Visit(Arg.getArgument()); + } + void VisitRequiresExpr(const RequiresExpr *E) { for (auto *D : E->getLocalParameters()) Visit(D); diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp index 5bb174e3548ed2..01064b76f6d462 100644 --- a/clang/test/AST/ast-dump-concepts.cpp +++ b/clang/test/AST/ast-dump-concepts.cpp @@ -107,3 +107,17 @@ auto FooFunc(C auto V) -> C decltype(auto) { } } + +namespace dump_unreslove_lookup_arguments { +template +constexpr bool C = true; + +template +requires(C) +// CHECK: ParenExpr {{.*}} '' lvalue +// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'C' +// CHECK-NEXT: `-TemplateArgument type 'T' +// CHECK-NEXT: `-TemplateTypeParmType {{.*}} 'T' +// CHECK-NEXT: `-TemplateTypeParm {{.*}} 'T' +struct Foo {}; +} diff --git a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp index cf740516db6f4b..5ac55d269dce48 100644 --- a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp +++ b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp @@ -1846,6 +1846,42 @@ int main() // CHECK-NEXT: "kind": "VarTemplateDecl", // CHECK-NEXT: "name": "is_const_v" // CHECK-NEXT: } +// CHECK-NEXT:], +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "TemplateArgument", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const _Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT:"id": "0x{{.*}}", +// CHECK-NEXT:"kind": "QualType", +// CHECK-NEXT:"type": { +// CHECK-NEXT: "qualType": "const _Ty" +// CHECK-NEXT:}, +// CHECK-NEXT:"qualifiers": "const", +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "isDependent": true, +// CHECK-NEXT: "isInstantiationDependent": true, +// CHECK-NEXT: "depth": 0, +// CHECK-NEXT: "index": 0, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmDecl", +// CHECK-NEXT: "name": "_Ty" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT:] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } // CHECK-NEXT:] // CHECK-NEXT: } // CHECK-NEXT: ] @@ -1900,6 +1936,32 @@ int main() // CHECK-NEXT: "kind": "VarTemplateDecl", // CHECK-NEXT: "name": "is_reference_v" // CHECK-NEXT: } +// CHECK-NEXT:], +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "TemplateArgument", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT:"id": "0x{{.*}}", +// CHECK-NEXT:"kind": "TemplateTypeParmType", +// CHECK-NEXT:"type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT:}, +// CHECK-NEXT:"isDependent": true, +// CHECK-NEXT:"isInstantiationDependent": true, +// CHECK-NEXT:"depth": 0, +// CHECK-NEXT:"index": 0, +//
[clang] [AST] Dump explicit template arguments for UnreslovedLookupExpr. (PR #90466)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/90466 Having them dump is useful for ad-hoc debugging (context: https://github.com/llvm/llvm-project/issues/90046) >From b584fab7f2283535d4a04bc55efec6ff508870de Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 29 Apr 2024 15:04:01 +0200 Subject: [PATCH] [AST] Dump explicit template arguments for UnreslovedLookupExpr. Having them dump is useful for ad-hoc debugging. --- clang/include/clang/AST/ASTNodeTraverser.h| 6 ++ clang/test/AST/ast-dump-concepts.cpp | 14 +++ ...dump-template-json-win32-mangler-crash.cpp | 88 +++ 3 files changed, 108 insertions(+) diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 216dc9eef08b62..cf7493ac37852b 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -844,6 +844,12 @@ class ASTNodeTraverser } } + void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr* E) { +if (E->hasExplicitTemplateArgs()) + for (auto Arg : E->template_arguments()) +Visit(Arg.getArgument()); + } + void VisitRequiresExpr(const RequiresExpr *E) { for (auto *D : E->getLocalParameters()) Visit(D); diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp index 5bb174e3548ed2..01064b76f6d462 100644 --- a/clang/test/AST/ast-dump-concepts.cpp +++ b/clang/test/AST/ast-dump-concepts.cpp @@ -107,3 +107,17 @@ auto FooFunc(C auto V) -> C decltype(auto) { } } + +namespace dump_unreslove_lookup_arguments { +template +constexpr bool C = true; + +template +requires(C) +// CHECK: ParenExpr {{.*}} '' lvalue +// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'C' +// CHECK-NEXT: `-TemplateArgument type 'T' +// CHECK-NEXT: `-TemplateTypeParmType {{.*}} 'T' +// CHECK-NEXT: `-TemplateTypeParm {{.*}} 'T' +struct Foo {}; +} diff --git a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp index cf740516db6f4b..5ac55d269dce48 100644 --- a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp +++ b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp @@ -1846,6 +1846,42 @@ int main() // CHECK-NEXT: "kind": "VarTemplateDecl", // CHECK-NEXT: "name": "is_const_v" // CHECK-NEXT: } +// CHECK-NEXT:], +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "TemplateArgument", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "const _Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT:"id": "0x{{.*}}", +// CHECK-NEXT:"kind": "QualType", +// CHECK-NEXT:"type": { +// CHECK-NEXT: "qualType": "const _Ty" +// CHECK-NEXT:}, +// CHECK-NEXT:"qualifiers": "const", +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "isDependent": true, +// CHECK-NEXT: "isInstantiationDependent": true, +// CHECK-NEXT: "depth": 0, +// CHECK-NEXT: "index": 0, +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TemplateTypeParmDecl", +// CHECK-NEXT: "name": "_Ty" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT:] +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } // CHECK-NEXT:] // CHECK-NEXT: } // CHECK-NEXT: ] @@ -1900,6 +1936,32 @@ int main() // CHECK-NEXT: "kind": "VarTemplateDecl", // CHECK-NEXT: "name": "is_reference_v" // CHECK-NEXT: } +// CHECK-NEXT:], +// CHECK-NEXT:"inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "TemplateArgument", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT:"id": "0x{{.*}}", +// CHECK-NEXT:"kind": "TemplateTypeParmType", +// CHECK-NEXT:"type": { +// CHECK-NEXT: "qualType": "_Ty" +// CHECK-NEXT:}, +// CHECK-NEXT:"isDependent": true, +// CHECK-NEXT:"isInstantiationDependent":
[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)
hokein wrote: Friendly ping. https://github.com/llvm/llvm-project/pull/82776 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Add __builtin_start_object_lifetime builtin. (PR #82776)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/82776 >From 3ab1a074592f85715c061007c56c69c24794a556 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 23 Feb 2024 10:03:16 +0100 Subject: [PATCH 1/2] [clang] Add __builtin_start_object_lifetime builtin. This patch implements a clang built `__builtin_start_object_lifetime`, it has the same semantics as C++23's `std::start_lifetime_as`, but without the implicit-lifetime type restriction, it can be used for implementing `std::start_lifetime_as` in the future. Due to the current clang lowering, the builtin reuses the existing `__builtin_launder` implementation: - it is a no-op for the most part; - with `-fstrict-vtable-pointers` flag, we update the vtpr assumption correctly (mark the load/store vptr with appropriate invariant group intrinsics) to prevent incorrect vptr load folding; - for now, the builtin is non-constant, cannot be executed in constant evaluation; CAVEAT: - this builtin may cause TBAA miscomplies without the `-fno-strict-alias` flag. These TBAA miscompiles are known issues and may need more LLVM IR support for the fix, fixing them is orthogonal to the implementaton of the builtin. Context: https://discourse.llvm.org/t/extension-for-creating-objects-via-memcpy/76961 --- clang/include/clang/Basic/Builtins.td | 6 +++ clang/lib/CodeGen/CGBuiltin.cpp | 1 + clang/lib/Sema/SemaChecking.cpp | 2 + clang/test/CodeGen/builtins.c | 10 .../builtin-start-object-life-time.cpp| 49 +++ clang/test/SemaCXX/builtins.cpp | 33 - 6 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenCXX/builtin-start-object-life-time.cpp diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index de721a87b3341d..399fabe53d9fa0 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -926,6 +926,12 @@ def Launder : Builtin { let Prototype = "void*(void*)"; } +def StartObjectLifeTime : Builtin { + let Spellings = ["__builtin_start_object_lifetime"]; + let Attributes = [NoThrow, CustomTypeChecking]; + let Prototype = "void*(void*)"; +} + def IsConstantEvaluated : LangBuiltin<"CXX_LANG"> { let Spellings = ["__builtin_is_constant_evaluated"]; let Attributes = [NoThrow, Constexpr]; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 7e5f2edfc732cc..e81f39149bfbc9 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4521,6 +4521,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(nullptr); } + case Builtin::BI__builtin_start_object_lifetime: case Builtin::BI__builtin_launder: { const Expr *Arg = E->getArg(0); QualType ArgTy = Arg->getType()->getPointeeType(); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 51757f4cf727d6..f16a9a53857154 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -38,6 +38,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" @@ -2641,6 +2642,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, TheCall->setType(Context.IntTy); break; } + case Builtin::BI__builtin_start_object_lifetime: case Builtin::BI__builtin_launder: return BuiltinLaunder(*this, TheCall); case Builtin::BI__sync_fetch_and_add: diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c index 407e0857d22311..00c81c23d0ed02 100644 --- a/clang/test/CodeGen/builtins.c +++ b/clang/test/CodeGen/builtins.c @@ -143,6 +143,7 @@ int main(void) { P(signbit, (1.0)); R(launder, ()); + R(start_object_lifetime, ()); return 0; } @@ -511,6 +512,15 @@ void test_builtin_launder(int *p) { int *d = __builtin_launder(p); } +/// It should be a NOP in C since there are no vtables. +// CHECK-LABEL: define{{.*}} void @test_builtin_start_object_lifetime +void test_builtin_start_object_lifetime(int *p) { + // CHECK: [[TMP:%.*]] = load ptr, + // CHECK-NOT: @llvm.launder + // CHECK: store ptr [[TMP]], + int *d = __builtin_start_object_lifetime(p); +} + // __warn_memset_zero_len should be NOP, see https://sourceware.org/bugzilla/show_bug.cgi?id=25399 // CHECK-LABEL: define{{.*}} void @test___warn_memset_zero_len void test___warn_memset_zero_len(void) { diff --git a/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp new file mode 100644 index 00..58012f52cc0ef5 --- /dev/null +++ b/clang/test/CodeGenCXX/builtin-start-object-life-time.cpp @@ -0,0
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
hokein wrote: > @hokein Independently of the direction taken I'd like to see a better > diagnostic than "atomic constraint using an undocumented/cryptic trait that > is not in the code is not satisfied". > So when we try to print atomic constraints, we should do something more user > friendly for is_deducible. (`note_atomic_constraint_evaluated_to_false` in > `diagnoseWellFormedUnsatisfiedConstraintExpr` AFAICT). It might be a bit > ad-hoc, but I think it's worth doing I agree with you -- having a well-described diagnostic message is better and clearer. I'm happy to improve it once we settle on the final implementation approach (the current diagnostic `because '__is_deducible(AFoo, Foo)' evaluated to false` seems okay to me. GCC also emits similar diagnostics). By the way, other parts of this patch are ready for review. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Implement a bitwise_copyable builtin type trait. (PR #86512)
hokein wrote: Friendly ping, it is ready for the second round of review. https://github.com/llvm/llvm-project/pull/86512 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
hokein wrote: It appears that the consensus is to avoid exposing the internal `__is_deducible` type trait to end-users, as there are no compelling use cases and it's not expected to be used in libc++. This also aligns with the approach taken by GCC. Regarding implementation, the current tablegen-based mechanism doesn't offer an optimal solution for defining internal-only builtins. Several options: 1) Making manual changes in the `TypeTrait` structure code, as proposed by @AaronBallman. While feasible, this approach may be somewhat hacky and would require modifications in multiple places (please see the current implementation, which involves four locations). 2) Following the standard defining-builtin approach but emitting a diagnostic warning when Clang parses `__is_deducible`. This option seems to strike the right balance, as it provides a compromise between adherence to clang's standard implementation and user guidance. Additionally, it would allow for dedicated lit tests for this type trait. 3) Following the standard approach but omitting the type trait name in the `TYPE_TRAIT_2` macro, as suggested by @cor3ntin. However, this approach will affect components that need to print the type-trait name (e.g., AST dump, diagnostics). Opinions and thoughts would be appreciated, @AaronBallman, @cor3ntin, @erichkeane https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
hokein wrote: > > Ah, I see. I haven't tried that, but one downside I can see is that it will > > make diagnostics for CTAD worse, we need to spell the type trait name in > > error messages when the __is_deducible trait fails. > > I think we should have a custom diag for that anyway "is not deducible from" > is better than " `__is_deducible<>` is false" I think this is one of the symptoms, missing the trait name in the AST dump is another symptom. And I'm not aware of an easy way to customize a diagnostic within clang's template-constraint check mechanism. One implementation I can think of is to manual call the `DeduceTemplateArgumentsFromType` in the function overload resolution for the alias CTAD, and then emit a custom diagnostic, but it feels awkward. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
hokein wrote: > > OK, I have hidden the `__is_deducible` trait as suggested. Please take > > another look. > > Sorry, I think my suggestion was not clear enough. did you try to put > `TYPE_TRAIT_2(/**/, IsDeducible, KEYCXX)` in `TokenKinds.def` (and then other > headers should _NOT_ be modified) Ah, I see. I haven't tried that, but one downside I can see is that it will make diagnostics for CTAD worse, we need to spell the type trait name in error messages when the `__is_deducible` trait fails. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] CTAD: implement the missing IsDeducible constraint for alias templates (PR #89358)
hokein wrote: OK, I have hidden the `__is_deducible` trait as suggested. Please take another look. https://github.com/llvm/llvm-project/pull/89358 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits