[clang] [Clang] Clarify diagnostic notes for implicitly generated deduction guides (PR #96084)
@@ -12114,6 +12115,35 @@ static void NoteFunctionCandidate(Sema , OverloadCandidate *Cand, return; } + // If this is an implicit deduction guide against an implicitly defined + // constructor, add a note for it. Neither these deduction guides nor their + // corresponding constructors are explicitly spelled in the source code, hokein wrote: I have a different perspective: I'd prefer printing them as long as they are synthesized (not part of the written source code). While the example of combined template parameters might not be the best one (and I agree that understanding them from existing contexts is often sufficient), the conjunction of associated constraints for a class and the corresponding constructor is probably less obvious. I think printing them would make the situation clearer and help users avoid guessing. Moreover, this approach would be consistent with what GCC does. https://github.com/llvm/llvm-project/pull/96084 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Clarify diagnostic notes for implicitly generated deduction guides (PR #96084)
@@ -12114,6 +12115,35 @@ static void NoteFunctionCandidate(Sema , OverloadCandidate *Cand, return; } + // If this is an implicit deduction guide against an implicitly defined + // constructor, add a note for it. Neither these deduction guides nor their + // corresponding constructors are explicitly spelled in the source code, hokein wrote: Any reason to filter out the "explicit constructor" case? We still synthesize a deduction guide from a constructor, and they are not identical, e.g. its template parameters is a combination of template parameters of the class and template parameters of the corresponding constructor. I think it is useful to print them as well. I think a simple model here would be that we always print synthesized deduction guides (this covers the using-alias case.) https://github.com/llvm/llvm-project/pull/96084 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Clarify diagnostic notes for implicitly generated deduction guides (PR #96084)
@@ -12114,6 +12115,35 @@ static void NoteFunctionCandidate(Sema , OverloadCandidate *Cand, return; } + // If this is an implicit deduction guide against an implicitly defined + // constructor, add a note for it. Neither these deduction guides nor their + // corresponding constructors are explicitly spelled in the source code, + // and simply producing a deduction failure note around the heading of the + // enclosing RecordDecl would be confusing. + // + // We prefer adding such notes at the end of the last deduction failure + // reason because duplicate code snippets appearing in the diagnostic + // would likely become noisy. + auto _ = llvm::make_scope_exit([&] { +auto *DG = dyn_cast(Fn); +if (!DG || !DG->isImplicit() || DG->getCorrespondingConstructor()) hokein wrote: (I assume we always print using-alias deduction guides) Note that checking the implicit guides is not sufficient for using-alias deduction guides. Those synthesized from the explicitly written deduction guide will retain the explicit bit (to ensure correct function overload resolution). https://github.com/llvm/llvm-project/pull/96084 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Clarify diagnostic notes for implicitly generated deduction guides (PR #96084)
hokein wrote: Thanks for the patch! +1 on the idea of printing deduction guides in diagnostics. This improves the experience for both users and compiler developers. This is https://github.com/llvm/llvm-project/issues/92393 :) > Perhaps an approach more similar to what we display for ambiguous cast paths > would be better, i.e., listing each implicit deduction guide we tried in a > single note. > > Thanks for suggesting a better approach. However, implementing this would > require significant changes to our diagnostic logic for overloads. We > currently explain the reasons for deduction failure in subsequent notes, with > around 16 different kinds of deduction failures, each with its own diagnostic > message. Given this complexity, I don't think it's necessary (or feasible) to > special-case CTAD guides for each note. In my opinion, including the deduction guide in the existing note (e.g., `candidate template "template S()-> S" ignored: ...`) is clearer and more concise. It seems that the current implementation in clang assumes all template candidates are written in the source code, which isn't true for the CTAD case. We could extend it to work for not-explicitly-written-in-source-code case. Although we have 19 `candidate template ignored` notes, they are mostly localized in `SemaOverload.cpp`. Extending them is possible but would require some work. However, I don't feel strongly about this, and am also fine with the current implementation, as it has already improved the experience. https://github.com/llvm/llvm-project/pull/96084 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema][CTAD] Allow user defined conversion for copy-list-initialization (PR #94752)
@@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused-value -std=c++20 %s hokein wrote: yeah, that's expected, we disable the clang-format for all lit test files (see the `clang/test/.clang-format`). https://github.com/llvm/llvm-project/pull/94752 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema][CTAD] Allow user defined conversion for copy-list-initialization (PR #94752)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/94752 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema][CTAD] Allow user defined conversion for copy-list-initialization (PR #94752)
https://github.com/hokein approved this pull request. thanks, looks good. https://github.com/llvm/llvm-project/pull/94752 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema][CTAD] Allow user defined conversion for copy-list-initialization (PR #94752)
@@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused-value -std=c++20 %s + +namespace std { + typedef decltype(sizeof(int)) size_t; + + template + struct initializer_list + { +const E *p; +size_t n; +initializer_list(const E *p, size_t n) : p(p), n(n) {} + }; + + struct string { +string(const char *); + }; + + // Classes to use to reproduce the exact scenario present in 62925. +template +class pair{ +public: +pair(T f, Y s) {} +}; + +template +class map { +public: +map(std::initializer_list>, int a = 4, int b = 5) {} +}; + +} // namespace std + + +// Classes to test different levels of nestings and conversions. +template +class Contained { + public: + Contained(T, Y) {} +}; + +template +class A { + public: + A(std::initializer_list >, int) {} +}; + + +// This is the almost the exact code that was in issue #62925. +void testOneLevelNesting() { + std::map mOk = {std::pair{5, 'a'}, {6, 'b'}, {7, 'c'}}; + + // Verify that narrowing conversion is disabled in the first level of nesting. + std::map mNarrow = {std::pair{5, 'a'}, {6.0f, 'b'}, {7, 'c'}}; // expected-error {{type 'float' cannot be narrowed to 'int' in initializer list}} // expected-note {{insert an explicit cast to silence this issue}} +} + +void testMultipleLevelNesting() { + A aOk = {{Contained{5, 'c'}, {5, 'c'}}, 5}; + + // Verify that narrowing conversion is disabled when it is not in a nested + // in another std::initializer_list, but it happens in the most outer one. + A aNarrowNested = {{Contained{5, 'c'}, {5.0f, 'c'}}, 5}; // expected-error {{type 'float' cannot be narrowed to 'int' in initializer list}} // expected-note {{insert an explicit cast to silence this issue}} hokein wrote: Class `Contained` and `pair` look the same (also for `A` and `map`). Can we reuse the `pair` and `map` to test the "mutiple level nesting" case? e.g. `std::map mNaarowNested = {{Contained{5, 'c'}, {5.0f, 'c'}}, 5}};` (you probably need to add a constructor `map(std::initializer_list>, int)`). https://github.com/llvm/llvm-project/pull/94752 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema][CTAD] Allow user defined conversion for copy-list-initialization (PR #94752)
@@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused-value -std=c++20 %s hokein wrote: nit: please format the test file. https://github.com/llvm/llvm-project/pull/94752 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema][CTAD] Allow user defined conversion for copy-list-initialization (PR #94752)
https://github.com/hokein commented: The change looks good to me. Please add a note in `llvm-project/clang/docs/ReleaseNotes.rst`. https://github.com/llvm/llvm-project/pull/94752 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema][CTAD] Allow user defined conversion for copy-list-initialization (PR #94752)
@@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused-value -std=c++20 %s + +namespace std { + typedef decltype(sizeof(int)) size_t; + + template + struct initializer_list + { +const E *p; +size_t n; +initializer_list(const E *p, size_t n) : p(p), n(n) {} + }; + + struct string { hokein wrote: nit: this is not used. https://github.com/llvm/llvm-project/pull/94752 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Sema][CTAD] Allow user defined conversion for copy-list-initialization (PR #94752)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/94752 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [include-cleaner] Pass WorkingDir to suggestPathToFileForDiagnostics (PR #95114)
https://github.com/hokein approved this pull request. https://github.com/llvm/llvm-project/pull/95114 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][HeaderSearch] Fix handling of relative file-paths in suggestPathToFileForDiagnostics (PR #95121)
https://github.com/hokein approved this pull request. https://github.com/llvm/llvm-project/pull/95121 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix handling of brace ellison when building deduction guides (PR #94889)
@@ -10918,22 +10944,24 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( if (!(RD->getDefinition() && RD->isAggregate())) return; QualType Ty = Context.getRecordType(RD); - SmallVector ElementTypes; - - InitListChecker CheckInitList(*this, Entity, ListInit, Ty, ElementTypes); - if (!CheckInitList.HadError()) { + auto BuildAggregateDeductionGuide = [&](MutableArrayRef + ElementTypes, + bool BracedVersion = false) { +if (ElementTypes.empty()) + return; // C++ [over.match.class.deduct]p1.8: // if e_i is of array type and x_i is a braced-init-list, T_i is an // rvalue reference to the declared type of e_i and // C++ [over.match.class.deduct]p1.9: -// if e_i is of array type and x_i is a bstring-literal, T_i is an +// if e_i is of array type and x_i is a string-literal, T_i is an // lvalue reference to the const-qualified declared type of e_i and // C++ [over.match.class.deduct]p1.10: // otherwise, T_i is the declared type of e_i -for (int I = 0, E = ListInit->getNumInits(); +for (int I = 0, E = BracedVersion ? ElementTypes.size() + : ListInit->getNumInits(); I < E && !isa(ElementTypes[I]); ++I) if (ElementTypes[I]->isArrayType()) { -if (isa(ListInit->getInit(I))) +if (isa(ListInit->getInit(I))) hokein wrote: It seems the code is diveraging from the standard. over.match.class.deduct#1.8 says > if e_i is of array type and x_i is a braced-init-list, T_i is an rvalue > reference to the declared type of e_i. And with this change, we will run into this code path if x_i is a `desianged-intializer-list`. https://github.com/llvm/llvm-project/pull/94889 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Don't print extra space when dumping template names (PR #95213)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/95213 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Don't print extra space when dumping template names (PR #95213)
hokein wrote: Thanks for the review, I'd go with the current fix. https://github.com/llvm/llvm-project/pull/95213 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix handling of brace ellison when building deduction guides (PR #94889)
@@ -1449,7 +1449,10 @@ void InitListChecker::CheckSubElementType(const InitializedEntity , // dependent non-array type or an array type with a value-dependent // bound assert(AggrDeductionCandidateParamTypes); - if (!isa_and_nonnull( + // Don't consider the brace elision if the initializer is a + // braced-init-list. + if (isa(expr) || hokein wrote: I think this code does the right thing, to make sure my understanding of the code is correct. Given the example ``` template struct Foo { T t[2]; }; Foo t = {{1, 2}}; ``` The `x1` is a brace-init-list `{1, 2}`, the corresponding `e1` is `T t[2]`, as the `e1` has a dependent type we can't perform semantic checks to see whether the `T t[2]` can be initialized by `x1`, we always assume true here. (This has an effect that we will generate the deduction guide even for invalid case e.g. `x1` is `{1, 2, 3}`, but this is fine as this code will be reject during template instantiation afterwards.) If my understanding is right, can you rephrase the comment `Don't consider the brace elision if the initializer is a braced-init-list.`? Readers can be easily confused with the comment above on L1447 (both are saying brace elision, but they are different). https://github.com/llvm/llvm-project/pull/94889 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix handling of brace ellison when building deduction guides (PR #94889)
@@ -10918,22 +10944,24 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( if (!(RD->getDefinition() && RD->isAggregate())) return; QualType Ty = Context.getRecordType(RD); - SmallVector ElementTypes; - - InitListChecker CheckInitList(*this, Entity, ListInit, Ty, ElementTypes); - if (!CheckInitList.HadError()) { + auto BuildAggregateDeductionGuide = [&](MutableArrayRef + ElementTypes, + bool BracedVersion = false) { +if (ElementTypes.empty()) + return; // C++ [over.match.class.deduct]p1.8: // if e_i is of array type and x_i is a braced-init-list, T_i is an // rvalue reference to the declared type of e_i and // C++ [over.match.class.deduct]p1.9: -// if e_i is of array type and x_i is a bstring-literal, T_i is an +// if e_i is of array type and x_i is a string-literal, T_i is an // lvalue reference to the const-qualified declared type of e_i and // C++ [over.match.class.deduct]p1.10: // otherwise, T_i is the declared type of e_i -for (int I = 0, E = ListInit->getNumInits(); +for (int I = 0, E = BracedVersion ? ElementTypes.size() + : ListInit->getNumInits(); I < E && !isa(ElementTypes[I]); ++I) if (ElementTypes[I]->isArrayType()) { -if (isa(ListInit->getInit(I))) +if (isa(ListInit->getInit(I))) hokein wrote: Hmm, from the grammar rules, I can see designated-initalizer-list can be one of the element of a braced-init-list (e.g. `{ designated-initializer-list }`, but I can't infer `a designated-initializer-list is a braced-init-list`. https://github.com/llvm/llvm-project/pull/94889 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Don't print extra space when dumping template names (PR #95213)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/95213 >From 3c96bf1b16360f52b235d31c08644a2749e7c808 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 12 Jun 2024 11:24:10 +0200 Subject: [PATCH] [clang] Don't print extra blank when dump the template name. --- clang/lib/AST/TextNodeDumper.cpp| 2 +- clang/test/AST/ast-dump-ctad-alias.cpp | 4 ++-- clang/test/AST/ast-dump-template-decls.cpp | 6 +++--- clang/test/AST/ast-dump-using-template.cpp | 8 clang/test/SemaTemplate/deduction-guide.cpp | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index e1a2709507eff..a26f50f0719c1 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1140,7 +1140,7 @@ void TextNodeDumper::dumpTemplateName(TemplateName TN, StringRef Label) { llvm::raw_svector_ostream SS(Str); TN.print(SS, PrintPolicy); } - OS << " '" << Str << "'"; + OS << "'" << Str << "'"; if (Context) { if (TemplateName CanonTN = Context->getCanonicalTemplateName(TN); diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index cd3b8c6821344..a4b6f06547443 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -36,11 +36,11 @@ Out2::AInner t(1.0); // CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible // CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2::AInner' dependent -// CHECK-NEXT: | | | `-name: 'Out2::AInner' +// CHECK-NEXT: | | | `-name: 'Out2::AInner' // CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}} // CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent // CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent -// CHECK-NEXT: | | |-name: 'Inner':'Out::Inner' qualified +// CHECK-NEXT: | | |-name: 'Inner':'Out::Inner' qualified // CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}} // CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' // CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0' diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index fea14abb3b2f4..f0a6204ce3cfa 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -117,7 +117,7 @@ using type2 = typename C::type1; // CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 type2 'typename C::type1':'void (int)' // CHECK-NEXT: ElaboratedType 0x{{[^ ]*}} 'typename C::type1' sugar // CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1' sugar alias -// CHECK-NEXT: name: 'C::type1':'PR55886::C::type1' qualified +// CHECK-NEXT: name: 'C::type1':'PR55886::C::type1' qualified // CHECK-NEXT: NestedNameSpecifier TypeSpec 'C':'PR55886::C' // CHECK-NEXT: TypeAliasTemplateDecl {{.+}} type1 // CHECK-NEXT: TemplateArgument type 'void' @@ -153,7 +153,7 @@ template struct D { }; using t2 = D::B; // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B' sugar alias{{$}} -// CHECK-NEXT: name: 'D::B':'PR56099::D::B' qualified +// CHECK-NEXT: name: 'D::B':'PR56099::D::B' qualified // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1 @@ -175,7 +175,7 @@ template class E {}; using test1 = D; // CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 test1 'D':'subst_default_argument::E>' // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A' sugar -// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified +// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified // CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2 diff --git a/clang/test/AST/ast-dump-using-template.cpp b/clang/test/AST/ast-dump-using-template.cpp index 22b9b76612add..75db5eb5a9d1c 100644 --- a/clang/test/AST/ast-dump-using-template.cpp +++ b/clang/test/AST/ast-dump-using-template.cpp @@ -21,7 +21,7 @@ using A = S; // CHECK: TypeAliasDecl // CHECK-NEXT: `-ElaboratedType {{.*}} 'S' sugar dependent // CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'S' dependent -// CHECK-NEXT: |-name: 'S':'ns::S' qualified +// CHECK-NEXT: |-name: 'S':'ns::S' qualified // CHECk-NEXT: | |-UsingShadowDecl {{.+}} ClassTemplate {{.+}} 'S' // TemplateName in TemplateArgument. @@ -30,7 +30,7 @@ using B = X; // CHECK:
[clang] [clang] fix broken canonicalization of DeducedTemplateSpecializationType (PR #95202)
https://github.com/hokein commented: good catch, the fix looks good to me overall, I will leave the final stamp to @ChuanqiXu9. (I agree that it would be nice to have a regression test if it is not too hard to reduce from libcxx) https://github.com/llvm/llvm-project/pull/95202 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Don't print extra space when dumping template names (PR #95213)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/95213 None >From c5f5d784a8cab287d3ec826a2636874ad9498563 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 12 Jun 2024 11:24:10 +0200 Subject: [PATCH] [clang] Don't print extra blank when dump the template name. --- clang/lib/AST/TextNodeDumper.cpp | 2 +- clang/test/AST/ast-dump-ctad-alias.cpp | 4 ++-- clang/test/AST/ast-dump-template-decls.cpp | 6 +++--- clang/test/AST/ast-dump-using-template.cpp | 8 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index e1a2709507eff..a26f50f0719c1 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1140,7 +1140,7 @@ void TextNodeDumper::dumpTemplateName(TemplateName TN, StringRef Label) { llvm::raw_svector_ostream SS(Str); TN.print(SS, PrintPolicy); } - OS << " '" << Str << "'"; + OS << "'" << Str << "'"; if (Context) { if (TemplateName CanonTN = Context->getCanonicalTemplateName(TN); diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index cd3b8c6821344..a4b6f06547443 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -36,11 +36,11 @@ Out2::AInner t(1.0); // CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible // CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2::AInner' dependent -// CHECK-NEXT: | | | `-name: 'Out2::AInner' +// CHECK-NEXT: | | | `-name: 'Out2::AInner' // CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}} // CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent // CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent -// CHECK-NEXT: | | |-name: 'Inner':'Out::Inner' qualified +// CHECK-NEXT: | | |-name: 'Inner':'Out::Inner' qualified // CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}} // CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' // CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0' diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index fea14abb3b2f4..f0a6204ce3cfa 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -117,7 +117,7 @@ using type2 = typename C::type1; // CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 type2 'typename C::type1':'void (int)' // CHECK-NEXT: ElaboratedType 0x{{[^ ]*}} 'typename C::type1' sugar // CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1' sugar alias -// CHECK-NEXT: name: 'C::type1':'PR55886::C::type1' qualified +// CHECK-NEXT: name: 'C::type1':'PR55886::C::type1' qualified // CHECK-NEXT: NestedNameSpecifier TypeSpec 'C':'PR55886::C' // CHECK-NEXT: TypeAliasTemplateDecl {{.+}} type1 // CHECK-NEXT: TemplateArgument type 'void' @@ -153,7 +153,7 @@ template struct D { }; using t2 = D::B; // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B' sugar alias{{$}} -// CHECK-NEXT: name: 'D::B':'PR56099::D::B' qualified +// CHECK-NEXT: name: 'D::B':'PR56099::D::B' qualified // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1 @@ -175,7 +175,7 @@ template class E {}; using test1 = D; // CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 test1 'D':'subst_default_argument::E>' // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A' sugar -// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified +// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified // CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2 diff --git a/clang/test/AST/ast-dump-using-template.cpp b/clang/test/AST/ast-dump-using-template.cpp index 22b9b76612add..75db5eb5a9d1c 100644 --- a/clang/test/AST/ast-dump-using-template.cpp +++ b/clang/test/AST/ast-dump-using-template.cpp @@ -21,7 +21,7 @@ using A = S; // CHECK: TypeAliasDecl // CHECK-NEXT: `-ElaboratedType {{.*}} 'S' sugar dependent // CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'S' dependent -// CHECK-NEXT: |-name: 'S':'ns::S' qualified +// CHECK-NEXT: |-name: 'S':'ns::S' qualified // CHECk-NEXT: | |-UsingShadowDecl {{.+}} ClassTemplate {{.+}} 'S' // TemplateName in TemplateArgument. @@ -30,7 +30,7 @@ using B = X; // CHECK: TypeAliasDecl // CHECK-NEXT: `-ElaboratedType {{.*}}
[clang] [Clang] Fix handling of brace ellison when building deduction guides (PR #94889)
@@ -335,3 +335,73 @@ namespace TTP { // CHECK-NEXT: `-TemplateArgument type 'T':'type-parameter-0-0'{{$}} // CHECK-NEXT:`-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0{{$}} // CHECK-NEXT: `-TemplateTypeParm {{.+}} 'T'{{$}} + +namespace GH64625 { + +template struct X { + T t[2]; +}; + +X x = {{1, 2}}, y = {1, 2}; hokein wrote: nit: `y = {1, 2}` is already working today. Let's just add the problematic test cases. https://github.com/llvm/llvm-project/pull/94889 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix handling of brace ellison when building deduction guides (PR #94889)
@@ -10918,22 +10944,24 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( if (!(RD->getDefinition() && RD->isAggregate())) return; QualType Ty = Context.getRecordType(RD); - SmallVector ElementTypes; - - InitListChecker CheckInitList(*this, Entity, ListInit, Ty, ElementTypes); - if (!CheckInitList.HadError()) { + auto BuildAggregateDeductionGuide = [&](MutableArrayRef + ElementTypes, + bool BracedVersion = false) { +if (ElementTypes.empty()) + return; // C++ [over.match.class.deduct]p1.8: // if e_i is of array type and x_i is a braced-init-list, T_i is an // rvalue reference to the declared type of e_i and // C++ [over.match.class.deduct]p1.9: -// if e_i is of array type and x_i is a bstring-literal, T_i is an +// if e_i is of array type and x_i is a string-literal, T_i is an // lvalue reference to the const-qualified declared type of e_i and // C++ [over.match.class.deduct]p1.10: // otherwise, T_i is the declared type of e_i -for (int I = 0, E = ListInit->getNumInits(); +for (int I = 0, E = BracedVersion ? ElementTypes.size() + : ListInit->getNumInits(); I < E && !isa(ElementTypes[I]); ++I) if (ElementTypes[I]->isArrayType()) { -if (isa(ListInit->getInit(I))) +if (isa(ListInit->getInit(I))) hokein wrote: Is there any justification for `a designated-initializer-list is also a braced-init-list`? I didn't find any related words in the standard, and I'm not sure this is correct, they at least have different forms per the standard grammar. https://github.com/llvm/llvm-project/pull/94889 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix handling of brace ellison when building deduction guides (PR #94889)
@@ -335,3 +335,73 @@ namespace TTP { // CHECK-NEXT: `-TemplateArgument type 'T':'type-parameter-0-0'{{$}} // CHECK-NEXT:`-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0{{$}} // CHECK-NEXT: `-TemplateTypeParm {{.+}} 'T'{{$}} + +namespace GH64625 { + +template struct X { hokein wrote: Can you add a test with multiple array members? like ``` template struct X { T t1[2]; T t2[3]; }; X x = {{1, 2}, {3, 4, 5}}; ``` https://github.com/llvm/llvm-project/pull/94889 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix handling of brace ellison when building deduction guides (PR #94889)
@@ -305,14 +305,32 @@ namespace { /// structured list even in 'verify only' mode, so that we can track which /// elements need 'empty' initializtion. class InitListChecker { +public: + struct CandidateParamTypesForAggregateDeduction { hokein wrote: nit: instead of using two pointers pointing to the external storage, I'd suggest storing value in this struct, and use a pointer of `CandidateParamTypesForAggregateDeduction` in the `InitListChecker`. https://github.com/llvm/llvm-project/pull/94889 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Fix handling of brace ellison when building deduction guides (PR #94889)
@@ -10918,22 +10944,24 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( if (!(RD->getDefinition() && RD->isAggregate())) return; QualType Ty = Context.getRecordType(RD); - SmallVector ElementTypes; - - InitListChecker CheckInitList(*this, Entity, ListInit, Ty, ElementTypes); - if (!CheckInitList.HadError()) { + auto BuildAggregateDeductionGuide = [&](MutableArrayRef + ElementTypes, + bool BracedVersion = false) { +if (ElementTypes.empty()) + return; // C++ [over.match.class.deduct]p1.8: // if e_i is of array type and x_i is a braced-init-list, T_i is an // rvalue reference to the declared type of e_i and // C++ [over.match.class.deduct]p1.9: -// if e_i is of array type and x_i is a bstring-literal, T_i is an +// if e_i is of array type and x_i is a string-literal, T_i is an // lvalue reference to the const-qualified declared type of e_i and // C++ [over.match.class.deduct]p1.10: // otherwise, T_i is the declared type of e_i -for (int I = 0, E = ListInit->getNumInits(); +for (int I = 0, E = BracedVersion ? ElementTypes.size() + : ListInit->getNumInits(); hokein wrote: this loop becomes harder to reason about, the iterator `I` is used to access two containers `ListInit`, `ElementTypes`, can we add some assertions to make sure we don't have out-of-bound issues here? https://github.com/llvm/llvm-project/pull/94889 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Substitute for the type aliases inside of a CTAD guide (PR #94740)
@@ -2630,7 +2711,8 @@ struct ConvertConstructorToDeductionGuideTransform { ParmVarDecl *transformFunctionTypeParam( ParmVarDecl *OldParam, MultiLevelTemplateArgumentList , - llvm::SmallVectorImpl ) { + llvm::SmallVectorImpl , + bool TransformingOuterPatterns = false) { hokein wrote: nit: remove this default argument for `TransformingOuterPatterns`, there is only 2 places calling this function (one for `true`, the other one for `false`) https://github.com/llvm/llvm-project/pull/94740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Substitute for the type aliases inside of a CTAD guide (PR #94740)
@@ -2220,23 +2220,103 @@ namespace { class ExtractTypeForDeductionGuide : public TreeTransform { llvm::SmallVectorImpl + ClassTemplateDecl *NestedPattern; + const MultiLevelTemplateArgumentList *OuterInstantiationArgs; public: typedef TreeTransform Base; ExtractTypeForDeductionGuide( Sema , - llvm::SmallVectorImpl ) - : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs) {} + llvm::SmallVectorImpl , + ClassTemplateDecl *NestedPattern, + const MultiLevelTemplateArgumentList *OuterInstantiationArgs) + : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs), +NestedPattern(NestedPattern), +OuterInstantiationArgs(OuterInstantiationArgs) {} TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); } + /// Returns true if it's safe to substitute \p Typedef with + /// \p OuterInstantiationArgs. + bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) { +if (!NestedPattern) + return false; + +static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) { + if (DC->Equals(TargetDC)) +return true; + while (DC->isRecord()) { +if (DC->Equals(TargetDC)) + return true; +DC = DC->getParent(); + } + return false; +}; + +if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl())) + return true; +if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext())) + return true; +return false; + } + + QualType + RebuildTemplateSpecializationType(TemplateName Template, +SourceLocation TemplateNameLoc, +TemplateArgumentListInfo ) { +if (!OuterInstantiationArgs || +!isa_and_present(Template.getAsTemplateDecl())) + return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, + TemplateArgs); + +auto *TATD = cast(Template.getAsTemplateDecl()); +auto *Pattern = TATD; +while (Pattern->getInstantiatedFromMemberTemplate()) + Pattern = Pattern->getInstantiatedFromMemberTemplate(); +if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl())) + return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, + TemplateArgs); + +Decl *NewD = SemaRef.SubstDecl( +TATD, SemaRef.getASTContext().getTranslationUnitDecl(), +*OuterInstantiationArgs); +if (!NewD) + return QualType(); + +auto *NewTATD = cast(NewD); +MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl()); + +return Base::RebuildTemplateSpecializationType( +TemplateName(NewTATD), TemplateNameLoc, TemplateArgs); + } + QualType TransformTypedefType(TypeLocBuilder , TypedefTypeLoc TL) { ASTContext = SemaRef.getASTContext(); TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); TypedefNameDecl *Decl = OrigDecl; // Transform the underlying type of the typedef and clone the Decl only if // the typedef has a dependent context. -if (OrigDecl->getDeclContext()->isDependentContext()) { +bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext(); + +// A typedef/alias Decl within the NestedPattern may reference the outer +// template parameters. They're substituted with corresponding instantiation +// arguments here and in RebuildTemplateSpecializationType() above. +// Otherwise, we would have a CTAD guide with "dangling" template +// parameters. +// For example, +// template struct Outer { +// using Alias = S; +// template struct Inner { +// Inner(Alias); +// }; +// }; +if (OuterInstantiationArgs && InDependentContext) { + Decl = cast_if_present(SemaRef.SubstDecl( + OrigDecl, Context.getTranslationUnitDecl(), *OuterInstantiationArgs)); hokein wrote: and here as well. https://github.com/llvm/llvm-project/pull/94740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Substitute for the type aliases inside of a CTAD guide (PR #94740)
@@ -2220,23 +2220,103 @@ namespace { class ExtractTypeForDeductionGuide : public TreeTransform { llvm::SmallVectorImpl + ClassTemplateDecl *NestedPattern; + const MultiLevelTemplateArgumentList *OuterInstantiationArgs; public: typedef TreeTransform Base; ExtractTypeForDeductionGuide( Sema , - llvm::SmallVectorImpl ) - : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs) {} + llvm::SmallVectorImpl , + ClassTemplateDecl *NestedPattern, + const MultiLevelTemplateArgumentList *OuterInstantiationArgs) + : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs), +NestedPattern(NestedPattern), +OuterInstantiationArgs(OuterInstantiationArgs) {} TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); } + /// Returns true if it's safe to substitute \p Typedef with + /// \p OuterInstantiationArgs. + bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) { +if (!NestedPattern) + return false; + +static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) { + if (DC->Equals(TargetDC)) +return true; + while (DC->isRecord()) { +if (DC->Equals(TargetDC)) + return true; +DC = DC->getParent(); + } + return false; +}; + +if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl())) + return true; +if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext())) + return true; +return false; + } + + QualType + RebuildTemplateSpecializationType(TemplateName Template, +SourceLocation TemplateNameLoc, +TemplateArgumentListInfo ) { +if (!OuterInstantiationArgs || +!isa_and_present(Template.getAsTemplateDecl())) + return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, + TemplateArgs); + +auto *TATD = cast(Template.getAsTemplateDecl()); +auto *Pattern = TATD; +while (Pattern->getInstantiatedFromMemberTemplate()) + Pattern = Pattern->getInstantiatedFromMemberTemplate(); +if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl())) + return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, + TemplateArgs); + +Decl *NewD = SemaRef.SubstDecl( +TATD, SemaRef.getASTContext().getTranslationUnitDecl(), +*OuterInstantiationArgs); +if (!NewD) + return QualType(); + +auto *NewTATD = cast(NewD); +MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl()); + +return Base::RebuildTemplateSpecializationType( +TemplateName(NewTATD), TemplateNameLoc, TemplateArgs); + } + QualType TransformTypedefType(TypeLocBuilder , TypedefTypeLoc TL) { ASTContext = SemaRef.getASTContext(); TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); TypedefNameDecl *Decl = OrigDecl; // Transform the underlying type of the typedef and clone the Decl only if // the typedef has a dependent context. -if (OrigDecl->getDeclContext()->isDependentContext()) { +bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext(); + +// A typedef/alias Decl within the NestedPattern may reference the outer +// template parameters. They're substituted with corresponding instantiation +// arguments here and in RebuildTemplateSpecializationType() above. +// Otherwise, we would have a CTAD guide with "dangling" template +// parameters. +// For example, +// template struct Outer { +// using Alias = S; +// template struct Inner { +// Inner(Alias); +// }; +// }; +if (OuterInstantiationArgs && InDependentContext) { + Decl = cast_if_present(SemaRef.SubstDecl( hokein wrote: We will perform the substitution even if the typedef/alias decl doesn't have any dependent template parameter references (e.g. `using Alias = S`.), this seems unnecessary. A simple idea to avoid it is to perform the substitution only if the type of `TypedefNameDecl` is dependent. https://github.com/llvm/llvm-project/pull/94740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Substitute for the type aliases inside of a CTAD guide (PR #94740)
https://github.com/hokein commented: Looks roughly good to me. https://github.com/llvm/llvm-project/pull/94740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Substitute for the type aliases inside of a CTAD guide (PR #94740)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/94740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Substitute for the type aliases inside of a CTAD guide (PR #94740)
@@ -16,3 +16,73 @@ using T = A::B; using Copy = decltype(copy); using Copy = A::B; + +namespace GH94614 { + +template struct S {}; hokein wrote: I wonder whether it is feasible to add an ast-dump test for this issue, I find seeing and verifying the shape of AST deduction guide is clearer. However, the ast-dump doesn't seem to dump much information about the type of the function parameter decl, which is the information we want to verify. https://github.com/llvm/llvm-project/pull/94740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Substitute for the type aliases inside of a CTAD guide (PR #94740)
@@ -2220,23 +2220,103 @@ namespace { class ExtractTypeForDeductionGuide : public TreeTransform { llvm::SmallVectorImpl + ClassTemplateDecl *NestedPattern; + const MultiLevelTemplateArgumentList *OuterInstantiationArgs; public: typedef TreeTransform Base; ExtractTypeForDeductionGuide( Sema , - llvm::SmallVectorImpl ) - : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs) {} + llvm::SmallVectorImpl , + ClassTemplateDecl *NestedPattern, + const MultiLevelTemplateArgumentList *OuterInstantiationArgs) + : Base(SemaRef), MaterializedTypedefs(MaterializedTypedefs), +NestedPattern(NestedPattern), +OuterInstantiationArgs(OuterInstantiationArgs) {} TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); } + /// Returns true if it's safe to substitute \p Typedef with + /// \p OuterInstantiationArgs. + bool mightReferToOuterTemplateParameters(TypedefNameDecl *Typedef) { +if (!NestedPattern) + return false; + +static auto WalkUp = [](DeclContext *DC, DeclContext *TargetDC) { + if (DC->Equals(TargetDC)) +return true; + while (DC->isRecord()) { +if (DC->Equals(TargetDC)) + return true; +DC = DC->getParent(); + } + return false; +}; + +if (WalkUp(Typedef->getDeclContext(), NestedPattern->getTemplatedDecl())) + return true; +if (WalkUp(NestedPattern->getTemplatedDecl(), Typedef->getDeclContext())) + return true; +return false; + } + + QualType + RebuildTemplateSpecializationType(TemplateName Template, +SourceLocation TemplateNameLoc, +TemplateArgumentListInfo ) { +if (!OuterInstantiationArgs || +!isa_and_present(Template.getAsTemplateDecl())) + return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, + TemplateArgs); + +auto *TATD = cast(Template.getAsTemplateDecl()); +auto *Pattern = TATD; +while (Pattern->getInstantiatedFromMemberTemplate()) + Pattern = Pattern->getInstantiatedFromMemberTemplate(); +if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl())) + return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, + TemplateArgs); + +Decl *NewD = SemaRef.SubstDecl( +TATD, SemaRef.getASTContext().getTranslationUnitDecl(), hokein wrote: Passing the `TranslationUnitDecl` seems wrong -- the NewD will be attached to the TU, I think we should use the `DC` member in `ConvertConstructorToDeductionGuideTransform`. https://github.com/llvm/llvm-project/pull/94740 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] Use clang_target_link_libraries() for clang libs (PR #94937)
https://github.com/hokein approved this pull request. https://github.com/llvm/llvm-project/pull/94937 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 6fe5428 - [Flang] Handle the newly-added "Reserved" FramePointerKind for 1a5239251ead73ee57f4e2f7fc93433ac7cf18b1
Author: Haojian Wu Date: 2024-06-07T12:49:41+02:00 New Revision: 6fe5428ecbd18aa263417a244c0850b1271617c0 URL: https://github.com/llvm/llvm-project/commit/6fe5428ecbd18aa263417a244c0850b1271617c0 DIFF: https://github.com/llvm/llvm-project/commit/6fe5428ecbd18aa263417a244c0850b1271617c0.diff LOG: [Flang] Handle the newly-added "Reserved" FramePointerKind for 1a5239251ead73ee57f4e2f7fc93433ac7cf18b1 Added: Modified: clang/lib/Driver/ToolChains/Flang.cpp Removed: diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 9609a1dc65c09..42b45dba2bd31 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -802,6 +802,9 @@ void Flang::ConstructJob(Compilation , const JobAction , case CodeGenOptions::FramePointerKind::None: FPKeepKindStr = "-mframe-pointer=none"; break; + case CodeGenOptions::FramePointerKind::Reserved: +FPKeepKindStr = "-mframe-pointer=reserved"; +break; case CodeGenOptions::FramePointerKind::NonLeaf: FPKeepKindStr = "-mframe-pointer=non-leaf"; break; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 7939312 - Fix -Wunused-variable in SemaAMDGPU.cpp in release build, NFC
Author: Haojian Wu Date: 2024-06-06T15:48:23+02:00 New Revision: 79393124ff74aaaf6a43f7c88e67fd76a6e44239 URL: https://github.com/llvm/llvm-project/commit/79393124ff74aaaf6a43f7c88e67fd76a6e44239 DIFF: https://github.com/llvm/llvm-project/commit/79393124ff74aaaf6a43f7c88e67fd76a6e44239.diff LOG: Fix -Wunused-variable in SemaAMDGPU.cpp in release build, NFC Added: Modified: clang/lib/Sema/SemaAMDGPU.cpp Removed: diff --git a/clang/lib/Sema/SemaAMDGPU.cpp b/clang/lib/Sema/SemaAMDGPU.cpp index 51d4f0d3d964..d11bc9eec330 100644 --- a/clang/lib/Sema/SemaAMDGPU.cpp +++ b/clang/lib/Sema/SemaAMDGPU.cpp @@ -31,7 +31,8 @@ bool SemaAMDGPU::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, constexpr const int SizeIdx = 2; llvm::APSInt Size; Expr *ArgExpr = TheCall->getArg(SizeIdx); -ExprResult R = SemaRef.VerifyIntegerConstantExpression(ArgExpr, ); +[[maybe_unused]] ExprResult R = +SemaRef.VerifyIntegerConstantExpression(ArgExpr, ); assert(!R.isInvalid()); switch (Size.getSExtValue()) { case 1: ___ 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 closed 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] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
hokein wrote: I'm landing it now to unblock our integration. I'm happy to address any post comments. https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/94471 >From 8457c4aa1758d10188da5978d30d2d1ed505e01e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 15:46:56 +0200 Subject: [PATCH 1/4] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f2dc331e61 The incremental processing mode doesn't seem to work well for C++. --- clang/lib/Sema/SemaDecl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a6734ef8c30aa..4b9b735f1cfb4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2288,7 +2288,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Partial translation units that are created in incremental processing must // not clean up the IdResolver because PTUs should take into account the // declarations that came from previous PTUs. -if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC) +if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC || +getLangOpts().CPlusPlus) IdResolver.RemoveDecl(D); // Warn on it if we are shadowing a declaration. >From 5d3e60cc5839fece4f3f8d8d158ae562d7604580 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 20:34:30 +0200 Subject: [PATCH 2/4] Fix more --- clang/lib/Interpreter/IncrementalParser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 5bc8385d874a1..bbc6d3addb085 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -413,7 +413,9 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit ) { if (!ND) continue; // Check if we need to clean up the IdResolver chain. -if (ND->getDeclName().getFETokenInfo()) +if (ND->getDeclName().getFETokenInfo() && +CI->getPreprocessor().isIncrementalProcessingEnabled() && +!D->getLangOpts().ObjC && !D->getLangOpts().CPlusPlus) getCI()->getSema().IdResolver.RemoveDecl(ND); } } >From 59b94757009ceae2a7fe685afd42d933b18cf3dc Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 21:11:25 +0200 Subject: [PATCH 3/4] address review comment. --- clang/lib/Interpreter/IncrementalParser.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index bbc6d3addb085..f709875379d7b 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -414,7 +414,6 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit ) { continue; // Check if we need to clean up the IdResolver chain. if (ND->getDeclName().getFETokenInfo() && -CI->getPreprocessor().isIncrementalProcessingEnabled() && !D->getLangOpts().ObjC && !D->getLangOpts().CPlusPlus) getCI()->getSema().IdResolver.RemoveDecl(ND); } >From 8894026730a65e9f3f352544d3a04251d2b246f1 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 21:30:02 +0200 Subject: [PATCH 4/4] clang-format --- clang/lib/Interpreter/IncrementalParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index f709875379d7b..a8d0294fb6151 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -413,8 +413,8 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit ) { if (!ND) continue; // Check if we need to clean up the IdResolver chain. -if (ND->getDeclName().getFETokenInfo() && -!D->getLangOpts().ObjC && !D->getLangOpts().CPlusPlus) +if (ND->getDeclName().getFETokenInfo() && !D->getLangOpts().ObjC && +!D->getLangOpts().CPlusPlus) getCI()->getSema().IdResolver.RemoveDecl(ND); } } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
@@ -413,7 +413,9 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit ) { if (!ND) continue; // Check if we need to clean up the IdResolver chain. -if (ND->getDeclName().getFETokenInfo()) +if (ND->getDeclName().getFETokenInfo() && +CI->getPreprocessor().isIncrementalProcessingEnabled() && hokein wrote: good point. Removed. https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/94471 >From 8457c4aa1758d10188da5978d30d2d1ed505e01e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 15:46:56 +0200 Subject: [PATCH 1/3] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f2dc331e61 The incremental processing mode doesn't seem to work well for C++. --- clang/lib/Sema/SemaDecl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a6734ef8c30aa..4b9b735f1cfb4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2288,7 +2288,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Partial translation units that are created in incremental processing must // not clean up the IdResolver because PTUs should take into account the // declarations that came from previous PTUs. -if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC) +if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC || +getLangOpts().CPlusPlus) IdResolver.RemoveDecl(D); // Warn on it if we are shadowing a declaration. >From 5d3e60cc5839fece4f3f8d8d158ae562d7604580 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 20:34:30 +0200 Subject: [PATCH 2/3] Fix more --- clang/lib/Interpreter/IncrementalParser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 5bc8385d874a1..bbc6d3addb085 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -413,7 +413,9 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit ) { if (!ND) continue; // Check if we need to clean up the IdResolver chain. -if (ND->getDeclName().getFETokenInfo()) +if (ND->getDeclName().getFETokenInfo() && +CI->getPreprocessor().isIncrementalProcessingEnabled() && +!D->getLangOpts().ObjC && !D->getLangOpts().CPlusPlus) getCI()->getSema().IdResolver.RemoveDecl(ND); } } >From 59b94757009ceae2a7fe685afd42d933b18cf3dc Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 21:11:25 +0200 Subject: [PATCH 3/3] address review comment. --- clang/lib/Interpreter/IncrementalParser.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index bbc6d3addb085..f709875379d7b 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -414,7 +414,6 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit ) { continue; // Check if we need to clean up the IdResolver chain. if (ND->getDeclName().getFETokenInfo() && -CI->getPreprocessor().isIncrementalProcessingEnabled() && !D->getLangOpts().ObjC && !D->getLangOpts().CPlusPlus) getCI()->getSema().IdResolver.RemoveDecl(ND); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
hokein wrote: I have update a new version, please take a second look. https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/94471 >From 8457c4aa1758d10188da5978d30d2d1ed505e01e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 15:46:56 +0200 Subject: [PATCH 1/2] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f2dc331e61 The incremental processing mode doesn't seem to work well for C++. --- clang/lib/Sema/SemaDecl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a6734ef8c30aa..4b9b735f1cfb4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2288,7 +2288,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Partial translation units that are created in incremental processing must // not clean up the IdResolver because PTUs should take into account the // declarations that came from previous PTUs. -if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC) +if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC || +getLangOpts().CPlusPlus) IdResolver.RemoveDecl(D); // Warn on it if we are shadowing a declaration. >From 5d3e60cc5839fece4f3f8d8d158ae562d7604580 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 20:34:30 +0200 Subject: [PATCH 2/2] Fix more --- clang/lib/Interpreter/IncrementalParser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 5bc8385d874a1..bbc6d3addb085 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -413,7 +413,9 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit ) { if (!ND) continue; // Check if we need to clean up the IdResolver chain. -if (ND->getDeclName().getFETokenInfo()) +if (ND->getDeclName().getFETokenInfo() && +CI->getPreprocessor().isIncrementalProcessingEnabled() && +!D->getLangOpts().ObjC && !D->getLangOpts().CPlusPlus) getCI()->getSema().IdResolver.RemoveDecl(ND); } } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
hokein wrote: > Oh, we need to adjust > https://github.com/root-project/root/blob/be5d34934de883270683030b3af2cd1195d17ea8/cmake/modules/RootMacros.cmake#L272 > to skip in case of C++... The link points to an irrelevant project, I assume you mean here https://github.com/llvm/llvm-project/blob/main/clang/lib/Interpreter/IncrementalParser.cpp#L416? If we need to skip for C++, I think we should do it for ObjectiveC as well, like ``` if (ND->getDeclName().getFETokenInfo() && !(!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC || getLangOpts().CPlusPlus)) { ... } ``` https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
hokein wrote: unfortunately, this seems to break an existing test: ``` OK ] InterpreterTest.IncrementalInputTopLevelDecls (66 ms) [ RUN ] InterpreterTest.Errors ClangReplInterpreterTests: /usr/local/google/home/hokein/workspace/llvm-project/clang/lib/Sema/IdentifierResolver.cpp:228: void clang::IdentifierResolver::RemoveDecl(NamedDecl *): Assertion `Ptr && "Didn't find this decl on its identifier's chain!"' failed. #0 0x5591835285e1 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (tools/clang/unittests/Interpreter/ClangReplInterpreterTests+0xa4e45e1) #1 0x559183528b9b PrintStackTraceSignalHandler(void*) Signals.cpp:0:0 #2 0x559183526356 llvm::sys::RunSignalHandlers() (tools/clang/unittests/Interpreter/ClangReplInterpreterTests+0xa4e2356) #3 0x559183529d35 SignalHandler(int) Signals.cpp:0:0 #4 0x7f5baf25a510 (/lib/x86_64-linux-gnu/libc.so.6+0x3c510) #5 0x7f5baf2a816 ``` https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
https://github.com/hokein edited https://github.com/llvm/llvm-project/pull/94471 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f (PR #94471)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/94471 The incremental processing mode doesn't seem to work well for C++. >From 8457c4aa1758d10188da5978d30d2d1ed505e01e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 5 Jun 2024 15:46:56 +0200 Subject: [PATCH] Fix clang reject valid C++ code after d999ce0302f06d250f6d496b56a5a5f2dc331e61 The incremental processing mode doesn't seem to work well for C++. --- clang/lib/Sema/SemaDecl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a6734ef8c30aa..4b9b735f1cfb4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2288,7 +2288,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Partial translation units that are created in incremental processing must // not clean up the IdResolver because PTUs should take into account the // declarations that came from previous PTUs. -if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC) +if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC || +getLangOpts().CPlusPlus) IdResolver.RemoveDecl(D); // Warn on it if we are shadowing a declaration. ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
hokein wrote: > I want to somehow record this breakage in the form of a test for our future > selves when decide to revisit this workaround-looking code. This is the processed file https://gist.github.com/hokein/e4a5881329c3956494afa2de7d350476. > I am a bit overwhelmed right now, are you willing to open a PR with that > change so we can merge it -- otherwise I could look later this week :( Sure, I will prepare one. https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
hokein wrote: > Out of curiosity, in what context you use -fincremental-extensions? The code snippet I provided is extracted from our internal test. We have an internal clang-tool (with the `incremental-extensions` on) to generate headers https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
hokein wrote: Thanks for the prompt response. I think limiting it to C-only will fix the issue (note that there is no `C` in `LangOpts`, you may want to use `!getLangOpts().CPlusPlus` to exclude C++). https://github.com/llvm/llvm-project/pull/89804 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-repl] Extend the C support. (PR #89804)
hokein wrote: @vgvassilev The reland d999ce0302f06d250f6d496b56a5a5f2dc331e61 makes the clang reject the valid code now: ``` $ cat /tmp/t33.cpp #include #include int main() { } $ ./bin/clang -Xclang -fsyntax-only -Xclang=-fincremental-extensions -stdlib=libc++ /tmp/t33.cpp <<< In file included from /tmp/t33.cpp:2: In file included from /usr/include/c++/v1/algorithm:1712: In file included from /usr/include/c++/v1/memory:877: In file included from /usr/include/c++/v1/iterator:684: In file included from /usr/include/c++/v1/__iterator/common_iterator.h:22: /usr/include/c++/v1/variant:1024:43: error: use of undeclared identifier '__arg'; did you mean '_pthread_cleanup_buffer::__arg'? 1024 | } __impl{this, _VSTD::forward<_Arg>(__arg)}; | ^ /usr/include/pthread.h:162:9: note: '_pthread_cleanup_buffer::__arg' declared here 162 | void *__arg;/* Its argument. */ | ^ In file included from /tmp/t33.cpp:2: In file included from /usr/include/c++/v1/algorithm:1861: In file included from /usr/include/c++/v1/__algorithm/ranges_stable_partition.h:15: /usr/include/c++/v1/__algorithm/stable_partition.h:246:18: error: use of undeclared label '__second_half_done' 246 | goto __second_half_done; | ^ 2 errors generated. ``` Can you take a look? https://github.com/llvm/llvm-project/pull/89804 ___ 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 3ce87797dbc36ae792b4d82077cd8f27f1eee53e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 25 Mar 2024 15:10:51 +0100 Subject: [PATCH] [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 __builtin_memcpy(buffer, src, size); // using __builtin_launder to prevent miscompile for -fstrict-vtable-pointers. return __builtin_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/docs/LanguageExtensions.rst | 24 clang/docs/ReleaseNotes.rst | 3 ++ clang/include/clang/AST/Type.h| 14 +++ clang/include/clang/Basic/TokenKinds.def | 2 + clang/lib/AST/Type.cpp| 37 +++ clang/lib/Sema/SemaExprCXX.cpp| 3 ++ ...builtin-is-bitwise-cloneable-fsanitize.cpp | 34 + .../SemaCXX/builtin-is-bitwise-cloneable.cpp | 8 clang/test/SemaObjCXX/arc-type-traits.mm | 9 + 9 files changed, 134 insertions(+) create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable-fsanitize.cpp create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable.cpp diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 46f99d0bbdd06..a49e4122ffc10 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -4016,6 +4016,30 @@ 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) + +**Description**: + +Objects of bitwise cloneable types can be bitwise copied by memcpy/memmove. The +Clang compiler warrants that this behavior is well defined, and won't be +broken by compiler optimizations and sanitizers. + +For implicit-lifetime types, the lifetime of the new object is implicitly +started after the copy. For other types (e.g., classes with virtual methods), +the lifetime isn't started, and using the object results in undefined behavior +according to the C++ Standard. + +This builtin can be used in constant expressions. + Atomic Min/Max builtins with memory ordering diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 39a9013c75a41..3d54144bf9206 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -337,6 +337,9 @@ Non-comprehensive list of changes in this release ``-Winvalid-constexpr`` is not enabled for the function definition, which should result in mild compile-time performance improvements. +- Added ``__is_bitwise_cloneable`` which is used to check whether a type + can be safely copied by memcpy/memmove. + New Compiler Flags -- - ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 263b632df23ce..9eb3f6c09e3d3 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1120,6 +1120,20 @@ class QualType { /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext ) const; + /// Return true if the type is safe to bitwise copy using memcpy/memmove. + /// + /// This is an extension in clang: bitwise cloneable types act as trivially + /// copyable types, meaning their underlying bytes can be safely copied by + /// memcpy or memmove. After the copy, the destination object has the same + /// object representation. + /// + /// However, there are cases where it is not
[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 0eec9639530a137da6c4c4b2cc4249a3f9dd9939 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 25 Mar 2024 15:10:51 +0100 Subject: [PATCH] [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 __builtin_memcpy(buffer, src, size); // using __builtin_launder to prevent miscompile for -fstrict-vtable-pointers. return __builtin_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/docs/LanguageExtensions.rst | 24 clang/docs/ReleaseNotes.rst | 3 ++ clang/include/clang/AST/Type.h| 14 +++ clang/include/clang/Basic/TokenKinds.def | 2 + clang/lib/AST/Type.cpp| 37 +++ clang/lib/Sema/SemaExprCXX.cpp| 3 ++ ...builtin-is-bitwise-cloneable-fsanitize.cpp | 34 + .../SemaCXX/builtin-is-bitwise-cloneable.cpp | 8 clang/test/SemaObjCXX/arc-type-traits.mm | 9 + 9 files changed, 134 insertions(+) create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable-fsanitize.cpp create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable.cpp diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 46f99d0bbdd06..a49e4122ffc10 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -4016,6 +4016,30 @@ 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) + +**Description**: + +Objects of bitwise cloneable types can be bitwise copied by memcpy/memmove. The +Clang compiler warrants that this behavior is well defined, and won't be +broken by compiler optimizations and sanitizers. + +For implicit-lifetime types, the lifetime of the new object is implicitly +started after the copy. For other types (e.g., classes with virtual methods), +the lifetime isn't started, and using the object results in undefined behavior +according to the C++ Standard. + +This builtin can be used in constant expressions. + Atomic Min/Max builtins with memory ordering diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 39a9013c75a41..cc2ff9920b5c1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -337,6 +337,9 @@ Non-comprehensive list of changes in this release ``-Winvalid-constexpr`` is not enabled for the function definition, which should result in mild compile-time performance improvements. +- Added ``__buitlin_bitwise_clonable`` which is used to check whether a type + can be safely copied by memcpy/memmove. + New Compiler Flags -- - ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 263b632df23ce..4bb3a18102ebb 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1120,6 +1120,20 @@ class QualType { /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext ) const; + /// Return true if the type is safe to bitwise copy using memcpy/memmove. + /// + /// This is an extension in clang: bitwise clonable types act as trivially + /// copyable types, meaning their underlying bytes can be safely copied by + /// memcpy or memmove. After the copy, the destination object has the same + /// object representation. + /// + /// However, there are cases where it is not
[clang] [Driver][test] Make the FileCheck less strict for some tests. (PR #94349)
https://github.com/hokein closed https://github.com/llvm/llvm-project/pull/94349 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Driver] Make the FileCheck less strict for some tests. (PR #94349)
@@ -12,7 +12,7 @@ // RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-BE-HF-32R2 %s // -// CHECK-BE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mips-mti-linux" hokein wrote: Thanks, I wasn't aware of the `-no-canonical-prefixes` option, it fixes the failures. https://github.com/llvm/llvm-project/pull/94349 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Driver] Make the FileCheck less strict for some tests. (PR #94349)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/94349 >From b9bd6c36196c7f1fdf6ec7a56260425e0b7255f7 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Jun 2024 14:51:10 +0200 Subject: [PATCH] [Driver] Dont use absolute paths for invoking subcommands for driver tests We see some tests are failing internally after 12949c952c4fbad776a860c003ccf176973278a0. In some CAS systems, we might not see the exact binary name (clang), this patch adds the `-no-canonical-prefixes` option to the command line to not realpath-ify the binary name. --- clang/test/Driver/mips-mti-linux.c | 4 ++-- clang/test/Driver/openmp-offload-gpu.c | 6 +++--- clang/test/Driver/openmp-offload.c | 14 +++--- clang/test/Driver/ve-toolchain.c | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/clang/test/Driver/mips-mti-linux.c b/clang/test/Driver/mips-mti-linux.c index d10eb837b8a6e..e976269dfadf6 100644 --- a/clang/test/Driver/mips-mti-linux.c +++ b/clang/test/Driver/mips-mti-linux.c @@ -6,7 +6,7 @@ //the --gcc-toolchain one. // = Big-endian, mips32r2, hard float -// RUN: %clang -### %s 2>&1 \ +// RUN: %clang -### -no-canonical-prefixes %s 2>&1 \ // RUN: --target=mips-mti-linux -mips32r2 -mhard-float -no-pie \ // RUN: -rtlib=platform -fuse-ld=ld \ // RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ @@ -25,7 +25,7 @@ // CHECK-BE-HF-32R2-SAME: "[[SYSROOT]]/mips-r2-hard-musl/usr/lib{{/|}}crtn.o" // = Little-endian, mips32r2, hard float -// RUN: %clang -### %s 2>&1 \ +// RUN: %clang -### -no-canonical-prefixes %s 2>&1 \ // RUN: --target=mips-mti-linux -mips32r2 -EL -mhard-float -no-pie \ // RUN: -rtlib=platform -fuse-ld=ld \ // RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ diff --git a/clang/test/Driver/openmp-offload-gpu.c b/clang/test/Driver/openmp-offload-gpu.c index 0b98aaf6ba53c..7c91bdab35be0 100644 --- a/clang/test/Driver/openmp-offload-gpu.c +++ b/clang/test/Driver/openmp-offload-gpu.c @@ -70,21 +70,21 @@ /// Check that the runtime bitcode library is part of the compile line. /// Create a bogus bitcode library and specify it with libomptarget-nvptx-bc-path -// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \ +// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \ // RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget/libomptarget-nvptx-test.bc \ // RUN: -Xopenmp-target -march=sm_52 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda \ // RUN: -fopenmp-relocatable-target -save-temps %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-BCLIB %s /// Specify the directory containing the bitcode lib, check clang picks the right one -// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \ +// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \ // RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget \ // RUN: -Xopenmp-target -march=sm_52 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda \ // RUN: -fopenmp-relocatable-target -save-temps \ // RUN: %s 2>&1 | FileCheck -check-prefix=CHK-BCLIB-DIR %s /// Create a bogus bitcode library and find it with LIBRARY_PATH -// RUN: env LIBRARY_PATH=%S/Inputs/libomptarget/subdir %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \ +// RUN: env LIBRARY_PATH=%S/Inputs/libomptarget/subdir %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \ // RUN: -Xopenmp-target -march=sm_52 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda \ // RUN: -fopenmp-relocatable-target -save-temps \ // RUN: %s 2>&1 | FileCheck -check-prefix=CHK-ENV-BCLIB %s diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index 38065d9398f45..eaed0d66df75c 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -35,7 +35,7 @@ /// ### /// Check -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 is passed when compiling for the device. -// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ +// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-EQ-TARGET %s // CHK-FOPENMP-EQ-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" @@ -43,7 +43,7 @@ /// ### /// Check -Xopenmp-target -mcpu=pwr7 is passed when compiling for the device. -// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -mcpu=pwr7 %s 2>&1 \ +// RUN: %clang -###
[clang] [Driver] Make the FileCheck less strict for some tests. (PR #94349)
https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/94349 >From fa0880d477439e4af3f0b1b057dc1c66a2ccbc1e Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Jun 2024 14:51:10 +0200 Subject: [PATCH] [Driver] Make the FileCheck less strict for some tests. We see some tests are failing internally after 12949c952c4fbad776a860c003ccf176973278a0. In some CAS systems, we might not see the exact binary name (clang), this patch removes the binary name in the FileCheck content to make these tests work on CAS. --- clang/test/Driver/mips-mti-linux.c | 4 ++-- clang/test/Driver/openmp-offload-gpu.c | 6 +++--- clang/test/Driver/openmp-offload.c | 10 +- clang/test/Driver/ve-toolchain.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/clang/test/Driver/mips-mti-linux.c b/clang/test/Driver/mips-mti-linux.c index d10eb837b8a6e..0be25a284b777 100644 --- a/clang/test/Driver/mips-mti-linux.c +++ b/clang/test/Driver/mips-mti-linux.c @@ -12,7 +12,7 @@ // RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-BE-HF-32R2 %s // -// CHECK-BE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mips-mti-linux" +// CHECK-BE-HF-32R2: "-triple" "mips-mti-linux" // CHECK-BE-HF-32R2-SAME: "-target-cpu" "mips32r2" // CHECK-BE-HF-32R2-SAME: "-isysroot" "{{.*}}mips_mti_linux/sysroot" // CHECK-BE-HF-32R2: "{{[^"]*}}ld.lld{{[^"]*}}" @@ -31,7 +31,7 @@ // RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-LE-HF-32R2 %s // -// CHECK-LE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mipsel-mti-linux" +// CHECK-LE-HF-32R2: "-triple" "mipsel-mti-linux" // CHECK-LE-HF-32R2-SAME: "-target-cpu" "mips32r2" // CHECK-LE-HF-32R2-SAME: "-isysroot" "{{.*}}mips_mti_linux/sysroot" // CHECK-LE-HF-32R2: "{{[^"]*}}ld.lld{{[^"]*}}" diff --git a/clang/test/Driver/openmp-offload-gpu.c b/clang/test/Driver/openmp-offload-gpu.c index 0b98aaf6ba53c..a9ddf65177ee5 100644 --- a/clang/test/Driver/openmp-offload-gpu.c +++ b/clang/test/Driver/openmp-offload-gpu.c @@ -89,9 +89,9 @@ // RUN: -fopenmp-relocatable-target -save-temps \ // RUN: %s 2>&1 | FileCheck -check-prefix=CHK-ENV-BCLIB %s -// CHK-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget-nvptx-test.bc -// CHK-BCLIB-DIR: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget{{/|}}libomptarget-nvptx-sm_52.bc -// CHK-ENV-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}subdir{{/|}}libomptarget-nvptx-sm_52.bc +// CHK-BCLIB: triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget-nvptx-test.bc +// CHK-BCLIB-DIR: triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget{{/|}}libomptarget-nvptx-sm_52.bc +// CHK-ENV-BCLIB: triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}subdir{{/|}}libomptarget-nvptx-sm_52.bc // CHK-BCLIB-NOT: {{error:|warning:}} /// ### diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index 38065d9398f45..9e7f523895ba3 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -38,7 +38,7 @@ // RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-EQ-TARGET %s -// CHK-FOPENMP-EQ-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" +// CHK-FOPENMP-EQ-TARGET: "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" /// ### @@ -46,7 +46,7 @@ // RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -mcpu=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET %s -// CHK-FOPENMP-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" +// CHK-FOPENMP-TARGET: "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" /// ## @@ -54,7 +54,7 @@ // RUN:%clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu --target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ // RUN:| FileCheck -check-prefix=CHK-FOPENMP-MCPU-TO-SAME-TRIPLE %s -// CHK-FOPENMP-MCPU-TO-SAME-TRIPLE: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" +// CHK-FOPENMP-MCPU-TO-SAME-TRIPLE: "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" /// ## @@ -62,7 +62,7 @@ // RUN:not %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda --target=powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \ //
[clang] [Driver] Make the FileCheck less strict for some tests. (PR #94349)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/94349 We see some tests are failing internally after 12949c952c4fbad776a860c003ccf176973278a0. In CAS systems, we might not see the exact binary name (clang), this patch removes the binary name in the FileCheck content to make these tests work on CAS. >From a5e8cfdc213a889e01080edb1cbdabe279c3449a Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 4 Jun 2024 14:51:10 +0200 Subject: [PATCH] [Driver] Make the FileCheck less strict for some tests. We see some tests are failing internally after 12949c952c4fbad776a860c003ccf176973278a0. In some CAS systems, we might not see the exact binary name (clang), this patch removes the binary name in the FileCheck content to make these tests work on CAS. --- clang/test/Driver/mips-mti-linux.c | 4 ++-- clang/test/Driver/openmp-offload-gpu.c | 6 +++--- clang/test/Driver/openmp-offload.c | 10 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/clang/test/Driver/mips-mti-linux.c b/clang/test/Driver/mips-mti-linux.c index d10eb837b8a6e..0be25a284b777 100644 --- a/clang/test/Driver/mips-mti-linux.c +++ b/clang/test/Driver/mips-mti-linux.c @@ -12,7 +12,7 @@ // RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-BE-HF-32R2 %s // -// CHECK-BE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mips-mti-linux" +// CHECK-BE-HF-32R2: "-triple" "mips-mti-linux" // CHECK-BE-HF-32R2-SAME: "-target-cpu" "mips32r2" // CHECK-BE-HF-32R2-SAME: "-isysroot" "{{.*}}mips_mti_linux/sysroot" // CHECK-BE-HF-32R2: "{{[^"]*}}ld.lld{{[^"]*}}" @@ -31,7 +31,7 @@ // RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-LE-HF-32R2 %s // -// CHECK-LE-HF-32R2: "{{[^"]*}}clang{{[^"]*}}" {{.*}} "-triple" "mipsel-mti-linux" +// CHECK-LE-HF-32R2: "-triple" "mipsel-mti-linux" // CHECK-LE-HF-32R2-SAME: "-target-cpu" "mips32r2" // CHECK-LE-HF-32R2-SAME: "-isysroot" "{{.*}}mips_mti_linux/sysroot" // CHECK-LE-HF-32R2: "{{[^"]*}}ld.lld{{[^"]*}}" diff --git a/clang/test/Driver/openmp-offload-gpu.c b/clang/test/Driver/openmp-offload-gpu.c index 0b98aaf6ba53c..a9ddf65177ee5 100644 --- a/clang/test/Driver/openmp-offload-gpu.c +++ b/clang/test/Driver/openmp-offload-gpu.c @@ -89,9 +89,9 @@ // RUN: -fopenmp-relocatable-target -save-temps \ // RUN: %s 2>&1 | FileCheck -check-prefix=CHK-ENV-BCLIB %s -// CHK-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget-nvptx-test.bc -// CHK-BCLIB-DIR: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget{{/|}}libomptarget-nvptx-sm_52.bc -// CHK-ENV-BCLIB: clang{{.*}}-triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}subdir{{/|}}libomptarget-nvptx-sm_52.bc +// CHK-BCLIB: triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget-nvptx-test.bc +// CHK-BCLIB-DIR: triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}libomptarget{{/|}}libomptarget-nvptx-sm_52.bc +// CHK-ENV-BCLIB: triple{{.*}}nvptx64-nvidia-cuda{{.*}}-mlink-builtin-bitcode{{.*}}subdir{{/|}}libomptarget-nvptx-sm_52.bc // CHK-BCLIB-NOT: {{error:|warning:}} /// ### diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index 38065d9398f45..9e7f523895ba3 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -38,7 +38,7 @@ // RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-EQ-TARGET %s -// CHK-FOPENMP-EQ-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" +// CHK-FOPENMP-EQ-TARGET: "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" /// ### @@ -46,7 +46,7 @@ // RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -mcpu=pwr7 %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET %s -// CHK-FOPENMP-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" +// CHK-FOPENMP-TARGET: "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" /// ## @@ -54,7 +54,7 @@ // RUN:%clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu --target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \ // RUN:| FileCheck -check-prefix=CHK-FOPENMP-MCPU-TO-SAME-TRIPLE %s -// CHK-FOPENMP-MCPU-TO-SAME-TRIPLE: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" +// CHK-FOPENMP-MCPU-TO-SAME-TRIPLE: "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device" ///
[clang] [clang] NFCI: remove obsolete workaround for template default arguments (PR #94311)
https://github.com/hokein approved this pull request. Thanks for the cleanup, this looks good to me. https://github.com/llvm/llvm-project/pull/94311 ___ 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: Add @eugenis as a reviewer, could you take a look on the sanitizer bit? 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)
hokein wrote: > Could we rewrite the description and documentation to capture what the type > trait is doing now? We have a lot of references to the > `is_trivially_copyable`, which is almost fully irrelevant to the current > implementation. Thanks, I updated the PR description and documentation in the code, please take a look again. I think it is worth to mentioning the `is_trivially_copyable`, they're conceptually relevant (users use `is_trivially_copyable` as a safe guard for `memcpy`). > Also, is there a _simple_ way to make this work with the corresponding > sanitizer? If not or it requires too much work, we could definitely return > false here. Just making sure we explored this. This doesn't scale well. There are a few sanitizers (asan, msan etc), and each sanitizer has their own version of memcpy. It is non-trivial to check all sanitizers to ensure all of them work properly. And it doesn't solve types with non-trivial ObjectiveC lifetime. 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)
@@ -4016,6 +4016,34 @@ 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) + +**Description**: + +This trait is similar to `std::is_trivially_copyable`, but additionally allows +to have user-defined constructors, virtual functions and virtual bases. It is up +to the user code to guarantee that a bitwise copy results in non-broken object +and that the lifetime of an object is properly started. + +Objects of bitwise cloneable types can be bitwise copied by memcpy/memmove. The +Clang compiler warrants that this behavior is well defined, and won't be +broken by compiler optimizations. + +After the copy, the lifetime of the new object isn't started yet (unless the +type is trivially copyable). Users must ensure its lifetime is started to avoid +undefined behavior. hokein wrote: > What should the intended action taken by the user be? Is this advice > actionable? I guess that if the type is implicit-lifetime-type, users could use start_lifetime_as (although it's not implemented in Clang). AFAIK, there is no way to start a lifetime of other objects (e.g. containing virtual members). For implicit-lifetime types, users don't need to start the lifetime explicitly, the `memcpy` implicitly starts the lifetime of the object, per the [standard](https://eel.is/c++draft/intro.object#note-6); for other types, yeah, this is no standard way to do it (for our case, we plan to do the trick with `__builtin_launder`, but I would not mention it in the public doc). How about this? ``` For implicit-lifetime types, the lifetime of the new object is implicitly started after the memcpy. For other types (e.g., classes with virtual methods), the lifetime isn't started, and using the object results in undefined behavior according to the C++ Standard, and there is no standard way to start the lifetime. ``` 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)
@@ -2749,6 +2749,17 @@ bool QualType::isTriviallyCopyableType(const ASTContext ) const { /*IsCopyConstructible=*/false); } +bool QualType::isBitwiseCloneableType(const ASTContext & Context) const { + if (const auto *RD = getCanonicalType()->getAsCXXRecordDecl()) { hokein wrote: Agree, for the safety reason, we should disable it for NonTrivialObjCLifetime. 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)
@@ -1120,6 +1120,14 @@ class QualType { /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext ) const; + /// Return true if the type is safe to bitwise copy by memcpy. + /// + /// This is an extension in clang: bitwise clonable types act as trivially hokein wrote: Done, updated the documentation accordingly, please take a second look. 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 011d6bbb434bdb46efe92891fe356885f82c4445 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 25 Mar 2024 15:10:51 +0100 Subject: [PATCH] ination of 2 commits. [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 __builtin_memcpy(buffer, src, size); // using __builtin_launder to prevent miscompile for -fstrict-vtable-pointers. return __builtin_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/docs/LanguageExtensions.rst | 28 +++ clang/docs/ReleaseNotes.rst | 3 ++ clang/include/clang/AST/Type.h| 16 + clang/include/clang/Basic/TokenKinds.def | 2 ++ clang/lib/AST/Type.cpp| 35 +++ clang/lib/Sema/SemaExprCXX.cpp| 3 ++ ...builtin-is-bitwise-cloneable-fsanitize.cpp | 34 ++ .../SemaCXX/builtin-is-bitwise-cloneable.cpp | 9 + clang/test/SemaObjCXX/arc-type-traits.mm | 9 + 9 files changed, 139 insertions(+) create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable-fsanitize.cpp create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable.cpp diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 46f99d0bbdd06..da569b9577e75 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -4016,6 +4016,34 @@ 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) + +**Description**: + +This trait is similar to `std::is_trivially_copyable`, but additionally allows +to have user-defined constructors, virtual functions and virtual bases. It is up +to the user code to guarantee that a bitwise copy results in non-broken object. + +Objects of bitwise cloneable types can be bitwise copied by memcpy/memmove. The +Clang compiler warrants that this behavior is well defined, and won't be +broken by compiler optimizations. + +For implicit-lifetime types, the lifetime of the new object is implicitly +started after the copy. For other types (e.g., classes with virtual methods), +the lifetime isn't started, and using the object results in undefined behavior +according to the C++ Standard. + +This builtin can be used in constant expressions. + Atomic Min/Max builtins with memory ordering diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 58e407a724a9c..2143611560278 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -318,6 +318,9 @@ Non-comprehensive list of changes in this release - Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may now be used within constant expressions. +- Added ``__buitlin_bitwise_clonable`` which is used to check whether a type + can be safely copied by memcpy/memmove. + New Compiler Flags -- - ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 263b632df23ce..0adada068bbfe 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1120,6 +1120,22 @@ class QualType { /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext ) const; + /// Return true if the type is safe to bitwise copy using memcpy/memmove. + /// + /// This is an extension in clang: bitwise clonable types act as
[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 49747cde60dc8a1f4ed4ddcee020f71c88f35287 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 25 Mar 2024 15:10:51 +0100 Subject: [PATCH] [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 __builtin_memcpy(buffer, src, size); // using __builtin_launder to prevent miscompile for -fstrict-vtable-pointers. return __builtin_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/docs/LanguageExtensions.rst | 28 +++ clang/include/clang/AST/Type.h| 8 ++ clang/include/clang/Basic/TokenKinds.def | 2 ++ clang/lib/AST/Type.cpp| 11 clang/lib/Sema/SemaExprCXX.cpp| 3 ++ ...builtin-is-bitwise-cloneable-fsanitize.cpp | 20 + .../SemaCXX/builtin-is-bitwise-cloneable.cpp | 6 7 files changed, 78 insertions(+) create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable-fsanitize.cpp create mode 100644 clang/test/SemaCXX/builtin-is-bitwise-cloneable.cpp diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 46f99d0bbdd06..0168411d04f50 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -4016,6 +4016,34 @@ 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) + +**Description**: + +This trait is similar to `std::is_trivially_copyable`, but additionally allows +to have user-defined constructors, virtual functions and virtual bases. It is up +to the user code to guarantee that a bitwise copy results in non-broken object +and that the lifetime of an object is properly started. + +Objects of bitwise cloneable types can be bitwise copied by memcpy/memmove. The +Clang compiler warrants that this behavior is well defined, and won't be +broken by compiler optimizations. + +After the copy, the lifetime of the new object isn't started yet (unless the +type is trivially copyable). Users must ensure its lifetime is started to avoid +undefined behavior. + +This builtin can be used in constant expressions. + Atomic Min/Max builtins with memory ordering diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 263b632df23ce..d79b942c599cf 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1120,6 +1120,14 @@ class QualType { /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext ) const; + /// Return true if the type is safe to bitwise copy by memcpy. + /// + /// This is an extension in clang: bitwise clonable types act as trivially + /// copyable types, their underlying bytes can be safely copied by memcpy or + /// memmove. Clang guarantees that the destination has the same **object** + /// representations after the copy. + bool isBitwiseCloneableType(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 b5a0e9df9f7ae..9c4b17465e18a 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -542,6 +542,8 @@ TYPE_TRAIT_2(__reference_converts_from_temporary, ReferenceConvertsFromTemporary // is not exposed to users. TYPE_TRAIT_2(/*EmptySpellingName*/, IsDeducible, KEYCXX)
[clang] [clang] CTAD alias: fix transformation for require-clause expr Part2. (PR #93533)
https://github.com/hokein created https://github.com/llvm/llvm-project/pull/93533 In the https://github.com/llvm/llvm-project/pull/90961 fix, we miss a case where the undeduced template parameters of the underlying deduction guide are not transformed, which leaves incorrect depth/index information, and causes crashes when evaluating constraints. This patch fix this missing case. Fixes #92596 Fixes #92212 >From efd657d537e57fd791dcd9cf0c38cc578c023e00 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 17 May 2024 15:28:48 +0200 Subject: [PATCH] [clang] CTAD alias: fix transformation for require-clause expr Part2. In the https://github.com/llvm/llvm-project/pull/90961 fix, we miss a case where the undeduced template parameters of the underlying deduction guide is not transformed, which leaves incorrect depth/index information, and causes crash when evaluating the constraints. This patch fix this missing case. Fixes #92596 Fixes #92212 --- clang/lib/Sema/SemaTemplate.cpp | 32 clang/test/AST/ast-dump-ctad-alias.cpp | 25 +++ clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 25 +++ 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 39e9dbed0c3e0..62d7097f68785 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2780,6 +2780,7 @@ Expr * buildAssociatedConstraints(Sema , FunctionTemplateDecl *F, TypeAliasTemplateDecl *AliasTemplate, ArrayRef DeduceResults, + unsigned UndeducedTemplateParameterStartIndex, Expr *IsDeducible) { Expr *RC = F->getTemplateParameters()->getRequiresClause(); if (!RC) @@ -2840,8 +2841,22 @@ buildAssociatedConstraints(Sema , FunctionTemplateDecl *F, for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) { const auto = DeduceResults[Index]; -if (D.isNull()) +if (D.isNull()) { // non-deduced template parameters of f + auto TP = F->getTemplateParameters()->getParam(Index); + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TemplateArgsForBuildingRC); + // Rebuild the template parameter with updated depth and index. + NamedDecl *NewParam = transformTemplateParameter( + SemaRef, F->getDeclContext(), TP, Args, + /*NewIndex=*/UndeducedTemplateParameterStartIndex++, + getTemplateParameterDepth(TP) + AdjustDepth); + + assert(TemplateArgsForBuildingRC[Index].isNull()); + TemplateArgsForBuildingRC[Index] = Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); continue; +} TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{}); TemplateArgumentLoc Output; @@ -2857,9 +2872,11 @@ buildAssociatedConstraints(Sema , FunctionTemplateDecl *F, MultiLevelTemplateArgumentList ArgsForBuildingRC; ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite); ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC); - // For 2), if the underlying F is instantiated from a member template, we need - // the entire template argument list, as the constraint AST in the - // require-clause of F remains completely uninstantiated. + // For 2), if the underlying function template F is nested in a class template + // (either instantiated from an explicitly-written deduction guide, or + // synthesized from a constructor), we need the entire template argument list, + // as the constraint AST in the require-clause of F remains completely + // uninstantiated. // // For example: // template // depth 0 @@ -2882,7 +2899,8 @@ buildAssociatedConstraints(Sema , FunctionTemplateDecl *F, // We add the outer template arguments which is [int] to the multi-level arg // list to ensure that the occurrence U in `C` will be replaced with int // during the substitution. - if (F->getInstantiatedFromMemberTemplate()) { + if (F->getLexicalDeclContext()->getDeclKind() == + clang::Decl::ClassTemplateSpecialization) { auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs( F, F->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, @@ -3100,6 +3118,7 @@ BuildDeductionGuideForTypeAlias(Sema , Context.getInjectedTemplateArg(NewParam)); TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument; } + unsigned UndeducedTemplateParameterStartIndex = FPrimeTemplateParams.size(); // ...followed by the template parameters of f that were not deduced // (including their default template arguments) for (unsigned FTemplateParamIdx : NonDeducedTemplateParamsInFIndex) { @@ -3169,7 +3188,8 @@
[clang] [Sema] Fix an out-of-bounds crash when diagnosing bad conversion for a function with a parameter pack. (PR #92721)
hokein wrote: The crash is already fixed by https://github.com/llvm/llvm-project/commit/7a28a5b3fee6c78ad59af79a3d03c00db153c49f https://github.com/llvm/llvm-project/pull/92721 ___ 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 closed https://github.com/llvm/llvm-project/pull/92721 ___ 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)
@@ -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(); hokein wrote: thanks for the test cases. (I wonder if there is a case where we should point at the second pack, but I don't come up with one, I think using the first pack is probably good enough. Alternatively, we could use the full `getParametersSourceRange` range without finding a particular pack, but it provides less precise location information). > Should we put that in a function in FunctionDecl? Probably not worth, it seems heavy to add a method in FunctionDecl to only fix this regression. https://github.com/llvm/llvm-project/pull/92721 ___ 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)
@@ -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. hokein wrote: Done. https://github.com/llvm/llvm-project/pull/92721 ___ 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 updated https://github.com/llvm/llvm-project/pull/92721 >From e2dc2cecee5891b88ff4c2e473220cc9fd36df34 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sun, 19 May 2024 22:47:14 +0200 Subject: [PATCH 1/2] [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 825e91876ffce..9fd8661949113 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -629,6 +629,8 @@ Bug Fixes in This Version - ``__is_array`` and ``__is_bounded_array`` no longer return ``true`` for zero-sized arrays. Fixes (#GH54705). +- 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 0c89fca8d38eb..a9603e63336ac 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -11301,8 +11301,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); +} >From 4358b43e283cb13dbe4d32fcce3c68b6da15b12a Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 27 May 2024 09:58:04 +0200 Subject: [PATCH 2/2] review comments Diagnose on the first parameter pack. --- clang/lib/Sema/SemaOverload.cpp | 12 +--- clang/test/Misc/diag-overload-cand-ranges.cpp | 6 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index a9603e63336ac..f9a5032e10c2d 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -11305,9 +11305,15 @@ static void DiagnoseBadConversion(Sema , OverloadCandidate *Cand, if (!isObjectArgument) { if (I < Fn->getNumParams()) ToParamRange = Fn->getParamDecl(I)->getSourceRange(); -else - // parameter pack case. - ToParamRange = Fn->parameters().back()->getSourceRange(); +else { + // For the parameter pack case, diagnose on the first pack. + for (const auto* ParamDecl : Fn->parameters()) { +if (ParamDecl->isParameterPack()) { + ToParamRange = ParamDecl->getSourceRange(); + break; +} + } +} } if (FromTy == S.Context.OverloadTy) { diff --git a/clang/test/Misc/diag-overload-cand-ranges.cpp b/clang/test/Misc/diag-overload-cand-ranges.cpp index 06d638d9b719c..a70ba0d1b1f77 100644 --- a/clang/test/Misc/diag-overload-cand-ranges.cpp +++ b/clang/test/Misc/diag-overload-cand-ranges.cpp @@ -1,4 +1,4 @@ -// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-print-source-range-info %s 2>&1 | FileCheck %s --strict-whitespace +// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-print-source-range-info -std=c++20 %s 2>&1 | FileCheck %s --strict-whitespace // CHECK: error: no matching function template struct mcdata { typedef int result_type; @@ -74,7 +74,11 @@ 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...); +// CHECK: error: no matching function for call to 'abbreviated_func' +// CHECK: :{[[@LINE+1]]:23-[[@LINE+1]]:30}: note: {{.*}} no known conversion from 'int' to
[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 edited https://github.com/llvm/llvm-project/pull/92721 ___ 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 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