[clang] [Clang][Sema] fix noexecpt mismatch of friend declaration (PR #102267)
jcsxky wrote: @sdkrystian Could you please take another look at this patch? The approach does what you said before. When checking exception specific equivalence of the two functions, we do instantiation and substitute all the template parameters with instantiated ones. But we can't find them as we create a new `LocalInstantiationScope`. So these instantiated parameters should be added to current new `LocalInstantiationScope`(like what `addInstantiatedParametersToScope` does in the following code) to make sure they can be found. Consider the test case: ```cpp template struct C { template friend void func() noexcept(N == 0); }; template void func() noexcept(N == 0) {} int main() { C t; return 0; } ``` Without this patch, `Sema::FindInstantiatedDecl` returns original template parameter in transforming exception specific when trying to find instantiated parameter of `N`. So we use the original parameter(`N`) whose depth is 1 in the primary template and this is incorrect and make the comparison failed since it should be 0 in the template specialization. Adding instantiated parameters to current `LocalInstantiationScope` makes `Sema::FindInstantiatedDecl` returns the correct instantiated parameter and it works. https://github.com/llvm/llvm-project/pull/102267 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix noexecpt mismatch of friend declaration (PR #102267)
https://github.com/jcsxky edited https://github.com/llvm/llvm-project/pull/102267 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix noexecpt mismatch of friend declaration (PR #102267)
jcsxky wrote: > substitute so all references to template parameters have the correct depth @sdkrystian Agree! The underlying issue is the incorrect depth makes the comparison of the operands of the `noexcept-specifier` failed. because clang can't find instantiated template parameter declarations in local scope. This approach add the instantiated template parameters to current scope to make clang find it and we get the correct depth. https://github.com/llvm/llvm-project/pull/102267 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Concepts] Fix a constraint comparison regression for out-of-line ClassTemplateDecls (PR #102587)
@@ -599,3 +599,39 @@ template unsigned long DerivedCollection::index() {} } // namespace GH72557 + +namespace GH102320 { + +template +concept Constrained = true; + +template class C { + template > class D; + template +requires Constrained + class E; +}; + +template template > class C::D {}; + +template +template + requires Constrained +class C::E {}; + +#if 0 +// FIXME: Is it conforming? Only Clang rejects it in every released version. +template <> +template T> +class C::D {}; +#endif + jcsxky wrote: I don't think we need this regression. As pointed in this [comment](https://github.com/llvm/llvm-project/pull/102554#discussion_r1710667937), we should not transform `ConceptSpecializationExpr` which makes the depth incorrect. I tested locally and my origin approach also makes sense to this case. https://github.com/llvm/llvm-project/pull/102587 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Concepts] Fix a constraint comparison regression for out-of-line ClassTemplateDecls (PR #102587)
jcsxky wrote: > Note that @jcsxky has a similar patch #102554 that fixes the same thing. I > don't intend to contend against him, and admittedly, that patch works. > > But I don't think that approach is so reasonable because it is hacky in that > `ForConstraintInstantiation` is disabled in the presence of > `ClassTemplateDecl`s, which seemingly does a superfluous job that > `getTemplateInstantiationArgs()` should do and blurs the meaning of the flag. > > That would also leave us a concern about whether we should change all the > other lines where `ForConstraintInstantiation` was true to the same pattern > in `SubstituteConstraintExpressionWithoutSatisfaction`. The approach in this patch does not work on the following case: ```cpp template concept Constrained = true; template class C { template class D; }; template <> template class C::D { }; ``` while mine does. https://github.com/llvm/llvm-project/pull/102587 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix mismatch of out-of-line definition of template class (PR #102554)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/102554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix mismatch of out-of-line definition of template class (PR #102554)
@@ -951,7 +951,8 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, + /*Pattern=*/nullptr, + !isa_and_present(DeclInfo.getDecl()), jcsxky wrote: By the way, I don't think we always need outer arguments since the depth of the `TemplateTypeParmType` in `ConceptSpecializationExpr` is 1 (not 0). https://github.com/llvm/llvm-project/pull/102554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix mismatch of out-of-line definition of template class (PR #102554)
jcsxky wrote: > I'm sorry but this approach doesn't make sense to me. > > I have to say that I self-assigned the issue hours before this patch (I don't > know when you started working on it because you haven't explained anything > either), and that means I'll look into that recently since I've also been > working on another similar case for template packs. Submitting a (especially > unreasonable fix) PR without asking first seems to be very impolite behavior. I am so sorry for that. Since I had been working on this issue yesterday and I didn't notice that you have assigned it to yourself as I didn't refresh my web page. Feel free to submit your solution if you have a better approach. I will close this PR later. Again, sorry for that and I will do better next time. Thanks for your remind! https://github.com/llvm/llvm-project/pull/102554 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix mismatch of out-of-line definition of template class (PR #102554)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/102554 Skip adding template instantiation arguments when the declaration is a nested class template when instantiating constraint expression. attempt to fix https://github.com/llvm/llvm-project/issues/102320 >From 0080b8743a1186d0463e1ff7af73a2a8776b66f1 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Fri, 9 Aug 2024 08:19:09 +0800 Subject: [PATCH] [Clang][Sema] Fix mismatch of out-of-line definition of template class --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaConcept.cpp | 3 ++- clang/test/SemaCXX/PR102320.cpp | 18 ++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/PR102320.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cb0a1b25e51c2..ffc7e34f1166f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -212,6 +212,7 @@ Bug Fixes to C++ Support - Clang now preserves the unexpanded flag in a lambda transform used for pack expansion. (#GH56852), (#GH85667), (#GH99877). - Fixed a bug when diagnosing ambiguous explicit specializations of constrained member functions. +- Fix a bug in out-of-line definition of constrained class template nested in a class template. (GH102320). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index d4c9d044985e3..016dd90b9e95e 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -951,7 +951,8 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, + /*Pattern=*/nullptr, + !isa_and_present(DeclInfo.getDecl()), /*SkipForSpecialization*/ false); if (MLTAL.getNumSubstitutedLevels() == 0) diff --git a/clang/test/SemaCXX/PR102320.cpp b/clang/test/SemaCXX/PR102320.cpp new file mode 100644 index 0..56973875c7b95 --- /dev/null +++ b/clang/test/SemaCXX/PR102320.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s +// expected-no-diagnostics + +template +concept Constrained = true; + +template +class C +{ +template +class D; +}; + +template +template +class C::D +{ +}; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImporter] fix assert fail due to offset overflow (PR #79084)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/79084 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
jcsxky wrote: > We can't go back from non-dependent into dependent. Sorry, maybe I use the word 'transform' that makes you confused. Actually, what I did in `TransformTemplateName` is transforming a `QualifiedTemplateName` which is dependent due to its qualifier dependency and dependent `DeclContext` to a `DependentTemplateName`. Although the transformed `DependentTemplateName` is also dependent, its qualifier is independent. This make the condition https://github.com/llvm/llvm-project/blob/e7622ab4721141d9e6af6041fa7f9bbc1029e9aa/clang/lib/Sema/SemaTemplate.cpp#L4691 false which holds before this patch. This time the flow goes into https://github.com/llvm/llvm-project/blob/e7622ab4721141d9e6af6041fa7f9bbc1029e9aa/clang/lib/Sema/SemaTemplate.cpp#L4741-L4746 and do the specialization. > Can you elaborate on that? I just tried to create `DependentTemplateName` at https://github.com/llvm/llvm-project/blob/e7622ab4721141d9e6af6041fa7f9bbc1029e9aa/clang/lib/Sema/SemaTemplate.cpp#L297-L298 a few days ago and break several cases which contains the code related to partial specialization. But I didn't dig into the code and give up that approach. https://github.com/llvm/llvm-project/pull/94725 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
jcsxky wrote: > I still don't understand why you are saying we didn't or can't build a > DependentTemplateSpecializationType instead. I mean we can transform `QualifiedTemplateName` to `DependentTemplateName` and this is what this patch does. If we build a `DependentTemplateName` instead of `QualifiedTemplateName` earlier would affect the code in partial specialization like: ```cpp template struct A::B ``` https://github.com/llvm/llvm-project/pull/94725 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 4e9e322a82e636783d2ba0ccda92f3547d557a64 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h| 19 ++ .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- .../PR12884_original_no_crash.cpp | 20 +++ clang/test/SemaTemplate/PR91677.cpp | 14 + .../SemaTemplate/typename-specifier-3.cpp | 7 --- 6 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaTemplate/PR12884_original_no_crash.cpp create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7ac0fa0141b47..8f217990a494c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -914,6 +914,7 @@ Bug Fixes to C++ Support - Clang now diagnoses explicit specializations with storage class specifiers in all contexts. - Fix an assertion failure caused by parsing a lambda used as a default argument for the value of a forward-declared class. (#GH93512). +- Clang now transforms qualifier of template name. (#91677). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index cf4e80399632b..6fd9f20647b0b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,25 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (getDerived().AlwaysRebuild() || + QualifierLoc != TransformedQualifierLoc) { +QualifierSS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +QualifierSS, QTN->hasTemplateKeyword() ? SourceLocation() : NameLoc, +*Template->getIdentifier(), NameLoc, ObjectType, +FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..4f447be06b926 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::template B::template C::template D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR12884_original_no_crash.cpp b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp new file mode 100644 index 0..f2b6f6e28c2f9 --- /dev/null +++ b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +namespace PR12884_original { + template struct A { +struct B { + template struct X {}; + typedef int arg; +}; +struct C { + typedef B::X x; // expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A::B'}} +}; + }; + + template <> struct A::B { +template struct X {}; +static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}} + }; + + A::C::x a; // expected-note{{in instantiation of member class 'PR12884_original::A::C' requested here}} +} dif
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 8359bac8e59c6b5ebc6500042dc473c3f4245c08 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h| 19 ++ .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- .../PR12884_original_no_crash.cpp | 20 +++ clang/test/SemaTemplate/PR91677.cpp | 14 + .../SemaTemplate/typename-specifier-3.cpp | 7 --- 6 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaTemplate/PR12884_original_no_crash.cpp create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7ac0fa0141b47..8f217990a494c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -914,6 +914,7 @@ Bug Fixes to C++ Support - Clang now diagnoses explicit specializations with storage class specifiers in all contexts. - Fix an assertion failure caused by parsing a lambda used as a default argument for the value of a forward-declared class. (#GH93512). +- Clang now transforms qualifier of template name. (#91677). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index cf4e80399632b..171f64d35b8cf 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,25 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (getDerived().AlwaysRebuild() || + QualifierLoc != TransformedQualifierLoc) { +QualifierSS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +QualifierSS, QTN->hasTemplateKeyword() ? NameLoc : SourceLocation(), +*Template->getIdentifier(), NameLoc, ObjectType, +FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..bd016894d75e0 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::template template B::template template C::template template D::template template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR12884_original_no_crash.cpp b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp new file mode 100644 index 0..f2b6f6e28c2f9 --- /dev/null +++ b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +namespace PR12884_original { + template struct A { +struct B { + template struct X {}; + typedef int arg; +}; +struct C { + typedef B::X x; // expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A::B'}} +}; + }; + + template <> struct A::B { +template struct X {}; +static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}} + }; + + A::C::x a; // expected-note{{in instantiation of member class 'PR12884_or
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 4b1d55c56f969e926645a856ba67e289776326a8 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h| 19 ++ .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- .../PR12884_original_no_crash.cpp | 20 +++ clang/test/SemaTemplate/PR91677.cpp | 14 + .../SemaTemplate/typename-specifier-3.cpp | 7 --- 6 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaTemplate/PR12884_original_no_crash.cpp create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7ac0fa0141b47..8f217990a494c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -914,6 +914,7 @@ Bug Fixes to C++ Support - Clang now diagnoses explicit specializations with storage class specifiers in all contexts. - Fix an assertion failure caused by parsing a lambda used as a default argument for the value of a forward-declared class. (#GH93512). +- Clang now transforms qualifier of template name. (#91677). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index cf4e80399632b..8beb94b0b3c98 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,25 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (getDerived().AlwaysRebuild() || + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, QTN->hasTemplateKeyword() ? NameLoc : SourceLocation(), +*Template->getIdentifier(), NameLoc, ObjectType, +FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b111d9e91de1d 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{A::template B::template C::template D::template template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR12884_original_no_crash.cpp b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp new file mode 100644 index 0..f2b6f6e28c2f9 --- /dev/null +++ b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +namespace PR12884_original { + template struct A { +struct B { + template struct X {}; + typedef int arg; +}; +struct C { + typedef B::X x; // expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A::B'}} +}; + }; + + template <> struct A::B { +template struct X {}; +static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}} + }; + + A::C::x a; // expected-note{{in instantiation of member class 'PR12884_original::A::C' requested here}} +} diff --git a/clang/test/SemaTemplate/PR91677.c
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
jcsxky wrote: @mizvekov After looking into the code, I think we should transform qualifier in TST. Consider the following code: ```cpp template t1::template t2 f1(); void f2() { f1(); } ``` `TemplateSpecializationType` of `t2` whose `Template` is a `QualifiedTemplateName`(`t1::`) will be dependent if we didn't transform the qualifier since its qualifier and `DeclContext` are both dependent and it wouldn't be specialized in `Sema::CheckTemplateIdType` due to its name dependency. Transform the qualifier and rebuild the `TemplateName` as a `DependentTemplateName` is also consistent with what it is before cpp20(`t2` is a `DependentTemplateName`) which needs a `typename` keyword(`typename t1::template t2`). > The fact that this change somehow affects program semantics is still > unexpected and unexplained. The case in `clang/test/SemaCXX/many-template-parameter-lists.cpp` is affected is because the qualifier didn't be transformed and we can't find the instantiation of the declaration(`X`) which will not happen after this patch. This case is also accepted by gcc. The other cases are expected or explained in the comments. >If I had to take a guess, there is something wrong in the dependency >computation for the NNS. Have you checked that? I didn't find some problems in dependency computation for the NNS. https://github.com/llvm/llvm-project/pull/94725 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 70928fcec829b6cb02fd9fe19b214518c872eea6 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h| 18 + .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- .../PR12884_original_no_crash.cpp | 20 +++ clang/test/SemaTemplate/PR91677.cpp | 14 + .../SemaTemplate/typename-specifier-3.cpp | 7 --- 6 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaTemplate/PR12884_original_no_crash.cpp create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7ac0fa0141b47..8f217990a494c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -914,6 +914,7 @@ Bug Fixes to C++ Support - Clang now diagnoses explicit specializations with storage class specifiers in all contexts. - Fix an assertion failure caused by parsing a lambda used as a default argument for the value of a forward-declared class. (#GH93512). +- Clang now transforms qualifier of template name. (#91677). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index cf4e80399632b..b3872a18da4fa 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,24 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (getDerived().AlwaysRebuild() || + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, SourceLocation(), *Template->getIdentifier(), NameLoc, +ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b5d954986dd4f 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::B::C::D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR12884_original_no_crash.cpp b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp new file mode 100644 index 0..f2b6f6e28c2f9 --- /dev/null +++ b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +namespace PR12884_original { + template struct A { +struct B { + template struct X {}; + typedef int arg; +}; +struct C { + typedef B::X x; // expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A::B'}} +}; + }; + + template <> struct A::B { +template struct X {}; +static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}} + }; + + A::C::x a; // expected-note{{in instantiation of member class 'PR12884_original::A::C' requested here}} +} diff --git a/clang/test/SemaTemplate/PR91677.cpp b/clang/test/SemaTemplate/PR91677.cpp new file mod
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 8327ee1afef04480a1a18eef169f24906e432e87 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h| 18 + .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- .../PR12884_original_no_crash.cpp | 20 +++ clang/test/SemaTemplate/PR91677.cpp | 14 + clang/test/SemaTemplate/instantiate-scope.cpp | 5 + .../SemaTemplate/typename-specifier-3.cpp | 7 --- 7 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 clang/test/SemaTemplate/PR12884_original_no_crash.cpp create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7ac0fa0141b47..8f217990a494c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -914,6 +914,7 @@ Bug Fixes to C++ Support - Clang now diagnoses explicit specializations with storage class specifiers in all contexts. - Fix an assertion failure caused by parsing a lambda used as a default argument for the value of a forward-declared class. (#GH93512). +- Clang now transforms qualifier of template name. (#91677). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index cf4e80399632b..b3872a18da4fa 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,24 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (getDerived().AlwaysRebuild() || + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, SourceLocation(), *Template->getIdentifier(), NameLoc, +ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b5d954986dd4f 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::B::C::D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR12884_original_no_crash.cpp b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp new file mode 100644 index 0..f2b6f6e28c2f9 --- /dev/null +++ b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +namespace PR12884_original { + template struct A { +struct B { + template struct X {}; + typedef int arg; +}; +struct C { + typedef B::X x; // expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A::B'}} +}; + }; + + template <> struct A::B { +template struct X {}; +static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}} + }; + + A::C::x a; // expected-note{{in instantiation of member class 'PR12884_original::A::C' requested here}} +} diff --git a/clang/test/SemaTemplate/PR91
[clang] [Clang][Sema] Skip checking anonymous enum in using enum declaration (PR #87144)
jcsxky wrote: > Hi @jcsxky , I fetched and rebased to origin/main just now (6/16/2024 at > 4:30pm Central US time), and rebuilt - and I see the crash. Did you try > rebasing to latest source and rebuilding? > > `$ clang --analyze -Xclang -analyzer-config -Xclang > experimental-enable-naive-ctu-analysis=true -Xclang -analyzer-config -Xclang > ctu-dir=ctudir -Xclang -analyzer-config -Xclang display-ctu-progress=true > test.cpp` `CTU loaded AST file: bstrwrap.cpp.ast` `clang: > clang/lib/AST/Decl.cpp:4045: void > clang::FunctionDecl::setDescribedFunctionTemplate(clang::FunctionTemplateDecl*): > Assertion "TemplateOrSpecialization.isNull() && "Member function is already > a specialization" failed.` `PLEASE submit a bug report to > https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, > preprocessed source, and associated run script.` > > ... Yes, I have tried the latest source, but it still looks good. Also, I didn't see the output `CTU loaded AST file: bstrwrap.cpp.ast`. I tried this command `clang-extdef-mapping test.cpp` and output is `11:c:@F@test0#` which is different from yours(`f` and `F`, output of the other file is identical). This time I see `CTU loaded AST file: bstrwrap.cpp.ast` but still has no crash. @vabridgers Can you check your output with command `clang-extdef-mapping test.cpp`? https://github.com/llvm/llvm-project/pull/87144 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Skip checking anonymous enum in using enum declaration (PR #87144)
jcsxky wrote: ```cpp ls bstrwrap.cpp bstrwrap.h ctudir test.cpp test.plist test.sh cat bstrwrap.cpp #include "bstrwrap.h" #include Bstrlib::CBString::CBString () { } cat bstrwrap.h #include namespace Bstrlib { struct CBString { CBString (); }; extern std::istream& getline (void); } cat test.cpp #include "bstrwrap.h" int test0 (void) { Bstrlib::CBString c0; return 0; } cat ctudir/externalDefMap.txt 11:c:@f@test0# test.cpp.ast 35:c:@n@Bstrlib@S@CBString@F@CBString# bstrwrap.cpp.ast ~/llvm-project/build/bin/clang test.cpp -emit-ast -D__clang_analyzer__ -w -o ctudir/test.cpp.ast ~/llvm-project/build/bin/clang bstrwrap.cpp -emit-ast -D__clang_analyzer__ -w -o ctudir/bstrwrap.cpp.ast ~/llvm-project/build/bin/clang --analyze -Xclang -analyzer-config -Xclang experimental-enable-naive-ctu-analysis=true -Xclang -analyzer-config -Xclang ctu-dir=ctudir -Xclang -analyzer-config -Xclang display-ctu-progress=true test.cpp ``` I have tested locally using main branch with clang and it has no crash. Maybe I missed something? Could you please take a second look? @vabridgers https://github.com/llvm/llvm-project/pull/87144 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Skip checking anonymous enum in using enum declaration (PR #87144)
jcsxky wrote: > This change has caused a regression in one of our systems integration tests > that test static analysis for the bstring lib project > (https://github.com/websnarf/bstrlib) with cross translation unit analysis > enabled. Unfortunately I do not have a simple reproducer that stands alone > just using clang, but I do have a reproducer that uses CodeChecker and can > paste in the crash signature here. Please consider reverting the change until > a proper fix can be made and this issue is addressed. > > ``` > bstrwrap.cpp > 1 #include "bstrwrap.h" > 2 #include > 3 > 4 Bstrlib::CBString::CBString () { > 5 } > > bstrwrap.h > 1 #include > 2 > 3 namespace Bstrlib { > 4 struct CBString { > 5CBString (); > 6 }; > 7 > 8 extern std::istream& getline (std::istream& sin, CBString& b, char > terminator='\n'); > 9 > 10 } // namespace Bstrlib > > > test.cpp > 1 #include "bstrwrap.h" > 2 > 3 int test0 (void) { > 4 Bstrlib::CBString c0; > 5 return 0; > 6 } > ``` > > Using CodeChecker from https://github.com/Ericsson/codechecker, Log the build > > `CodeChecker log -b "g++ -c test.cpp bstrwrap.cpp" -o comp.json` > > Repro step > > ``` > ``env PATH=:$PATH CC_ANALYZERS_FROM_PATH=1 CodeChecker > analyze comp.json --clean --ctu -o report --analyzers clangsa`` > ``` > > The crash signature, appears to be crashing in AST Import. > > ``` > 1. parser at end of file > 2. While analyzing stack: > #0 Calling test0() > 3. test.cpp:4:21: Error evaluating statement > 4. test.cpp:4:21: Error evaluating statement > #0 0x03cb7248 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) > (clang-19+0x3cb7248) > #1 0x03cb4f2c llvm::sys::CleanupOnSignal(unsigned long) > (clang-19+0x3cb4f2c) > #2 0x03bfd308 CrashRecoverySignalHandler(int) > CrashRecoveryContext.cpp:0:0 > #3 0x7f9e5d53d630 __restore_rt sigaction.c:0:0 > #4 0x7f9e5af39387 raise (/lib64/libc.so.6+0x36387) > #5 0x7f9e5af3aa78 abort (/lib64/libc.so.6+0x37a78) > #6 0x7f9e5af321a6 __assert_fail_base (/lib64/libc.so.6+0x2f1a6) > #7 0x7f9e5af32252 (/lib64/libc.so.6+0x2f252) > #8 0x072ada26 > clang::FunctionDecl::setDescribedFunctionTemplate(clang::FunctionTemplateDecl*) > (clang-19+0x72ada26) > #9 0x07190a56 > clang::ASTNodeImporter::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl*) > (clang-19+0x7190a56) > #10 0x0716e998 clang::declvisitor::Base clang::ASTNodeImporter, llvm::Expected>::Visit(clang::Decl*) > crtstuff.c:0:0 > #11 0x0716eedb clang::ASTImporter::Import(clang::Decl*) > (clang-19+0x716eedb) > #12 0x07172108 std::conditional clang::Decl>, llvm::Expected, > llvm::Expected>::type > clang::ASTNodeImporter::import(clang::Decl*) crtstuff.c:0:0 > #13 0x0717d072 > clang::ASTNodeImporter::ImportDeclContext(clang::DeclContext*, bool) > (clang-19+0x717d072) > #14 0x0718677b > clang::ASTNodeImporter::VisitNamespaceDecl(clang::NamespaceDecl*) > (clang-19+0x718677b) > #15 0x0716ea38 clang::declvisitor::Base clang::ASTNodeImporter, llvm::Expected>::Visit(clang::Decl*) > crtstuff.c:0:0 > #16 0x0716eedb clang::ASTImporter::Import(clang::Decl*) > (clang-19+0x716eedb) > #17 0x07175146 > clang::ASTImporter::Import(clang::NestedNameSpecifier*) (clang-19+0x7175146) > #18 0x0717a0bb > clang::ASTNodeImporter::VisitElaboratedType(clang::ElaboratedType const*) > (clang-19+0x717a0bb) > #19 0x07174945 clang::TypeVisitor llvm::Expected>::Visit(clang::Type const*) crtstuff.c:0:0 > #20 0x07174c07 clang::ASTImporter::Import(clang::Type const*) > (clang-19+0x7174c07) > #21 0x07175bd7 clang::ASTImporter::Import(clang::QualType) > (clang-19+0x7175bd7) > #22 0x07177e20 > clang::ASTNodeImporter::VisitLValueReferenceType(clang::LValueReferenceType > const*) (clang-19+0x7177e20) > ``` Looks like ASTImporter issue. Could you please provider a reproducer using clang only? That would be better to catch the issue. Just reverting this patch may not crash any more, but it would lead to incorrect AST be imported and influenced the accuracy of static analysis. https://github.com/llvm/llvm-project/pull/87144 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] SourceLocIdentKind::Function should not be dependent (PR #94942)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/94942 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] SourceLocIdentKind::Function should not be dependent (PR #94942)
jcsxky wrote: > So, looked into this more. You are correct that `Function` needs not be > dependent because we only ever show the name of the function unqualified. > However, `FunctionSig` does. Here is an example of what we are trying to > preserve https://godbolt.org/z/M3eTa8nn5 (the clang 17 behavior was incorrect) > > I apologize for not realizing earlier that your change was actually sensible > in the case of `Function` Never mind! After looking into the code a little bit more, `FunctionSig` indeed needs to be dependent. ```cpp template constexpr int g() { return N; } template struct S { void f(auto) { constexpr const char* F = __builtin_FUNCSIG(); static_assert(__builtin_strlen(F)==g<__builtin_strlen(F)>()); } }; void f(){ S{}.f(0); } ``` However, it still crash when we changed from `__builtin_FUNCTION` to `__builtin_FUNCSIG` in the testcase from https://github.com/llvm/llvm-project/issues/80210. The underlying issue is that `CurContext` is `FunctionTemplateDecl` which is dependent and we used it as `ParentContext` of `SourceLocExpr` when transforming `decltype` of function `construct_at`. This makes transformed return type of `construct_at` dependent which is not what we want. I will close this patch since it doesn't resolve the underlying issue. Thanks for your time for the review! @cor3ntin https://github.com/llvm/llvm-project/pull/94942 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] SourceLocIdentKind::Function should not be dependent (PR #94942)
jcsxky wrote: ```cpp struct BasicPersistent; struct SourceLocation { static constexpr const char* Current(const char * func = __builtin_FUNCTION()) { return func; } }; template BasicPersistent &&__declval(int); template auto declval() -> decltype(__declval<_Tp>(0)); template _Tp forward; template auto construct_at(_Tp *, _Args...) -> decltype(new _Tp(declval<_Args>()...)) { constexpr auto *F = SourceLocation::Current(); static_assert(__builtin_strlen(F) == 12); return 0; } template struct allocator; template struct allocator_traits; template struct allocator_traits> { using pointer = _Tp *; template static void construct(_Up __p, _Args...) { construct_at(__p, forward<_Args>...); } }; struct __alloc_traits : allocator_traits> { } push_back___x; __alloc_traits::pointer _M_impl_0; template void emplace_back(_Args...) { __alloc_traits::construct(_M_impl_0, forward<_Args>...); } struct BasicPersistent { BasicPersistent(BasicPersistent &&, const char* = SourceLocation::Current()) {} }; void CFXJSE_EngineAddObjectToUpArray() { emplace_back(push_back___x); } ``` I modify the testcase as above and I think we just need to make dependent if Kind is `SourceLocIdentKind::SourceLocStruct`. Could you please take another look? @cor3ntin https://github.com/llvm/llvm-project/pull/94942 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] SourceLocIdentKind::Function should not be dependent (PR #94942)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94942 >From 96f4e2a5c82296b61e53189135d88a2d2b0da9f4 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Mon, 10 Jun 2024 16:53:54 +0800 Subject: [PATCH] [clang] SourceLocIdentKind::Function should not be dependent --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/AST/Expr.h| 2 -- clang/test/CodeGenCXX/PR80210.cpp | 34 +++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGenCXX/PR80210.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cf1ba02cbc4b2..efe78139de6fa 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -846,6 +846,7 @@ Bug Fixes to C++ Support - Fix a crash caused by improper use of ``__array_extent``. (#GH80474) - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). +- Fix a crash when SourceLocExpr instantiated in a dependent context. (GH80210). Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index f2bf667636dc9..f1f7d49cc6c63 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4786,8 +4786,6 @@ class SourceLocExpr final : public Expr { static bool MayBeDependent(SourceLocIdentKind Kind) { switch (Kind) { -case SourceLocIdentKind::Function: -case SourceLocIdentKind::FuncSig: case SourceLocIdentKind::SourceLocStruct: return true; default: diff --git a/clang/test/CodeGenCXX/PR80210.cpp b/clang/test/CodeGenCXX/PR80210.cpp new file mode 100644 index 0..fdd3beb99209e --- /dev/null +++ b/clang/test/CodeGenCXX/PR80210.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o /dev/null -verify -triple %itanium_abi_triple +// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o /dev/null -verify -triple %ms_abi_triple + +// expected-no-diagnostics + +struct BasicPersistent; +template BasicPersistent &&__declval(int); +template auto declval() -> decltype(__declval<_Tp>(0)); +template _Tp forward; +template +auto construct_at(_Tp *, _Args...) -> decltype(new _Tp(declval<_Args>()...)) {return 0;} +template struct allocator; +template struct allocator_traits; +template struct allocator_traits> { + using pointer = _Tp *; + template + static void construct(_Up __p, _Args...) { +construct_at(__p, forward<_Args>...); + } +}; +struct __alloc_traits : allocator_traits> { +} push_back___x; +__alloc_traits::pointer _M_impl_0; +template void emplace_back(_Args...) { + __alloc_traits::construct(_M_impl_0, forward<_Args>...); +} +struct SourceLocation { + static SourceLocation Current(const char * = __builtin_FUNCTION()); +}; +struct BasicPersistent { + BasicPersistent(BasicPersistent &&, + SourceLocation = SourceLocation::Current()); +}; +void CFXJSE_EngineAddObjectToUpArray() { emplace_back(push_back___x); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
jcsxky wrote: > Needs changes as discussed. > Needs changes as discussed. I am really appreciate for your guidance and I will check in the weekend. https://github.com/llvm/llvm-project/pull/94725 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] SourceLocIdentKind::Function should not be dependent (PR #94942)
jcsxky wrote: > SourceLocation needs to be dependent because we want to make the name of the > function and any template parameter refers to the instantiated function > rather than that of the function template. This was changed in #78436 > > The issue is that SourceLocation then is a dependent expression that does not > depend on any parameters and its never re-transformed (hence the crash). > > I have so far been unable to find a solution. I wonder if we should attach > the template parameters to the source location expression, but that seems a > bit involved. I tested this patch locally with the code from https://github.com/llvm/llvm-project/issues/78128 and it works well. I doubt whether we need to make `SourceLocation` dependent when `Kind` is `SourceLocIdentKind::Function`. I don't come up with a testcase that make this patch failed or crash. https://github.com/llvm/llvm-project/pull/94942 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [StructuralEquivalence] improve NTTP and CXXDependentScopeMemberExpr comparison (PR #95190)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/95190 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [StructuralEquivalence] improve NTTP and CXXDependentScopeMemberExpr comparison (PR #95190)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/95190 >From ba081d51a0cc803188760eec2847bfc73d2192b8 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Wed, 12 Jun 2024 09:47:16 +0800 Subject: [PATCH] [StructuralEquivalence] improve NTTP and CXXDependentScopeMemberExpr comparison --- clang/lib/AST/ASTStructuralEquivalence.cpp| 14 - .../AST/StructuralEquivalenceTest.cpp | 57 ++- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index d56bf21b459e0..37555c324282f 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -348,6 +348,15 @@ class StmtComparer { return true; } + bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1, +const CXXDependentScopeMemberExpr *E2) { +if (!IsStructurallyEquivalent(Context, E1->getMember(), E2->getMember())) { + return false; +} +return IsStructurallyEquivalent(Context, E1->getBaseType(), +E2->getBaseType()); + } + bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1, const UnaryExprOrTypeTraitExpr *E2) { if (E1->getKind() != E2->getKind()) @@ -1997,7 +2006,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } return false; } - + if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth()) +return false; + if (D1->getIndex() != D2->getIndex()) +return false; // Check types. if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) { if (Context.Complain) { diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 91dd717d7b25e..952c83be0cb64 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -1877,6 +1877,34 @@ TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) { EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second)); } +TEST_F(StructuralEquivalenceCacheTest, + NonTypeTemplateParmWithDifferentPositionNoEq) { + auto TU = makeTuDecls( + R"( + template + struct A { +template +void foo() {} + }; + )", + R"( + template + struct A { +template +void foo() {} + }; + )", + Lang_CXX03); + + StructuralEquivalenceContext Ctx( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); + + auto NTTP = findDeclPair( + TU, nonTypeTemplateParmDecl(hasName("T"))); + EXPECT_FALSE(Ctx.IsEquivalent(NTTP.first, NTTP.second)); +} + TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) { auto TU = makeTuDecls( R"( @@ -2441,8 +2469,7 @@ TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) { void foo(A); )", Lang_CXX11); - // FIXME: These should not match, - EXPECT_TRUE(testStructuralMatch(t)); + EXPECT_FALSE(testStructuralMatch(t)); } TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) { @@ -2595,5 +2622,31 @@ TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceCacheTest, CXXDependentScopeMemberExprNoEq) { + auto S = makeStmts( + R"( + template + void foo() { +(void)T().x; + } + struct A { int x; }; + void bar() { +foo(); + } + )", + R"( + template + void foo() { +(void)T().y; + } + struct A { int y; }; + void bar() { +foo(); + } + )", + Lang_CXX11, cxxDependentScopeMemberExpr()); + EXPECT_FALSE(testStructuralMatch(S)); +} + } // end namespace ast_matchers } // end namespace clang ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [StructuralEquivalence] improve NTTP and CXXDependentScopeMemberExpr comparison (PR #95190)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/95190 >From 157f664408062da41f4d82d20ddc06e0e563fe31 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Wed, 12 Jun 2024 09:47:16 +0800 Subject: [PATCH] [StructuralEquivalence] improve NTTP and CXXDependentScopeMemberExpr comparison --- clang/lib/AST/ASTStructuralEquivalence.cpp| 14 +- .../AST/StructuralEquivalenceTest.cpp | 49 ++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index d56bf21b459e0..37555c324282f 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -348,6 +348,15 @@ class StmtComparer { return true; } + bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1, +const CXXDependentScopeMemberExpr *E2) { +if (!IsStructurallyEquivalent(Context, E1->getMember(), E2->getMember())) { + return false; +} +return IsStructurallyEquivalent(Context, E1->getBaseType(), +E2->getBaseType()); + } + bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1, const UnaryExprOrTypeTraitExpr *E2) { if (E1->getKind() != E2->getKind()) @@ -1997,7 +2006,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } return false; } - + if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth()) +return false; + if (D1->getIndex() != D2->getIndex()) +return false; // Check types. if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) { if (Context.Complain) { diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 91dd717d7b25e..cea1ce87a7eb9 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -1877,6 +1877,34 @@ TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) { EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second)); } +TEST_F(StructuralEquivalenceCacheTest, + NonTypeTemplateParmWithDifferentPositionNoEq) { + auto TU = makeTuDecls( + R"( + template + struct A { +template +void foo() {} + }; + )", + R"( + template + struct A { +template +void foo() {} + }; + )", + Lang_CXX03); + + StructuralEquivalenceContext Ctx( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); + + auto NTTP = findDeclPair( + TU, nonTypeTemplateParmDecl(hasName("T"))); + EXPECT_FALSE(Ctx.IsEquivalent(NTTP.first, NTTP.second)); +} + TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) { auto TU = makeTuDecls( R"( @@ -2441,8 +2469,7 @@ TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) { void foo(A); )", Lang_CXX11); - // FIXME: These should not match, - EXPECT_TRUE(testStructuralMatch(t)); + EXPECT_FALSE(testStructuralMatch(t)); } TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) { @@ -2595,5 +2622,23 @@ TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceCacheTest, CXXDependentScopeMemberExprNoEq) { + auto S = makeStmts( + R"( + template + void foo() { +T().x; + } + )", + R"( + template + void foo() { +T().y; + } + )", + Lang_CXX11, cxxDependentScopeMemberExpr()); + EXPECT_FALSE(testStructuralMatch(S)); +} + } // end namespace ast_matchers } // end namespace clang ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [StructuralEquivalence] improve NTTP and CXXDependentScopeMemberExpr comparison (PR #95190)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/95190 improve `ASTStructuralEquivalenceTest`: 1. compare the depth and index of NTTP 2. provide comparison of `CXXDependentScopeMemberExpr` to `StmtCompare`. >From 644c6e8499285e5b3ab17193ec63eed051dae583 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Wed, 12 Jun 2024 09:47:16 +0800 Subject: [PATCH] [StructuralEquivalence] improve NTTP and CXXDependentScopeMemberExpr comparison --- clang/lib/AST/ASTStructuralEquivalence.cpp| 14 - .../AST/StructuralEquivalenceTest.cpp | 52 ++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index d56bf21b459e0..37555c324282f 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -348,6 +348,15 @@ class StmtComparer { return true; } + bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1, +const CXXDependentScopeMemberExpr *E2) { +if (!IsStructurallyEquivalent(Context, E1->getMember(), E2->getMember())) { + return false; +} +return IsStructurallyEquivalent(Context, E1->getBaseType(), +E2->getBaseType()); + } + bool IsStmtEquivalent(const UnaryExprOrTypeTraitExpr *E1, const UnaryExprOrTypeTraitExpr *E2) { if (E1->getKind() != E2->getKind()) @@ -1997,7 +2006,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } return false; } - + if (!Context.IgnoreTemplateParmDepth && D1->getDepth() != D2->getDepth()) +return false; + if (D1->getIndex() != D2->getIndex()) +return false; // Check types. if (!IsStructurallyEquivalent(Context, D1->getType(), D2->getType())) { if (Context.Complain) { diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 91dd717d7b25e..55b2580bfce3b 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -1877,6 +1877,34 @@ TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) { EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second)); } +TEST_F(StructuralEquivalenceCacheTest, + NonTypeTemplateParmWithDifferentPositionNoEq) { + auto TU = makeTuDecls( + R"( + template + struct A { +template +void foo() {} + }; + )", + R"( + template + struct A { +template +void foo() {} + }; + )", + Lang_CXX03); + + StructuralEquivalenceContext Ctx( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false); + + auto NTTP = findDeclPair( + TU, nonTypeTemplateParmDecl(hasName("T"))); + EXPECT_FALSE(Ctx.IsEquivalent(NTTP.first, NTTP.second)); +} + TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) { auto TU = makeTuDecls( R"( @@ -2441,8 +2469,7 @@ TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) { void foo(A); )", Lang_CXX11); - // FIXME: These should not match, - EXPECT_TRUE(testStructuralMatch(t)); + EXPECT_FALSE(testStructuralMatch(t)); } TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) { @@ -2595,5 +2622,26 @@ TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) { EXPECT_FALSE(testStructuralMatch(t)); } +const internal::VariadicDynCastAllOfMatcher +cxxDependentScopeMemberExpr; + +TEST_F(StructuralEquivalenceCacheTest, CXXDependentScopeMemberExprNoEq) { + auto S = makeStmts( + R"( + template + void foo() { +T().x; + } + )", + R"( + template + void foo() { +T().y; + } + )", + Lang_CXX11, cxxDependentScopeMemberExpr()); + EXPECT_FALSE(testStructuralMatch(S)); +} + } // end namespace ast_matchers } // end namespace clang ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] SourceLocIdentKind::Function should not be dependent (PR #94942)
jcsxky wrote: > because we want to make the name of the function and any template parameter refers to the instantiated function rather than that of the function template. Does that mean we should transform the `SourceLocExpr` into a certain function name when instantiating if it is `__builtin_FUNCTION`? https://github.com/llvm/llvm-project/pull/94942 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] SourceLocIdentKind::Function should not be dependent (PR #94942)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/94942 Consider the testcase, return type of `construct_at` is ```cpp DecltypeType 0x5570d8c0 'decltype(new struct BasicPersistent(declval()))' sugar dependent |-CXXNewExpr 0x5570d880 'struct BasicPersistent *' Function 0x5570ace0 'operator new' 'void *(unsigned long)' | `-CXXConstructExpr 0x5570d848 'struct BasicPersistent' 'void (BasicPersistent &&, SourceLocation)' | |-CallExpr 0x5570aae8 'BasicPersistent':'struct BasicPersistent' xvalue | | `-ImplicitCastExpr 0x5570aad0 'auto (*)(void) -> decltype(__declval(0))' | | `-DeclRefExpr 0x5570aa18 'auto (void) -> decltype(__declval(0))' lvalue Function 0x5570a908 'declval' 'auto (void) -> decltype(__declval(0))' (FunctionTemplate 0x556d0548 'declval') non_odr_use_unevaluated | `-CXXDefaultArgExpr 0x5570d820 'SourceLocation':'struct SourceLocation' has rewritten init | `-CallExpr 0x5570d7b0 'SourceLocation':'struct SourceLocation' | |-ImplicitCastExpr 0x5570d798 'SourceLocation (*)(const char *)' | | `-DeclRefExpr 0x556fe5c8 'SourceLocation (const char *)' lvalue CXXMethod 0x556fdb28 'Current' 'SourceLocation (const char *)' | | `-NestedNameSpecifier TypeSpec 'struct SourceLocation' | `-CXXDefaultArgExpr 0x5570d7f8 'const char *' has rewritten init | `-SourceLocExpr 0x5570d7d8 'const char *' `-PointerType 0x55704800 'struct BasicPersistent *' `-SubstTemplateTypeParmType 0x557047d0 'struct BasicPersistent' sugar typename depth 0 index 0 _Tp |-FunctionTemplate 0x556ee048 'construct_at' `-RecordType 0x556cfd10 'struct BasicPersistent' `-CXXRecord 0x556fdc98 'BasicPersistent' ``` when in the process of instantiation. This type is dependent due to the dependency of `SourceLocExpr` which leads to the crash(only crash in codegen stage and `clang-check -ast-dump` is OK). `SourceLocExpr` is created in a dependent context when transforming the return type of `construct_at` because its context(`Sema.CurContext`) is a dependent `FunctionDecl`. But `SourceLocExpr` should not be dependent when we finish the transformation. Removing `SourceLocIdentKind::Function` makes `SourceLocExpr` independent. attempt to fix https://github.com/llvm/llvm-project/issues/80210 >From 8ad1b50f267b24693189e3a401d5970308a09f83 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Mon, 10 Jun 2024 16:53:54 +0800 Subject: [PATCH] [clang] SourceLocIdentKind::Function should not be dependent --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/AST/Expr.h| 1 - clang/test/CodeGenCXX/PR80210.cpp | 34 +++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenCXX/PR80210.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cf1ba02cbc4b2..efe78139de6fa 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -846,6 +846,7 @@ Bug Fixes to C++ Support - Fix a crash caused by improper use of ``__array_extent``. (#GH80474) - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). +- Fix a crash when SourceLocExpr instantiated in a dependent context. (GH80210). Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index f2bf667636dc9..92bd7940bdba9 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -4786,7 +4786,6 @@ class SourceLocExpr final : public Expr { static bool MayBeDependent(SourceLocIdentKind Kind) { switch (Kind) { -case SourceLocIdentKind::Function: case SourceLocIdentKind::FuncSig: case SourceLocIdentKind::SourceLocStruct: return true; diff --git a/clang/test/CodeGenCXX/PR80210.cpp b/clang/test/CodeGenCXX/PR80210.cpp new file mode 100644 index 0..fdd3beb99209e --- /dev/null +++ b/clang/test/CodeGenCXX/PR80210.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o /dev/null -verify -triple %itanium_abi_triple +// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o /dev/null -verify -triple %ms_abi_triple + +// expected-no-diagnostics + +struct BasicPersistent; +template BasicPersistent &&__declval(int); +template auto declval() -> decltype(__declval<_Tp>(0)); +template _Tp forward; +template +auto construct_at(_Tp *, _Args...) -> decltype(new _Tp(declval<_Args>()...)) {return 0;} +template struct allocator; +template struct allocator_traits; +template struct allocator_traits> { + using pointer = _Tp *; + template + static void construct(_Up __p, _Args...) { +construct_at(__p, forward<_Args>...); + } +}; +struct __alloc_traits : allocator_traits> { +} push_back___x; +__alloc_traits::pointer _M_impl_0; +template void emplace_back(_
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky ready_for_review https://github.com/llvm/llvm-project/pull/94725 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
jcsxky wrote: crash on trunk assertion. https://github.com/llvm/llvm-project/pull/94725 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky edited https://github.com/llvm/llvm-project/pull/94725 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From a1754c56a3293cd6529244f9a0f7486f4912e18d Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h| 18 + .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- .../PR12884_original_no_crash.cpp | 20 +++ clang/test/SemaTemplate/PR91677.cpp | 14 + clang/test/SemaTemplate/instantiate-scope.cpp | 8 .../SemaTemplate/typename-specifier-3.cpp | 7 --- 7 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 clang/test/SemaTemplate/PR12884_original_no_crash.cpp create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b9c9070fcb22f..e775bd6494fc0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -846,6 +846,7 @@ Bug Fixes to C++ Support - Fix a crash caused by improper use of ``__array_extent``. (#GH80474) - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). +- Clang now transforms qualifier of template name. (#91677). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3bfda09d5f80f..2fea4d9947870 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,24 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (getDerived().AlwaysRebuild() || + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, SourceLocation(), *Template->getIdentifier(), NameLoc, +ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b5d954986dd4f 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::B::C::D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR12884_original_no_crash.cpp b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp new file mode 100644 index 0..f2b6f6e28c2f9 --- /dev/null +++ b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +namespace PR12884_original { + template struct A { +struct B { + template struct X {}; + typedef int arg; +}; +struct C { + typedef B::X x; // expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A::B'}} +}; + }; + + template <> struct A::B { +template struct X {}; +static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}} + }; + + A::C::x a; // expected-note{{in instantiation of member class 'PR12884_original::A::C' requested here}} +} diff --git a/clang/test/SemaTemplate/P
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 2977f65d503c2a96247705ce50157870aaefa003 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/TreeTransform.h| 18 + .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- .../PR12884_original_no_crash.cpp | 20 +++ clang/test/SemaTemplate/PR91677.cpp | 14 + clang/test/SemaTemplate/instantiate-scope.cpp | 8 .../SemaTemplate/typename-specifier-3.cpp | 7 --- 7 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 clang/test/SemaTemplate/PR12884_original_no_crash.cpp create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b9c9070fcb22f..e775bd6494fc0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -846,6 +846,7 @@ Bug Fixes to C++ Support - Fix a crash caused by improper use of ``__array_extent``. (#GH80474) - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). +- Clang now transforms qualifier of template name. (#91677). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3bfda09d5f80f..2fea4d9947870 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,24 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (getDerived().AlwaysRebuild() || + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, SourceLocation(), *Template->getIdentifier(), NameLoc, +ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b5d954986dd4f 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::B::C::D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR12884_original_no_crash.cpp b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp new file mode 100644 index 0..cfc3fc06bd4cf --- /dev/null +++ b/clang/test/SemaTemplate/PR12884_original_no_crash.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +namespace PR12884_original { + template struct A { +struct B { + template struct X {}; + typedef int arg; +}; +struct C { + typedef B::X x; // expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A::B'}} +}; + }; + + template <> struct A::B { +template struct X {}; +static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}} + }; + + A::C::x a; // expected-note{{in instantiation of member class 'PR12884_original::A::C' requested here}} +} \ No newline at end of file diff --git
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 57576620fc412015bd19a34e12be61f4b81eb655 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/lib/Sema/TreeTransform.h | 18 ++ .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- clang/test/SemaTemplate/PR91677.cpp| 14 ++ clang/test/SemaTemplate/instantiate-scope.cpp | 8 .../test/SemaTemplate/typename-specifier-3.cpp | 7 --- 5 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3bfda09d5f80f..b4d31cbbf0c7c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,24 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (!getDerived().AlwaysRebuild() && + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, SourceLocation(), *Template->getIdentifier(), NameLoc, +ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b5d954986dd4f 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::B::C::D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR91677.cpp b/clang/test/SemaTemplate/PR91677.cpp new file mode 100644 index 0..cc8db60a438ea --- /dev/null +++ b/clang/test/SemaTemplate/PR91677.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s +// expected-no-diagnostics + +template struct t1 { + template + struct t2 {}; +}; + +template +t1::template t2 f1(); + +void f2() { + f1(); +} diff --git a/clang/test/SemaTemplate/instantiate-scope.cpp b/clang/test/SemaTemplate/instantiate-scope.cpp index 733105674b7a4..3a1708a695ceb 100644 --- a/clang/test/SemaTemplate/instantiate-scope.cpp +++ b/clang/test/SemaTemplate/instantiate-scope.cpp @@ -11,10 +11,10 @@ template using A = T; // These definitions are OK, X...> is equivalent to X // so this defines the member of the primary template. template -void X...>::f(int) {} // expected-error {{undeclared}} +void X...>::f(int) {} // expected-error {{use of undeclared identifier 'f'}} template -int X...>::n = 0; // expected-error {{undeclared}} +int X...>::n = 0; // expected-error {{use of undeclared identifier 'f'}} struct Y {}; void f(Y); @@ -25,6 +25,6 @@ void g() { // Error, substitution fails; this should not be treated as a SFINAE-able // condition, so we don't select X::f(...). - X().f(0); // expected-note {{instantiation of}} - X::n = 1; // expected-note {{instantiation of}} + X().f(0); // expected-note {{in instantiation of member function 'X::f' requested here}} + X::n = 1; // expected-note {{in instantiation of static data member 'X::n' requested here}} } diff --git a/clang/test/SemaTemplate/typename-specifier-3.cpp b/clang/test/SemaTemplate/typename-specifi
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 6a90ef0b3947a0de2d6453856c80d8f0fd393548 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/lib/Sema/TreeTransform.h | 18 ++ .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- clang/test/SemaTemplate/PR91677.cpp| 14 ++ clang/test/SemaTemplate/instantiate-scope.cpp | 11 ++- .../test/SemaTemplate/typename-specifier-3.cpp | 7 --- 5 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3bfda09d5f80f..b4d31cbbf0c7c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,24 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (!getDerived().AlwaysRebuild() && + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, SourceLocation(), *Template->getIdentifier(), NameLoc, +ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b5d954986dd4f 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::B::C::D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR91677.cpp b/clang/test/SemaTemplate/PR91677.cpp new file mode 100644 index 0..cc8db60a438ea --- /dev/null +++ b/clang/test/SemaTemplate/PR91677.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s +// expected-no-diagnostics + +template struct t1 { + template + struct t2 {}; +}; + +template +t1::template t2 f1(); + +void f2() { + f1(); +} diff --git a/clang/test/SemaTemplate/instantiate-scope.cpp b/clang/test/SemaTemplate/instantiate-scope.cpp index 733105674b7a4..a8f02acd23fab 100644 --- a/clang/test/SemaTemplate/instantiate-scope.cpp +++ b/clang/test/SemaTemplate/instantiate-scope.cpp @@ -2,7 +2,8 @@ template struct X { void f(int); - void f(...); + void f(...); // expected-note {{member is declared here}} \ + expected-note {{member is declared here}} static int n; }; @@ -11,10 +12,10 @@ template using A = T; // These definitions are OK, X...> is equivalent to X // so this defines the member of the primary template. template -void X...>::f(int) {} // expected-error {{undeclared}} +void X...>::f(int) {} // expected-error {{use of undeclared identifier 'f'}} template -int X...>::n = 0; // expected-error {{undeclared}} +int X...>::n = 0; // expected-error {{use of undeclared identifier 'f'}} struct Y {}; void f(Y); @@ -25,6 +26,6 @@ void g() { // Error, substitution fails; this should not be treated as a SFINAE-able // condition, so we don't select X::f(...). - X().f(0); // expected-note {{instantiation of}} - X::n = 1; // expected-note {{instantiation of}} + X().f(0); // expected-note {{in instantiation of member function 'X::f'
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/94725 >From 917cd980ed6a130b9f175492638afa22a1246c5c Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 7 +++ clang/lib/Sema/TreeTransform.h | 18 ++ .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- clang/test/SemaTemplate/PR91677.cpp| 14 ++ clang/test/SemaTemplate/instantiate-scope.cpp | 15 --- .../test/SemaTemplate/typename-specifier-3.cpp | 7 --- 6 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 0681520764d9a..d30a9c2a2588f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -60,10 +60,9 @@ static bool SubstQualifier(Sema &SemaRef, const DeclT *OldDecl, DeclT *NewDecl, !OldDecl->getLexicalDeclContext()->isDependentContext()) && "non-friend with qualified name defined in dependent context"); Sema::ContextRAII SavedContext( - SemaRef, - const_cast(NewDecl->getFriendObjectKind() -? NewDecl->getLexicalDeclContext() -: OldDecl->getLexicalDeclContext())); + SemaRef, const_cast(NewDecl->getFriendObjectKind() + ? NewDecl->getLexicalDeclContext() + : NewDecl->getDeclContext())); NestedNameSpecifierLoc NewQualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3bfda09d5f80f..b4d31cbbf0c7c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,24 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (!getDerived().AlwaysRebuild() && + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, SourceLocation(), *Template->getIdentifier(), NameLoc, +ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b5d954986dd4f 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::B::C::D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR91677.cpp b/clang/test/SemaTemplate/PR91677.cpp new file mode 100644 index 0..cc8db60a438ea --- /dev/null +++ b/clang/test/SemaTemplate/PR91677.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s +// expected-no-diagnostics + +template struct t1 { + template + struct t2 {}; +}; + +template +t1::template t2 f1(); + +void f2() { + f1(); +} diff --git a/clang/test/SemaTemplate/instantiate-scope.cpp b/clang/test/SemaTemplate/instantiate-scope.cpp index 733105674
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky converted_to_draft https://github.com/llvm/llvm-project/pull/94725 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] qualifier should be transformed (PR #94725)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/94725 None >From 9fc6172cb3ef627eb7d4e939dff6f4504c06150a Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 7 Jun 2024 14:04:52 +0800 Subject: [PATCH] [Clang][Sema] qualifier should be transformed --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 7 +++ clang/lib/Sema/TreeTransform.h | 18 ++ .../SemaCXX/many-template-parameter-lists.cpp | 6 +++--- clang/test/SemaTemplate/PR91677.cpp| 14 ++ clang/test/SemaTemplate/instantiate-scope.cpp | 15 --- .../test/SemaTemplate/typename-specifier-3.cpp | 7 --- 6 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 clang/test/SemaTemplate/PR91677.cpp diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 0681520764d9a..d30a9c2a2588f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -60,10 +60,9 @@ static bool SubstQualifier(Sema &SemaRef, const DeclT *OldDecl, DeclT *NewDecl, !OldDecl->getLexicalDeclContext()->isDependentContext()) && "non-friend with qualified name defined in dependent context"); Sema::ContextRAII SavedContext( - SemaRef, - const_cast(NewDecl->getFriendObjectKind() -? NewDecl->getLexicalDeclContext() -: OldDecl->getLexicalDeclContext())); + SemaRef, const_cast(NewDecl->getFriendObjectKind() + ? NewDecl->getLexicalDeclContext() + : NewDecl->getDeclContext())); NestedNameSpecifierLoc NewQualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3bfda09d5f80f..b4d31cbbf0c7c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4568,6 +4568,24 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); +if (QTN->getQualifier()) { + CXXScopeSpec QualifierSS; + QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(), + NameLoc); + NestedNameSpecifierLoc QualifierLoc = + QualifierSS.getWithLocInContext(getSema().getASTContext()); + NestedNameSpecifierLoc TransformedQualifierLoc = + getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!TransformedQualifierLoc) +return Name; + if (!getDerived().AlwaysRebuild() && + QualifierLoc != TransformedQualifierLoc) { +SS.Adopt(TransformedQualifierLoc); +return getDerived().RebuildTemplateName( +SS, SourceLocation(), *Template->getIdentifier(), NameLoc, +ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true); + } +} TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, diff --git a/clang/test/SemaCXX/many-template-parameter-lists.cpp b/clang/test/SemaCXX/many-template-parameter-lists.cpp index f98005c7e6fb5..b5d954986dd4f 100644 --- a/clang/test/SemaCXX/many-template-parameter-lists.cpp +++ b/clang/test/SemaCXX/many-template-parameter-lists.cpp @@ -5,7 +5,7 @@ template struct X { template - struct A { // expected-note {{not-yet-instantiated member is declared here}} + struct A { template struct B { template @@ -28,9 +28,9 @@ struct X { template template template - friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X'; it has not yet been instantiated}} + friend void A::template B::template C::template D::template E::operator+=(Z); // expected-warning {{dependent nested name specifier 'A::B::C::D::template E::' for friend class declaration is not supported; turning off access control for 'X'}} }; void test() { - X::A::B::C::D::E() += 1.0; // expected-note {{in instantiation of template class 'X' requested here}} + X::A::B::C::D::E() += 1.0; } diff --git a/clang/test/SemaTemplate/PR91677.cpp b/clang/test/SemaTemplate/PR91677.cpp new file mode 100644 index 0..cc8db60a438ea --- /dev/null +++ b/clang/test/SemaTemplate/PR91677.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s +// expected-no-diagnostics + +template struct t1 { + template + struct t2 {}; +}; + +template +t1::template t2 f1(); + +void f2() { + f1(); +} diff --git a/clang/test/SemaTemplate/instantiate-scope.cpp b/clang/test/SemaTemplate/instantiate-scope.cpp index 733
[clang] [clang][ASTImport] fix issue on anonymous enum import (PR #93923)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/93923 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [Clang] Implement resolution for CWG1835 (PR #92957)
@@ -1442,19 +1442,27 @@ SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const { CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, -SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, +SourceLocation TemplateKWLoc, ArrayRef UnqualifiedLookups, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) : Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue, OK_Ordinary), - Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc), + Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc), jcsxky wrote: There is a warning here. `field 'OperatorLoc' will be initialized after field 'MemberNameInfo'` https://github.com/llvm/llvm-project/pull/92957 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImport] fix issue on anonymous enum import (PR #93923)
@@ -9674,6 +9674,40 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) { EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember()); } +AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) { + for (EnumConstantDecl *D : Node.enumerators()) +if (D->getName() == ConstName) + return true; + return false; +} + +TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) { + const char *ToCode = + R"( + struct A { +enum { E1, E2} x; +enum { E3, E4} y; + }; + )"; + Decl *ToTu = getToTuDecl(ToCode, Lang_CXX11); + auto *ToE = FirstDeclMatcher().match( + ToTu, enumDecl(hasEnumConstName("E1"))); jcsxky wrote: Import test on the other enum has been added to make this test completely. https://github.com/llvm/llvm-project/pull/93923 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImport] fix issue on anonymous enum import (PR #93923)
@@ -9674,6 +9674,40 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) { EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember()); } +AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) { + for (EnumConstantDecl *D : Node.enumerators()) +if (D->getName() == ConstName) + return true; + return false; +} + +TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) { + const char *ToCode = + R"( + struct A { +enum { E1, E2} x; +enum { E3, E4} y; + }; + )"; + Decl *ToTu = getToTuDecl(ToCode, Lang_CXX11); + auto *ToE = FirstDeclMatcher().match( + ToTu, enumDecl(hasEnumConstName("E1"))); + const char *Code = + R"( + struct A { +enum { E1, E2} x; +enum { E3, E4} y; + }; + )"; + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + auto *FromE = FirstDeclMatcher().match( + FromTU, enumDecl(hasEnumConstName("E1"))); + auto *ImportedE = Import(FromE, Lang_CXX11); + ASSERT_TRUE(ImportedE); + EXPECT_EQ(ImportedE, ToE); + EXPECT_FALSE(ImportedE->enumerators().empty()); jcsxky wrote: Updated. https://github.com/llvm/llvm-project/pull/93923 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImport] fix issue on anonymous enum import (PR #93923)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/93923 >From 7e602ae8d3c7ca0c3218d8ce9106510c43b6295b Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 31 May 2024 13:12:41 +0800 Subject: [PATCH 1/2] [clang][ASTImport] fix issue on anonymous enum import --- clang/lib/AST/ASTImporter.cpp | 2 +- clang/unittests/AST/ASTImporterTest.cpp | 21 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index cab5ee6047956..3b9080e09b331 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2929,7 +2929,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // We may already have an enum of the same name; try to find and match it. EnumDecl *PrevDecl = nullptr; - if (!DC->isFunctionOrMethod() && SearchName) { + if (!DC->isFunctionOrMethod()) { SmallVector ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, SearchName); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 3dc1c336365d1..4cee0b75653a5 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -9674,6 +9674,27 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) { EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember()); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) { + const char *ToCode = + R"( + struct A { +enum { E1,E2} x; + }; + )"; + (void)getToTuDecl(ToCode, Lang_CXX11); + const char *Code = + R"( + struct A { +enum { E1,E2} x; + }; + )"; + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + auto *FromE = FirstDeclMatcher().match(FromTU, enumDecl()); + auto *ToE = Import(FromE, Lang_CXX11); + ASSERT_TRUE(ToE); + EXPECT_FALSE(ToE->enumerators().empty()); +} + INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions); >From d8c1d25b026c0377bd5d84644fb13cd072f9694c Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Sat, 1 Jun 2024 00:52:01 +0800 Subject: [PATCH 2/2] update testcase --- clang/unittests/AST/ASTImporterTest.cpp | 33 +++-- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 4cee0b75653a5..92f9bae6cb064 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -9674,25 +9674,44 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) { EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember()); } +AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) { + for (EnumConstantDecl *D : Node.enumerators()) +if (D->getName() == ConstName) + return true; + return false; +} + TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) { const char *ToCode = R"( struct A { -enum { E1,E2} x; +enum { E1, E2} x; +enum { E3, E4} y; }; )"; - (void)getToTuDecl(ToCode, Lang_CXX11); + Decl *ToTU = getToTuDecl(ToCode, Lang_CXX11); + auto *ToE1 = FirstDeclMatcher().match( + ToTU, enumDecl(hasEnumConstName("E1"))); + auto *ToE3 = FirstDeclMatcher().match( + ToTU, enumDecl(hasEnumConstName("E3"))); const char *Code = R"( struct A { -enum { E1,E2} x; +enum { E1, E2} x; +enum { E3, E4} y; }; )"; Decl *FromTU = getTuDecl(Code, Lang_CXX11); - auto *FromE = FirstDeclMatcher().match(FromTU, enumDecl()); - auto *ToE = Import(FromE, Lang_CXX11); - ASSERT_TRUE(ToE); - EXPECT_FALSE(ToE->enumerators().empty()); + auto *FromE1 = FirstDeclMatcher().match( + FromTU, enumDecl(hasEnumConstName("E1"))); + auto *ImportedE1 = Import(FromE1, Lang_CXX11); + ASSERT_TRUE(ImportedE1); + EXPECT_EQ(ImportedE1, ToE1); + auto *FromE3 = FirstDeclMatcher().match( + FromTU, enumDecl(hasEnumConstName("E3"))); + auto *ImportedE3 = Import(FromE3, Lang_CXX11); + ASSERT_TRUE(ImportedE3); + EXPECT_EQ(ImportedE3, ToE3); } INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImport] fix issue on anonymous enum import (PR #93923)
@@ -9674,6 +9674,27 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) { EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember()); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) { + const char *ToCode = + R"( + struct A { +enum { E1,E2} x; + }; + )"; + (void)getToTuDecl(ToCode, Lang_CXX11); + const char *Code = + R"( + struct A { +enum { E1,E2} x; + }; + )"; + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + auto *FromE = FirstDeclMatcher().match(FromTU, enumDecl()); + auto *ToE = Import(FromE, Lang_CXX11); + ASSERT_TRUE(ToE); + EXPECT_FALSE(ToE->enumerators().empty()); jcsxky wrote: Done. https://github.com/llvm/llvm-project/pull/93923 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImport] fix issue on anonymous enum import (PR #93923)
jcsxky wrote: > Does this work on the following code? > > ``` > struct A { > enum { E1,E2 } x; > enum { E3,E4 } y; > }; > ``` I have updated testcase according to your suggestion to demonstrate this solution works correctly on the testcase above. https://github.com/llvm/llvm-project/pull/93923 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImport] fix issue on anonymous enum import (PR #93923)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/93923 >From 7e602ae8d3c7ca0c3218d8ce9106510c43b6295b Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 31 May 2024 13:12:41 +0800 Subject: [PATCH 1/2] [clang][ASTImport] fix issue on anonymous enum import --- clang/lib/AST/ASTImporter.cpp | 2 +- clang/unittests/AST/ASTImporterTest.cpp | 21 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index cab5ee6047956..3b9080e09b331 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2929,7 +2929,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // We may already have an enum of the same name; try to find and match it. EnumDecl *PrevDecl = nullptr; - if (!DC->isFunctionOrMethod() && SearchName) { + if (!DC->isFunctionOrMethod()) { SmallVector ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, SearchName); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 3dc1c336365d1..4cee0b75653a5 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -9674,6 +9674,27 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) { EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember()); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) { + const char *ToCode = + R"( + struct A { +enum { E1,E2} x; + }; + )"; + (void)getToTuDecl(ToCode, Lang_CXX11); + const char *Code = + R"( + struct A { +enum { E1,E2} x; + }; + )"; + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + auto *FromE = FirstDeclMatcher().match(FromTU, enumDecl()); + auto *ToE = Import(FromE, Lang_CXX11); + ASSERT_TRUE(ToE); + EXPECT_FALSE(ToE->enumerators().empty()); +} + INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions); >From a32f4f879ef4e080b192ad6a4ee1528591ce2136 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Sat, 1 Jun 2024 00:52:01 +0800 Subject: [PATCH 2/2] update testcase --- clang/unittests/AST/ASTImporterTest.cpp | 27 ++--- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 4cee0b75653a5..dcf30d7ec1a6f 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -9674,25 +9674,38 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) { EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember()); } +AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) { + for (EnumConstantDecl *D : Node.enumerators()) +if (D->getName() == ConstName) + return true; + return false; +} + TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) { const char *ToCode = R"( struct A { -enum { E1,E2} x; +enum { E1, E2} x; +enum { E3, E4} y; }; )"; - (void)getToTuDecl(ToCode, Lang_CXX11); + Decl *ToTu = getToTuDecl(ToCode, Lang_CXX11); + auto *ToE = FirstDeclMatcher().match( + ToTu, enumDecl(hasEnumConstName("E1"))); const char *Code = R"( struct A { -enum { E1,E2} x; +enum { E1, E2} x; +enum { E3, E4} y; }; )"; Decl *FromTU = getTuDecl(Code, Lang_CXX11); - auto *FromE = FirstDeclMatcher().match(FromTU, enumDecl()); - auto *ToE = Import(FromE, Lang_CXX11); - ASSERT_TRUE(ToE); - EXPECT_FALSE(ToE->enumerators().empty()); + auto *FromE = FirstDeclMatcher().match( + FromTU, enumDecl(hasEnumConstName("E1"))); + auto *ImportedE = Import(FromE, Lang_CXX11); + ASSERT_TRUE(ImportedE); + EXPECT_EQ(ImportedE, ToE); + EXPECT_FALSE(ImportedE->enumerators().empty()); } INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImport] fix issue on anonymous enum import (PR #93923)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/93923 Don't skip searching in `ToContext` during importing `EnumDecl`. And `IsStructuralMatch` in `StructralEquivalence` can make sure to determine whether the found result is match or not. >From 7e602ae8d3c7ca0c3218d8ce9106510c43b6295b Mon Sep 17 00:00:00 2001 From: huqizhi Date: Fri, 31 May 2024 13:12:41 +0800 Subject: [PATCH] [clang][ASTImport] fix issue on anonymous enum import --- clang/lib/AST/ASTImporter.cpp | 2 +- clang/unittests/AST/ASTImporterTest.cpp | 21 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index cab5ee6047956..3b9080e09b331 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2929,7 +2929,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // We may already have an enum of the same name; try to find and match it. EnumDecl *PrevDecl = nullptr; - if (!DC->isFunctionOrMethod() && SearchName) { + if (!DC->isFunctionOrMethod()) { SmallVector ConflictingDecls; auto FoundDecls = Importer.findDeclsInToCtx(DC, SearchName); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 3dc1c336365d1..4cee0b75653a5 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -9674,6 +9674,27 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) { EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember()); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnum) { + const char *ToCode = + R"( + struct A { +enum { E1,E2} x; + }; + )"; + (void)getToTuDecl(ToCode, Lang_CXX11); + const char *Code = + R"( + struct A { +enum { E1,E2} x; + }; + )"; + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + auto *FromE = FirstDeclMatcher().match(FromTU, enumDecl()); + auto *ToE = Import(FromE, Lang_CXX11); + ASSERT_TRUE(ToE); + EXPECT_FALSE(ToE->enumerators().empty()); +} + INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType (PR #93411)
jcsxky wrote: > So After we have formed a TemplateSpecializationType, we are done with the > NNS. We keep it around in an ElaboratedType for type sugar only, it should > not be needed to compile the program correctly anymore. > > So I think this solution violates one important aspect of our AST design. > > If we still need the NNS, we have to hold-off on building the TST until we > don't. Ah, I see. Thanks for your explanation on the motivation of AST design! https://github.com/llvm/llvm-project/pull/93411 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [clang] Preserve Qualifiers and type sugar in TemplateNames (PR #93433)
jcsxky wrote: @mizvekov After I apply you changes in this patch, https://github.com/llvm/llvm-project/issues/91677 is still crash(although it makes sense with `-ast-dump` option). I put it below for explanation clearly: ```cpp template struct t1 { template struct t2 {}; }; template t1::template t2 f1(); void f2() { f1(); } ``` The reason seems that we transform `TemplateDecl` to the original one and do nothing and then crash in codegen stage. For `t1::t2`, we have transformed qualifier(`t1`) in `TransformElaboratedType`. But, we transform qualifier in `TransformTemplateName` for `t2` again because of transforming `TransformTemplateSpecializationType`. This leads to the transformation of the `TemplateDecl` as I described in the beginning. I think we can reuse the transformed qualifier(`t1`) in `TransformElaboratedType` and this is what I did in https://github.com/llvm/llvm-project/pull/93411. Could you please take another look? https://github.com/llvm/llvm-project/pull/93433 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType (PR #93411)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/93411 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType (PR #93411)
jcsxky wrote: > The problem here is the loss of the qualification on the TemplateNames > > This patch fixes the problem, without taking any workarounds: #93433 > > It also doesn't cause any change in diagnostics in > `clang/test/SemaTemplate/typename-specifier-3.cpp`. I think we should report this message since `B::arg` in `A` is a NTTP. https://github.com/llvm/llvm-project/pull/93411 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType (PR #93411)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/93411 >From f5f0b14945a70e3e4fd92d5e5cbdb428334fe2b8 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Sat, 25 May 2024 16:30:27 +0800 Subject: [PATCH 1/2] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType --- clang/lib/Sema/TreeTransform.h | 43 +- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index dee335b526991..7e8b080a347e8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -29,8 +29,10 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" +#include "clang/Sema/DeclSpec.h" #include "clang/Sema/Designator.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Lookup.h" @@ -7216,7 +7218,46 @@ TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, return QualType(); } - QualType NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc()); + QualType NamedT; + if (0 && SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && isa(TL.getNamedTypeLoc().getType())) { +const TemplateSpecializationType *TST = TL.getNamedTypeLoc().getType()->getAs(); +TemplateSpecializationTypeLoc SpecTL = +TL.getNamedTypeLoc().castAs(); +// TemplateArgumentListInfo NewTemplateArgs; +// NewTemplateArgs.setLAngleLoc(SpecTL.getLAngleLoc()); +// NewTemplateArgs.setRAngleLoc(SpecTL.getRAngleLoc()); + +// typedef TemplateArgumentLocContainerIterator< +// TemplateSpecializationTypeLoc> ArgIterator; +// if (getDerived().TransformTemplateArguments(ArgIterator(SpecTL, 0), +// ArgIterator(SpecTL, SpecTL.getNumArgs()), +// NewTemplateArgs)) +// return QualType(); + +CXXScopeSpec SS; +SS.Adopt(QualifierLoc); +TemplateName InstName = getDerived().RebuildTemplateName( +SS, TL.getTemplateKeywordLoc(), *TST->getTemplateName().getAsTemplateDecl()->getIdentifier(), TL.getNamedTypeLoc().getBeginLoc(), QualType(), nullptr, +false); + +if (InstName.isNull()) + return QualType(); + +// If it's still dependent, make a dependent specialization. +// if (InstName.getAsDependentTemplateName()) +// return SemaRef.Context.getDependentTemplateSpecializationType( +// Keyword, QualifierLoc.getNestedNameSpecifier(), Name, +// Args.arguments()); + +// Otherwise, make an elaborated type wrapping a non-dependent +// specialization. +// NamedT = getDerived().RebuildTemplateSpecializationType(InstName, TL.getNamedTypeLoc().getBeginLoc(), NewTemplateArgs); +NamedT = TransformTemplateSpecializationType(TLB, SpecTL, InstName); + } else { +NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc()); + + } + if (NamedT.isNull()) return QualType(); >From 3ebed0fecd90101b57082909348a60070c689d12 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Sun, 26 May 2024 19:35:17 +0800 Subject: [PATCH 2/2] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType --- clang/lib/Sema/TreeTransform.h| 54 ++- clang/test/SemaCXX/PR91677.cpp| 14 + .../SemaTemplate/typename-specifier-3.cpp | 7 +-- 3 files changed, 35 insertions(+), 40 deletions(-) create mode 100644 clang/test/SemaCXX/PR91677.cpp diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7e8b080a347e8..6ef2eec09ec02 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -29,10 +29,8 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" -#include "clang/AST/TypeLoc.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" -#include "clang/Sema/DeclSpec.h" #include "clang/Sema/Designator.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Lookup.h" @@ -7219,48 +7217,30 @@ TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, } QualType NamedT; - if (0 && SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && isa(TL.getNamedTypeLoc().getType())) { -const TemplateSpecializationType *TST = TL.getNamedTypeLoc().getType()->getAs(); + if (SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && + isa(TL.getNamedTypeLoc().getType())) { TemplateSpecializationTypeLoc SpecTL = TL.getNamedTypeLoc().castAs(); -// TemplateArgumentListInfo NewTemplateArgs; -// NewTemplateArgs.setLAngleLoc(SpecTL.getLAngleLoc()); -// NewTemplateArgs.setRAngleLoc(SpecTL.getRAngleLoc()); - -// typedef Templat
[clang] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType (PR #93411)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/93411 >From f5f0b14945a70e3e4fd92d5e5cbdb428334fe2b8 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Sat, 25 May 2024 16:30:27 +0800 Subject: [PATCH 1/2] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType --- clang/lib/Sema/TreeTransform.h | 43 +- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index dee335b526991..7e8b080a347e8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -29,8 +29,10 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" +#include "clang/Sema/DeclSpec.h" #include "clang/Sema/Designator.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Lookup.h" @@ -7216,7 +7218,46 @@ TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, return QualType(); } - QualType NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc()); + QualType NamedT; + if (0 && SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && isa(TL.getNamedTypeLoc().getType())) { +const TemplateSpecializationType *TST = TL.getNamedTypeLoc().getType()->getAs(); +TemplateSpecializationTypeLoc SpecTL = +TL.getNamedTypeLoc().castAs(); +// TemplateArgumentListInfo NewTemplateArgs; +// NewTemplateArgs.setLAngleLoc(SpecTL.getLAngleLoc()); +// NewTemplateArgs.setRAngleLoc(SpecTL.getRAngleLoc()); + +// typedef TemplateArgumentLocContainerIterator< +// TemplateSpecializationTypeLoc> ArgIterator; +// if (getDerived().TransformTemplateArguments(ArgIterator(SpecTL, 0), +// ArgIterator(SpecTL, SpecTL.getNumArgs()), +// NewTemplateArgs)) +// return QualType(); + +CXXScopeSpec SS; +SS.Adopt(QualifierLoc); +TemplateName InstName = getDerived().RebuildTemplateName( +SS, TL.getTemplateKeywordLoc(), *TST->getTemplateName().getAsTemplateDecl()->getIdentifier(), TL.getNamedTypeLoc().getBeginLoc(), QualType(), nullptr, +false); + +if (InstName.isNull()) + return QualType(); + +// If it's still dependent, make a dependent specialization. +// if (InstName.getAsDependentTemplateName()) +// return SemaRef.Context.getDependentTemplateSpecializationType( +// Keyword, QualifierLoc.getNestedNameSpecifier(), Name, +// Args.arguments()); + +// Otherwise, make an elaborated type wrapping a non-dependent +// specialization. +// NamedT = getDerived().RebuildTemplateSpecializationType(InstName, TL.getNamedTypeLoc().getBeginLoc(), NewTemplateArgs); +NamedT = TransformTemplateSpecializationType(TLB, SpecTL, InstName); + } else { +NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc()); + + } + if (NamedT.isNull()) return QualType(); >From e60cdac25c4ea2e85894e51dfd5268544cadd27d Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Sun, 26 May 2024 19:35:17 +0800 Subject: [PATCH 2/2] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType --- clang/lib/Sema/TreeTransform.h| 54 ++- clang/test/SemaCXX/PR91677.cpp| 31 +++ .../SemaTemplate/typename-specifier-3.cpp | 7 +-- 3 files changed, 52 insertions(+), 40 deletions(-) create mode 100644 clang/test/SemaCXX/PR91677.cpp diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7e8b080a347e8..6ef2eec09ec02 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -29,10 +29,8 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" -#include "clang/AST/TypeLoc.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" -#include "clang/Sema/DeclSpec.h" #include "clang/Sema/Designator.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Lookup.h" @@ -7219,48 +7217,30 @@ TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, } QualType NamedT; - if (0 && SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && isa(TL.getNamedTypeLoc().getType())) { -const TemplateSpecializationType *TST = TL.getNamedTypeLoc().getType()->getAs(); + if (SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && + isa(TL.getNamedTypeLoc().getType())) { TemplateSpecializationTypeLoc SpecTL = TL.getNamedTypeLoc().castAs(); -// TemplateArgumentListInfo NewTemplateArgs; -// NewTemplateArgs.setLAngleLoc(SpecTL.getLAngleLoc()); -// NewTemplateArgs.setRAngleLoc(SpecTL.getRAngleLoc()); - -// typedef T
[clang] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType (PR #93411)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/93411 Consider the following testcase: ```cpp namespace PR12884_original { template struct A { struct B { ##1 template struct X {}; typedef int arg; }; struct C { typedef B::X x; }; }; template <> struct A::B { ##2 template struct X {}; static const int arg = 0; }; A::C::x a; } ``` It will crash when compiling with `clang(assertions trunk)`. The reason is that we lookup `X`(`B::X`) in `##1` when instantiating `typedef B::X x; ` during instantiating `A::C::x`. This is incorrect because we should lookup `X` in `##2` when we see the declaration `A::C::x a;`. Since clang parse `A::B` to an `ElaboratedType`(`typename` is not required while compiling with `-std=c++20`) while `typename A::B` turns to be a `DependentTemplateSpecializationType`, we should rebuild the `TemplateName` with transformed `Qualifier`(whose type is `NestedNameSpecifier`) to make sure the lookup context is correct. This patch also attempts to fix #91677 which crashes with the same reason. >From ee56373184dff3fd721709ca07a1770957eace29 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Sat, 25 May 2024 16:30:27 +0800 Subject: [PATCH 1/2] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType --- clang/lib/Sema/TreeTransform.h | 43 +- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index dee335b526991..7e8b080a347e8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -29,8 +29,10 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" +#include "clang/Sema/DeclSpec.h" #include "clang/Sema/Designator.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Lookup.h" @@ -7216,7 +7218,46 @@ TreeTransform::TransformElaboratedType(TypeLocBuilder &TLB, return QualType(); } - QualType NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc()); + QualType NamedT; + if (0 && SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && isa(TL.getNamedTypeLoc().getType())) { +const TemplateSpecializationType *TST = TL.getNamedTypeLoc().getType()->getAs(); +TemplateSpecializationTypeLoc SpecTL = +TL.getNamedTypeLoc().castAs(); +// TemplateArgumentListInfo NewTemplateArgs; +// NewTemplateArgs.setLAngleLoc(SpecTL.getLAngleLoc()); +// NewTemplateArgs.setRAngleLoc(SpecTL.getRAngleLoc()); + +// typedef TemplateArgumentLocContainerIterator< +// TemplateSpecializationTypeLoc> ArgIterator; +// if (getDerived().TransformTemplateArguments(ArgIterator(SpecTL, 0), +// ArgIterator(SpecTL, SpecTL.getNumArgs()), +// NewTemplateArgs)) +// return QualType(); + +CXXScopeSpec SS; +SS.Adopt(QualifierLoc); +TemplateName InstName = getDerived().RebuildTemplateName( +SS, TL.getTemplateKeywordLoc(), *TST->getTemplateName().getAsTemplateDecl()->getIdentifier(), TL.getNamedTypeLoc().getBeginLoc(), QualType(), nullptr, +false); + +if (InstName.isNull()) + return QualType(); + +// If it's still dependent, make a dependent specialization. +// if (InstName.getAsDependentTemplateName()) +// return SemaRef.Context.getDependentTemplateSpecializationType( +// Keyword, QualifierLoc.getNestedNameSpecifier(), Name, +// Args.arguments()); + +// Otherwise, make an elaborated type wrapping a non-dependent +// specialization. +// NamedT = getDerived().RebuildTemplateSpecializationType(InstName, TL.getNamedTypeLoc().getBeginLoc(), NewTemplateArgs); +NamedT = TransformTemplateSpecializationType(TLB, SpecTL, InstName); + } else { +NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc()); + + } + if (NamedT.isNull()) return QualType(); >From cb29d45c174f4fd267c273c4386a2010941a63ac Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Sun, 26 May 2024 19:35:17 +0800 Subject: [PATCH 2/2] [Clang][Sema] Use correct TemplateName when transforming TemplateSpecializationType --- clang/lib/Sema/TreeTransform.h| 54 ++- clang/test/SemaCXX/PR91677.cpp| 31 +++ .../SemaTemplate/typename-specifier-3.cpp | 7 +-- 3 files changed, 52 insertions(+), 40 deletions(-) create mode 100644 clang/test/SemaCXX/PR91677.cpp diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7e8b080a347e8..6ef2eec09ec02 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -29,10 +29,8 @@ #include "clang/AST/StmtObjC.h
[clang] [clang][ASTImporter] Fix possible crash "given incorrect InsertPos for specialization". (PR #89887)
https://github.com/jcsxky approved this pull request. https://github.com/llvm/llvm-project/pull/89887 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImporter] Fix possible crash "given incorrect InsertPos for specialization". (PR #89887)
jcsxky wrote: > > Could you please show your commands which reproduced this crash? I tested > > locally with the following commands and it runs OK. > > ```c++ > > clang++ -cc1 -std=c++17 -emit-pch -o test.cpp.ast test.cpp > > clang++ -cc1 -x c++ -ast-merge test.cpp.ast /dev/null -ast-dump > > ``` > > That code is only an example, it differs not much of the real code that > caused the crash. But it is not enough to use this code for the problem > reproduction. This code can be used to get the case when the specialization > list is changed before the insertion, but even then no crash happens: > > ```c++ > namespace N { > template > int B = B + B; > template <> > int B<0> = 0; > template <> > int B<1> = 1; > } > int A = N::B<5>; > ``` > > With clang version 18.1.6 the original crash does not occur any more. The > "original crash" was reproduced on specific source files of project > "contour". Probably I can attach the files and command, but some changes can > be required to make it work. Could you please show me how to reproduce the crash in detail if possible? Then I can debug this issue in my spare time. https://github.com/llvm/llvm-project/pull/89887 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImporter] Fix possible crash "given incorrect InsertPos for specialization". (PR #89887)
jcsxky wrote: > A test is needed to make the change acceptable but I could not find an easy > case to provoke the situation. The problem looks to be related to his code: > > ```c++ > using size_t = int; > template class tuple; > > template > struct integral_constant > { > static constexpr T value = v; > using value_type = T; > using type = integral_constant; // using injected-class-name > constexpr operator value_type() const noexcept { return value; } > constexpr value_type operator()() const noexcept { return value; } // > since c++14 > }; > > using true_type = integral_constant; > using false_type = integral_constant; > > template > struct is_same : false_type {}; > > template > struct is_same : true_type {}; > > template< class T, class U > > inline constexpr bool is_same_v = is_same::value; > > namespace A { > template > struct __tuple_count; > > template > inline constexpr size_t __tuple_count_v = > __tuple_count<_Tp, _Tuple>::value; > > template > struct __tuple_count<_Tp, tuple<_Types...>> > : integral_constant { }; > > template > struct __tuple_count<_Tp, tuple<_First, _Rest...>> > : integral_constant< > size_t, > __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { }; > }; > > > size_t x = A::__tuple_count_v>; > ``` Could you please show your commands which reproduced this crash? I tested locally with the following commands and it runs OK. ```cpp clang++ -cc1 -std=c++17 -emit-pch -o test.cpp.ast test.cpp clang++ -cc1 -x c++ -ast-merge test.cpp.ast /dev/null -ast-dump ``` https://github.com/llvm/llvm-project/pull/89887 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AST] fix crash in mangle lambda expression (PR #78896)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/78896 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
jcsxky wrote: > I don't think this is the right approach. I stepped though the example and > the reason we reject is because: > > * We substitute a dependent `AutoType` in for the types of the template > parameters when they are initially built. > * We call `getMoreSpecialized` determine whether the partial specialization > is more specialized than the primary. > * We determine that neither template is at least as specialized as the other > via `isAtLeastAsSpecializedAs`. > * We call `TemplateParameterListsAreEqual` per [[temp.func.order] > p6.2.2](http://eel.is/c++draft/temp.func.order#6.2.2) to check for template > parameter equivalence, and compare the two template parameters by calling > `MatchTemplateParameterKind`. > * `MatchTemplateParameterKind` calls `ASTContext::getUnconstrainedType` to > get the unconstrained type of the template parameters per [[temp.over.link] > p6 sentence 2](http://eel.is/c++draft/temp.over.link#6.sentence-2). For the > class templates template parameter, it returns the type unchanged (a > _**dependent**_ `AutoType`). For the class template partial specializations > template parameter, it returns an unconstrained `AutoType` _**that isn't > dependent**_. > * We compare the adjusted types and determine they aren't equal, so we > consider neither template to be more specialized than the other. > > So, I think the correct fix is to propagate dependence in > `ASTContext::getUnconstrainedType`. I have a branch that implements this > [here](https://github.com/sdkrystian/llvm-project/tree/partial-spec-dependent-auto). > WDYT @erichkeane @cor3ntin @zyn0217? This is really a perfect approach and it has addressed the underlying issue. And thanks for your explaination! https://github.com/llvm/llvm-project/pull/91842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/91842 >From 0ebdcec675c39b26b8bee1a8b07c12fae2c58523 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Sat, 11 May 2024 14:04:23 +0800 Subject: [PATCH] [clang] visit constraint of NTTP --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/StmtProfile.cpp | 4 .../temp.fct/temp.func.order/p6.cpp | 6 +++--- clang/test/SemaCXX/PR77377.cpp| 19 +++ 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 clang/test/SemaCXX/PR77377.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7c5dcc59c7016..30d359c582d3f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -707,6 +707,7 @@ Bug Fixes to C++ Support initialized, rather than evaluating them as a part of the larger manifestly constant evaluated expression. - Fix a bug in access control checking due to dealyed checking of friend declaration. Fixes (#GH12361). +- Fix a bug on template class partial specialization due to traverse of constraint of NTTP. Fixes (#GH77377). Bug Fixes to AST Handling ^ diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8fb8940142eb0..a23a2efa2389e 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2257,6 +2257,10 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmExpr( const SubstNonTypeTemplateParmExpr *E) { // Profile exactly as the replacement expression. Visit(E->getReplacement()); + if (auto *NTTP = dyn_cast(E->getParameter()); + NTTP && NTTP->getPlaceholderTypeConstraint()) { +Visit(NTTP->getPlaceholderTypeConstraint()); + } } void StmtProfiler::VisitFunctionParmPackExpr(const FunctionParmPackExpr *S) { diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp index 9f44878da6254..5f9719a2dc561 100644 --- a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp @@ -79,14 +79,14 @@ template struct Y2 {}; // expected-note {{partial template class U, typename... Z> struct Y3 { Y3()=delete; }; template class U, typename... Z> -struct Y3 { Y3()=delete; }; +struct Y3 { Y3()=delete; }; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} template class U, typename... Z> -struct Y3 {}; +struct Y3 {}; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} void f() { Y1 a; Y2 b; // expected-error {{ambiguous partial specializations}} - Y3 c; + Y3 c; // expected-error {{ambiguous partial specializations of 'Y3'}} } // Per [temp.func.order]p6.2.2, specifically "if the function parameters that diff --git a/clang/test/SemaCXX/PR77377.cpp b/clang/test/SemaCXX/PR77377.cpp new file mode 100644 index 0..ae34809c3903d --- /dev/null +++ b/clang/test/SemaCXX/PR77377.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s +// expected-no-diagnostics + +template +constexpr bool is_same_v = false; + +template +constexpr bool is_same_v = true; + +template +concept same_as = is_same_v; + +template +struct A {}; + +template auto p> +struct A {}; + +A<0> a; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/91842 >From 4133001711b82c93e057e1bd05476c5d052d597f Mon Sep 17 00:00:00 2001 From: huqizhi Date: Sat, 11 May 2024 14:04:23 +0800 Subject: [PATCH] [clang] visit constraint of NTTP --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/StmtProfile.cpp | 4 .../temp.fct/temp.func.order/p6.cpp | 6 +++--- clang/test/SemaCXX/PR77377.cpp| 19 +++ 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 clang/test/SemaCXX/PR77377.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7c5dcc59c7016..30d359c582d3f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -707,6 +707,7 @@ Bug Fixes to C++ Support initialized, rather than evaluating them as a part of the larger manifestly constant evaluated expression. - Fix a bug in access control checking due to dealyed checking of friend declaration. Fixes (#GH12361). +- Fix a bug on template class partial specialization due to traverse of constraint of NTTP. Fixes (#GH77377). Bug Fixes to AST Handling ^ diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8fb8940142eb0..a23a2efa2389e 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2257,6 +2257,10 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmExpr( const SubstNonTypeTemplateParmExpr *E) { // Profile exactly as the replacement expression. Visit(E->getReplacement()); + if (auto *NTTP = dyn_cast(E->getParameter()); + NTTP && NTTP->getPlaceholderTypeConstraint()) { +Visit(NTTP->getPlaceholderTypeConstraint()); + } } void StmtProfiler::VisitFunctionParmPackExpr(const FunctionParmPackExpr *S) { diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp index 9f44878da6254..5f9719a2dc561 100644 --- a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp @@ -79,14 +79,14 @@ template struct Y2 {}; // expected-note {{partial template class U, typename... Z> struct Y3 { Y3()=delete; }; template class U, typename... Z> -struct Y3 { Y3()=delete; }; +struct Y3 { Y3()=delete; }; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} template class U, typename... Z> -struct Y3 {}; +struct Y3 {}; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} void f() { Y1 a; Y2 b; // expected-error {{ambiguous partial specializations}} - Y3 c; + Y3 c; // expected-error {{ambiguous partial specializations of 'Y3'}} } // Per [temp.func.order]p6.2.2, specifically "if the function parameters that diff --git a/clang/test/SemaCXX/PR77377.cpp b/clang/test/SemaCXX/PR77377.cpp new file mode 100644 index 0..ae34809c3903d --- /dev/null +++ b/clang/test/SemaCXX/PR77377.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s +// expected-no-diagnostics + +template +constexpr bool is_same_v = false; + +template +constexpr bool is_same_v = true; + +template +concept same_as = is_same_v; + +template +struct A {}; + +template auto p> +struct A {}; + +A<0> a; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
@@ -79,14 +79,14 @@ template struct Y2 {}; // expected-note {{partial template class U, typename... Z> struct Y3 { Y3()=delete; }; template class U, typename... Z> -struct Y3 { Y3()=delete; }; +struct Y3 { Y3()=delete; }; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} template class U, typename... Z> -struct Y3 {}; +struct Y3 {}; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} void f() { Y1 a; Y2 b; // expected-error {{ambiguous partial specializations}} - Y3 c; + Y3 c; // expected-error {{ambiguous partial specializations of 'Y3'}} jcsxky wrote: When instantiation, we are checking which one of the two partial specialization is more specialized. Obviously, the first one(`auto D`) is not more specialized than the second(`auto E`). When applied this patch, the second one is not more specialized than the first as well. This is because `isSameTemplateArg` return `false` and the result is not `TemplateDeductionResult::Success`. Although we get correct result, it is not because of ignoring the type-constraint. Back to the quote, if we ignore the use of type-constraints for placeholder types, is the following example ill-formed due to their equivalent template arguments? ```cpp template constexpr bool True = true; template concept C = True; template concept D = C && sizeof(T) > 2; template concept E = D && alignof(T) > 1; template struct Y3 { Y3()=delete; }; template struct Y3 { Y3()=delete; }; template struct Y3 {}; ``` But EDG, gcc and MSVC all accept this code. So I think the existing test is rejected may not be related to the quote. WDYT? @cor3ntin @zyn0217 @erichkeane https://github.com/llvm/llvm-project/pull/91842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
https://github.com/jcsxky edited https://github.com/llvm/llvm-project/pull/91842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
@@ -79,14 +79,14 @@ template struct Y2 {}; // expected-note {{partial template class U, typename... Z> struct Y3 { Y3()=delete; }; template class U, typename... Z> -struct Y3 { Y3()=delete; }; +struct Y3 { Y3()=delete; }; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} template class U, typename... Z> -struct Y3 {}; +struct Y3 {}; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} void f() { Y1 a; Y2 b; // expected-error {{ambiguous partial specializations}} - Y3 c; + Y3 c; // expected-error {{ambiguous partial specializations of 'Y3'}} jcsxky wrote: I think the quote can explain why we should report error here. Maybe more work are required to find out where we do the ignore and how this patch impacts this case. https://github.com/llvm/llvm-project/pull/91842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
https://github.com/jcsxky edited https://github.com/llvm/llvm-project/pull/91842 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] visit constraint of NTTP (PR #91842)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/91842 attempt to fix `isSameTemplateArg` returns incorrect result since clang didn't visit constraint of NTTP. Furthermore, It makes class template partial specialization not more specialized than the class template itself. >From ddc0fbb7a249fbc6f2d2795fda262b2e7ca0a4e9 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Sat, 11 May 2024 14:04:23 +0800 Subject: [PATCH] [clang] visit constraint of NTTP --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/StmtProfile.cpp | 5 + .../temp.fct/temp.func.order/p6.cpp | 6 +++--- clang/test/SemaCXX/PR77377.cpp| 19 +++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 clang/test/SemaCXX/PR77377.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7c5dcc59c7016..30d359c582d3f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -707,6 +707,7 @@ Bug Fixes to C++ Support initialized, rather than evaluating them as a part of the larger manifestly constant evaluated expression. - Fix a bug in access control checking due to dealyed checking of friend declaration. Fixes (#GH12361). +- Fix a bug on template class partial specialization due to traverse of constraint of NTTP. Fixes (#GH77377). Bug Fixes to AST Handling ^ diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 8fb8940142eb0..0bb5a40d7350e 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2257,6 +2257,11 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmExpr( const SubstNonTypeTemplateParmExpr *E) { // Profile exactly as the replacement expression. Visit(E->getReplacement()); + if (auto *NTTP = + dyn_cast_if_present(E->getParameter()); + NTTP && NTTP->getPlaceholderTypeConstraint()) { +Visit(NTTP->getPlaceholderTypeConstraint()); + } } void StmtProfiler::VisitFunctionParmPackExpr(const FunctionParmPackExpr *S) { diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp index 9f44878da6254..5f9719a2dc561 100644 --- a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p6.cpp @@ -79,14 +79,14 @@ template struct Y2 {}; // expected-note {{partial template class U, typename... Z> struct Y3 { Y3()=delete; }; template class U, typename... Z> -struct Y3 { Y3()=delete; }; +struct Y3 { Y3()=delete; }; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} template class U, typename... Z> -struct Y3 {}; +struct Y3 {}; // expected-note {{partial specialization matches [with T = int, I = 1, W = 1, S = A{}, U = S, Z = ]}} void f() { Y1 a; Y2 b; // expected-error {{ambiguous partial specializations}} - Y3 c; + Y3 c; // expected-error {{ambiguous partial specializations of 'Y3'}} } // Per [temp.func.order]p6.2.2, specifically "if the function parameters that diff --git a/clang/test/SemaCXX/PR77377.cpp b/clang/test/SemaCXX/PR77377.cpp new file mode 100644 index 0..ae34809c3903d --- /dev/null +++ b/clang/test/SemaCXX/PR77377.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s +// expected-no-diagnostics + +template +constexpr bool is_same_v = false; + +template +constexpr bool is_same_v = true; + +template +concept same_as = is_same_v; + +template +struct A {}; + +template auto p> +struct A {}; + +A<0> a; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/91430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/91430 >From 002751420c7f71fa9903d94e135565793bd8c6f8 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Tue, 7 May 2024 22:32:39 +0800 Subject: [PATCH 1/2] [Clang][Sema] access checking of friend declaration should not be delayed --- clang/include/clang/Sema/Scope.h | 6 ++ clang/lib/Parse/ParseDecl.cpp| 7 +-- clang/lib/Sema/Scope.cpp | 2 ++ clang/lib/Sema/SemaAccess.cpp| 12 ++-- clang/test/SemaCXX/PR12361.cpp | 30 ++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 clang/test/SemaCXX/PR12361.cpp diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 1752a25111a77..084db73034219 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -159,6 +159,9 @@ class Scope { /// This is a scope of type alias declaration. TypeAliasScope = 0x2000, + +/// This is a scope of friend declaration. +FriendScope = 0x4000, }; private: @@ -586,6 +589,9 @@ class Scope { /// Determine whether this scope is a type alias scope. bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; } + /// Determine whether this scope is a friend scope. + bool isFriendScope() const { return getFlags() & Scope::FriendScope; } + /// Returns if rhs has a higher scope depth than this. /// /// The caller is responsible for calling this only if one of the two scopes diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 2c11ae693c354..5b5fc02ad4023 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4331,9 +4331,12 @@ void Parser::ParseDeclarationSpecifiers( // friend case tok::kw_friend: - if (DSContext == DeclSpecContext::DSC_class) + if (DSContext == DeclSpecContext::DSC_class) { isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); - else { +Scope *CurS = getCurScope(); +if (!isInvalid && CurS) + CurS->setFlags(CurS->getFlags() | Scope::FriendScope); + } else { PrevSpec = ""; // not actually used by the diagnostic DiagID = diag::err_friend_invalid_in_context; isInvalid = true; diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index 11a41753a1bda..780aa898b1085 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -229,6 +229,8 @@ void Scope::dumpImpl(raw_ostream &OS) const { {ClassInheritanceScope, "ClassInheritanceScope"}, {CatchScope, "CatchScope"}, {OpenACCComputeConstructScope, "OpenACCComputeConstructScope"}, + {TypeAliasScope, "TypeAliasScope"}, + {FriendScope, "FriendScope"}, }; for (auto Info : FlagInfo) { diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 6a707eeb66d01..72c6736bb6648 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1477,8 +1477,16 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // void foo(A::private_type); // void B::foo(A::private_type); if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { -S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); -return Sema::AR_delayed; +Scope *TS = S.getCurScope(); +bool IsFriendDeclaration = false; +while (TS && !IsFriendDeclaration) { + IsFriendDeclaration = TS->isFriendScope(); + TS = TS->getParent(); +} +if (!IsFriendDeclaration) { + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; +} } EffectiveContext EC(S.CurContext); diff --git a/clang/test/SemaCXX/PR12361.cpp b/clang/test/SemaCXX/PR12361.cpp new file mode 100644 index 0..95ceb45b7ba04 --- /dev/null +++ b/clang/test/SemaCXX/PR12361.cpp @@ -0,0 +1,30 @@ + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s + +class D { +class E{ +class F{}; // expected-note{{implicitly declared private here}} +friend void foo(D::E::F& q); +}; +friend void foo(D::E::F& q); // expected-error{{'F' is a private member of 'D::E'}} +}; + +void foo(D::E::F& q) {} + +class D1 { +class E1{ +class F1{}; // expected-note{{implicitly declared private here}} +friend D1::E1::F1 foo1(); +}; +friend D1::E1::F1 foo1(); // expected-error{{'F1' is a private member of 'D1::E1'}} +}; + +D1::E1::F1 foo1() { return D1::E1::F1(); } + +class D2 { +class E2{ +class F2{}; +friend void foo2(); +}; +friend void foo2(){ D2::E2::F2 c;} +}; >From 113c8508881babe25ab9d1daa9ab9a72018da124 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Wed, 8 May 2024 21:22:01 +0800 Subject: [PATCH 2/2] apply reviews --- clang/docs/ReleaseN
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/91430 >From 324e4361b4cb1b17065b4dc7d4bdfa41fe781e7d Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Tue, 7 May 2024 22:32:39 +0800 Subject: [PATCH 1/2] [Clang][Sema] access checking of friend declaration should not be delayed --- clang/include/clang/Sema/Scope.h | 6 ++ clang/lib/Parse/ParseDecl.cpp| 7 +-- clang/lib/Sema/Scope.cpp | 2 ++ clang/lib/Sema/SemaAccess.cpp| 12 ++-- clang/test/SemaCXX/PR12361.cpp | 30 ++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 clang/test/SemaCXX/PR12361.cpp diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 1752a25111a77..084db73034219 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -159,6 +159,9 @@ class Scope { /// This is a scope of type alias declaration. TypeAliasScope = 0x2000, + +/// This is a scope of friend declaration. +FriendScope = 0x4000, }; private: @@ -586,6 +589,9 @@ class Scope { /// Determine whether this scope is a type alias scope. bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; } + /// Determine whether this scope is a friend scope. + bool isFriendScope() const { return getFlags() & Scope::FriendScope; } + /// Returns if rhs has a higher scope depth than this. /// /// The caller is responsible for calling this only if one of the two scopes diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 4e4b05b21383e..78a81c77f48c6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4332,9 +4332,12 @@ void Parser::ParseDeclarationSpecifiers( // friend case tok::kw_friend: - if (DSContext == DeclSpecContext::DSC_class) + if (DSContext == DeclSpecContext::DSC_class) { isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); - else { +Scope *CurS = getCurScope(); +if (!isInvalid && CurS) + CurS->setFlags(CurS->getFlags() | Scope::FriendScope); + } else { PrevSpec = ""; // not actually used by the diagnostic DiagID = diag::err_friend_invalid_in_context; isInvalid = true; diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index 11a41753a1bda..780aa898b1085 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -229,6 +229,8 @@ void Scope::dumpImpl(raw_ostream &OS) const { {ClassInheritanceScope, "ClassInheritanceScope"}, {CatchScope, "CatchScope"}, {OpenACCComputeConstructScope, "OpenACCComputeConstructScope"}, + {TypeAliasScope, "TypeAliasScope"}, + {FriendScope, "FriendScope"}, }; for (auto Info : FlagInfo) { diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 6a707eeb66d01..72c6736bb6648 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1477,8 +1477,16 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // void foo(A::private_type); // void B::foo(A::private_type); if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { -S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); -return Sema::AR_delayed; +Scope *TS = S.getCurScope(); +bool IsFriendDeclaration = false; +while (TS && !IsFriendDeclaration) { + IsFriendDeclaration = TS->isFriendScope(); + TS = TS->getParent(); +} +if (!IsFriendDeclaration) { + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; +} } EffectiveContext EC(S.CurContext); diff --git a/clang/test/SemaCXX/PR12361.cpp b/clang/test/SemaCXX/PR12361.cpp new file mode 100644 index 0..95ceb45b7ba04 --- /dev/null +++ b/clang/test/SemaCXX/PR12361.cpp @@ -0,0 +1,30 @@ + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s + +class D { +class E{ +class F{}; // expected-note{{implicitly declared private here}} +friend void foo(D::E::F& q); +}; +friend void foo(D::E::F& q); // expected-error{{'F' is a private member of 'D::E'}} +}; + +void foo(D::E::F& q) {} + +class D1 { +class E1{ +class F1{}; // expected-note{{implicitly declared private here}} +friend D1::E1::F1 foo1(); +}; +friend D1::E1::F1 foo1(); // expected-error{{'F1' is a private member of 'D1::E1'}} +}; + +D1::E1::F1 foo1() { return D1::E1::F1(); } + +class D2 { +class E2{ +class F2{}; +friend void foo2(); +}; +friend void foo2(){ D2::E2::F2 c;} +}; >From 97723ff0ec73ac107bc74f222852e4c12b727eb0 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Wed, 8 May 2024 21:22:01 +0800 Subject: [PATCH 2/2] apply reviews --- clang/docs/ReleaseN
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
@@ -1477,8 +1477,16 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // void foo(A::private_type); // void B::foo(A::private_type); if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { -S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); -return Sema::AR_delayed; +Scope *TS = S.getCurScope(); +bool IsFriendDeclaration = false; +while (TS && !IsFriendDeclaration) { + IsFriendDeclaration = TS->isFriendScope(); + TS = TS->getParent(); +} +if (!IsFriendDeclaration) { + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; +} jcsxky wrote: Added. https://github.com/llvm/llvm-project/pull/91430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
@@ -229,6 +229,8 @@ void Scope::dumpImpl(raw_ostream &OS) const { {ClassInheritanceScope, "ClassInheritanceScope"}, {CatchScope, "CatchScope"}, {OpenACCComputeConstructScope, "OpenACCComputeConstructScope"}, + {TypeAliasScope, "TypeAliasScope"}, jcsxky wrote: Removed. This will be done in a follow-up. https://github.com/llvm/llvm-project/pull/91430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
@@ -1477,8 +1477,16 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // void foo(A::private_type); jcsxky wrote: Done. https://github.com/llvm/llvm-project/pull/91430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/91430 >From ec4f21b7823a89a793b0799b22c6bbdb0bfb4c52 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Tue, 7 May 2024 22:32:39 +0800 Subject: [PATCH 1/2] [Clang][Sema] access checking of friend declaration should not be delayed --- clang/include/clang/Sema/Scope.h | 6 ++ clang/lib/Parse/ParseDecl.cpp| 7 +-- clang/lib/Sema/Scope.cpp | 2 ++ clang/lib/Sema/SemaAccess.cpp| 12 ++-- clang/test/SemaCXX/PR12361.cpp | 30 ++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 clang/test/SemaCXX/PR12361.cpp diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 1752a25111a77..084db73034219 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -159,6 +159,9 @@ class Scope { /// This is a scope of type alias declaration. TypeAliasScope = 0x2000, + +/// This is a scope of friend declaration. +FriendScope = 0x4000, }; private: @@ -586,6 +589,9 @@ class Scope { /// Determine whether this scope is a type alias scope. bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; } + /// Determine whether this scope is a friend scope. + bool isFriendScope() const { return getFlags() & Scope::FriendScope; } + /// Returns if rhs has a higher scope depth than this. /// /// The caller is responsible for calling this only if one of the two scopes diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 4e4b05b21383e..78a81c77f48c6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4332,9 +4332,12 @@ void Parser::ParseDeclarationSpecifiers( // friend case tok::kw_friend: - if (DSContext == DeclSpecContext::DSC_class) + if (DSContext == DeclSpecContext::DSC_class) { isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); - else { +Scope *CurS = getCurScope(); +if (!isInvalid && CurS) + CurS->setFlags(CurS->getFlags() | Scope::FriendScope); + } else { PrevSpec = ""; // not actually used by the diagnostic DiagID = diag::err_friend_invalid_in_context; isInvalid = true; diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index 11a41753a1bda..780aa898b1085 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -229,6 +229,8 @@ void Scope::dumpImpl(raw_ostream &OS) const { {ClassInheritanceScope, "ClassInheritanceScope"}, {CatchScope, "CatchScope"}, {OpenACCComputeConstructScope, "OpenACCComputeConstructScope"}, + {TypeAliasScope, "TypeAliasScope"}, + {FriendScope, "FriendScope"}, }; for (auto Info : FlagInfo) { diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 6a707eeb66d01..72c6736bb6648 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1477,8 +1477,16 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // void foo(A::private_type); // void B::foo(A::private_type); if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { -S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); -return Sema::AR_delayed; +Scope *TS = S.getCurScope(); +bool IsFriendDeclaration = false; +while (TS && !IsFriendDeclaration) { + IsFriendDeclaration = TS->isFriendScope(); + TS = TS->getParent(); +} +if (!IsFriendDeclaration) { + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; +} } EffectiveContext EC(S.CurContext); diff --git a/clang/test/SemaCXX/PR12361.cpp b/clang/test/SemaCXX/PR12361.cpp new file mode 100644 index 0..95ceb45b7ba04 --- /dev/null +++ b/clang/test/SemaCXX/PR12361.cpp @@ -0,0 +1,30 @@ + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s + +class D { +class E{ +class F{}; // expected-note{{implicitly declared private here}} +friend void foo(D::E::F& q); +}; +friend void foo(D::E::F& q); // expected-error{{'F' is a private member of 'D::E'}} +}; + +void foo(D::E::F& q) {} + +class D1 { +class E1{ +class F1{}; // expected-note{{implicitly declared private here}} +friend D1::E1::F1 foo1(); +}; +friend D1::E1::F1 foo1(); // expected-error{{'F1' is a private member of 'D1::E1'}} +}; + +D1::E1::F1 foo1() { return D1::E1::F1(); } + +class D2 { +class E2{ +class F2{}; +friend void foo2(); +}; +friend void foo2(){ D2::E2::F2 c;} +}; >From 77cfb6f93c8c91cfbe5d3d1ed4e90450afa026fa Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Wed, 8 May 2024 21:22:01 +0800 Subject: [PATCH 2/2] apply reviews --- clang/docs/ReleaseN
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/91430 >From a4eee6db746e8de0743369f701d1b6a3fcc84754 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Tue, 7 May 2024 22:32:39 +0800 Subject: [PATCH 1/2] [Clang][Sema] access checking of friend declaration should not be delayed --- clang/include/clang/Sema/Scope.h | 6 ++ clang/lib/Parse/ParseDecl.cpp| 7 +-- clang/lib/Sema/Scope.cpp | 2 ++ clang/lib/Sema/SemaAccess.cpp| 12 ++-- clang/test/SemaCXX/PR12361.cpp | 30 ++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 clang/test/SemaCXX/PR12361.cpp diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 1752a25111a77..084db73034219 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -159,6 +159,9 @@ class Scope { /// This is a scope of type alias declaration. TypeAliasScope = 0x2000, + +/// This is a scope of friend declaration. +FriendScope = 0x4000, }; private: @@ -586,6 +589,9 @@ class Scope { /// Determine whether this scope is a type alias scope. bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; } + /// Determine whether this scope is a friend scope. + bool isFriendScope() const { return getFlags() & Scope::FriendScope; } + /// Returns if rhs has a higher scope depth than this. /// /// The caller is responsible for calling this only if one of the two scopes diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 4e4b05b21383e..78a81c77f48c6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4332,9 +4332,12 @@ void Parser::ParseDeclarationSpecifiers( // friend case tok::kw_friend: - if (DSContext == DeclSpecContext::DSC_class) + if (DSContext == DeclSpecContext::DSC_class) { isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); - else { +Scope *CurS = getCurScope(); +if (!isInvalid && CurS) + CurS->setFlags(CurS->getFlags() | Scope::FriendScope); + } else { PrevSpec = ""; // not actually used by the diagnostic DiagID = diag::err_friend_invalid_in_context; isInvalid = true; diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index 11a41753a1bda..780aa898b1085 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -229,6 +229,8 @@ void Scope::dumpImpl(raw_ostream &OS) const { {ClassInheritanceScope, "ClassInheritanceScope"}, {CatchScope, "CatchScope"}, {OpenACCComputeConstructScope, "OpenACCComputeConstructScope"}, + {TypeAliasScope, "TypeAliasScope"}, + {FriendScope, "FriendScope"}, }; for (auto Info : FlagInfo) { diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 6a707eeb66d01..72c6736bb6648 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1477,8 +1477,16 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // void foo(A::private_type); // void B::foo(A::private_type); if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { -S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); -return Sema::AR_delayed; +Scope *TS = S.getCurScope(); +bool IsFriendDeclaration = false; +while (TS && !IsFriendDeclaration) { + IsFriendDeclaration = TS->isFriendScope(); + TS = TS->getParent(); +} +if (!IsFriendDeclaration) { + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; +} } EffectiveContext EC(S.CurContext); diff --git a/clang/test/SemaCXX/PR12361.cpp b/clang/test/SemaCXX/PR12361.cpp new file mode 100644 index 0..95ceb45b7ba04 --- /dev/null +++ b/clang/test/SemaCXX/PR12361.cpp @@ -0,0 +1,30 @@ + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s + +class D { +class E{ +class F{}; // expected-note{{implicitly declared private here}} +friend void foo(D::E::F& q); +}; +friend void foo(D::E::F& q); // expected-error{{'F' is a private member of 'D::E'}} +}; + +void foo(D::E::F& q) {} + +class D1 { +class E1{ +class F1{}; // expected-note{{implicitly declared private here}} +friend D1::E1::F1 foo1(); +}; +friend D1::E1::F1 foo1(); // expected-error{{'F1' is a private member of 'D1::E1'}} +}; + +D1::E1::F1 foo1() { return D1::E1::F1(); } + +class D2 { +class E2{ +class F2{}; +friend void foo2(); +}; +friend void foo2(){ D2::E2::F2 c;} +}; >From bce02c31f4b6601e7d031f74fa7e46d868a7d423 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Wed, 8 May 2024 21:22:01 +0800 Subject: [PATCH 2/2] apply reviews --- clang/docs/ReleaseN
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
jcsxky wrote: > Can you add a changelog entry? Ah, I forgot that! will be added when applying other reviews. https://github.com/llvm/llvm-project/pull/91430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
https://github.com/jcsxky edited https://github.com/llvm/llvm-project/pull/91430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/91430 >From a4eee6db746e8de0743369f701d1b6a3fcc84754 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Tue, 7 May 2024 22:32:39 +0800 Subject: [PATCH] [Clang][Sema] access checking of friend declaration should not be delayed --- clang/include/clang/Sema/Scope.h | 6 ++ clang/lib/Parse/ParseDecl.cpp| 7 +-- clang/lib/Sema/Scope.cpp | 2 ++ clang/lib/Sema/SemaAccess.cpp| 12 ++-- clang/test/SemaCXX/PR12361.cpp | 30 ++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 clang/test/SemaCXX/PR12361.cpp diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 1752a25111a77..084db73034219 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -159,6 +159,9 @@ class Scope { /// This is a scope of type alias declaration. TypeAliasScope = 0x2000, + +/// This is a scope of friend declaration. +FriendScope = 0x4000, }; private: @@ -586,6 +589,9 @@ class Scope { /// Determine whether this scope is a type alias scope. bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; } + /// Determine whether this scope is a friend scope. + bool isFriendScope() const { return getFlags() & Scope::FriendScope; } + /// Returns if rhs has a higher scope depth than this. /// /// The caller is responsible for calling this only if one of the two scopes diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 4e4b05b21383e..78a81c77f48c6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4332,9 +4332,12 @@ void Parser::ParseDeclarationSpecifiers( // friend case tok::kw_friend: - if (DSContext == DeclSpecContext::DSC_class) + if (DSContext == DeclSpecContext::DSC_class) { isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); - else { +Scope *CurS = getCurScope(); +if (!isInvalid && CurS) + CurS->setFlags(CurS->getFlags() | Scope::FriendScope); + } else { PrevSpec = ""; // not actually used by the diagnostic DiagID = diag::err_friend_invalid_in_context; isInvalid = true; diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index 11a41753a1bda..780aa898b1085 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -229,6 +229,8 @@ void Scope::dumpImpl(raw_ostream &OS) const { {ClassInheritanceScope, "ClassInheritanceScope"}, {CatchScope, "CatchScope"}, {OpenACCComputeConstructScope, "OpenACCComputeConstructScope"}, + {TypeAliasScope, "TypeAliasScope"}, + {FriendScope, "FriendScope"}, }; for (auto Info : FlagInfo) { diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 6a707eeb66d01..72c6736bb6648 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1477,8 +1477,16 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // void foo(A::private_type); // void B::foo(A::private_type); if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { -S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); -return Sema::AR_delayed; +Scope *TS = S.getCurScope(); +bool IsFriendDeclaration = false; +while (TS && !IsFriendDeclaration) { + IsFriendDeclaration = TS->isFriendScope(); + TS = TS->getParent(); +} +if (!IsFriendDeclaration) { + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; +} } EffectiveContext EC(S.CurContext); diff --git a/clang/test/SemaCXX/PR12361.cpp b/clang/test/SemaCXX/PR12361.cpp new file mode 100644 index 0..95ceb45b7ba04 --- /dev/null +++ b/clang/test/SemaCXX/PR12361.cpp @@ -0,0 +1,30 @@ + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s + +class D { +class E{ +class F{}; // expected-note{{implicitly declared private here}} +friend void foo(D::E::F& q); +}; +friend void foo(D::E::F& q); // expected-error{{'F' is a private member of 'D::E'}} +}; + +void foo(D::E::F& q) {} + +class D1 { +class E1{ +class F1{}; // expected-note{{implicitly declared private here}} +friend D1::E1::F1 foo1(); +}; +friend D1::E1::F1 foo1(); // expected-error{{'F1' is a private member of 'D1::E1'}} +}; + +D1::E1::F1 foo1() { return D1::E1::F1(); } + +class D2 { +class E2{ +class F2{}; +friend void foo2(); +}; +friend void foo2(){ D2::E2::F2 c;} +}; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] access checking of friend declaration should not be delayed (PR #91430)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/91430 attempt to fix https://github.com/llvm/llvm-project/issues/12361 Consider this example: ```cpp class D { class E{ class F{}; // expected-note{{implicitly declared private here}} friend void foo(D::E::F& q); }; friend void foo(D::E::F& q); }; void foo(D::E::F& q) {} ``` The first friend declaration of foo is correct. After that, the second friend declaration delayed access checking and set its previous declaration to be the first one. When doing access checking of `F`(which is private filed of `E`), we put its canonical declaration(the first friend declaration) into `EffectiveContext.Functions`. Actually, we are still checking the first one. This is incorrect due to the delayed checking. Creating a new scope to indicate we are parsing a friend declaration and doing access checking in time. >From 836a66f221777e5c3bdd78087f82c2567854c10c Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Tue, 7 May 2024 22:32:39 +0800 Subject: [PATCH] [Clang][Sema] access checking of friend declaration should not be delayed --- clang/include/clang/Sema/Scope.h | 6 ++ clang/lib/Parse/ParseDecl.cpp| 7 +-- clang/lib/Sema/Scope.cpp | 2 ++ clang/lib/Sema/SemaAccess.cpp| 8 +++- clang/test/SemaCXX/PR12361.cpp | 30 ++ 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 clang/test/SemaCXX/PR12361.cpp diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 1752a25111a77..084db73034219 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -159,6 +159,9 @@ class Scope { /// This is a scope of type alias declaration. TypeAliasScope = 0x2000, + +/// This is a scope of friend declaration. +FriendScope = 0x4000, }; private: @@ -586,6 +589,9 @@ class Scope { /// Determine whether this scope is a type alias scope. bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; } + /// Determine whether this scope is a friend scope. + bool isFriendScope() const { return getFlags() & Scope::FriendScope; } + /// Returns if rhs has a higher scope depth than this. /// /// The caller is responsible for calling this only if one of the two scopes diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 4e4b05b21383e..78a81c77f48c6 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4332,9 +4332,12 @@ void Parser::ParseDeclarationSpecifiers( // friend case tok::kw_friend: - if (DSContext == DeclSpecContext::DSC_class) + if (DSContext == DeclSpecContext::DSC_class) { isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); - else { +Scope *CurS = getCurScope(); +if (!isInvalid && CurS) + CurS->setFlags(CurS->getFlags() | Scope::FriendScope); + } else { PrevSpec = ""; // not actually used by the diagnostic DiagID = diag::err_friend_invalid_in_context; isInvalid = true; diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index 11a41753a1bda..780aa898b1085 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -229,6 +229,8 @@ void Scope::dumpImpl(raw_ostream &OS) const { {ClassInheritanceScope, "ClassInheritanceScope"}, {CatchScope, "CatchScope"}, {OpenACCComputeConstructScope, "OpenACCComputeConstructScope"}, + {TypeAliasScope, "TypeAliasScope"}, + {FriendScope, "FriendScope"}, }; for (auto Info : FlagInfo) { diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 6a707eeb66d01..ded88da510525 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1476,7 +1476,13 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, // Or we might be parsing something that will turn out to be a friend: // void foo(A::private_type); // void B::foo(A::private_type); - if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { + Scope *TS = S.getCurScope(); + bool IsFriendDeclaration = false; + while (TS && !IsFriendDeclaration) { +IsFriendDeclaration = TS->isFriendScope(); +TS = TS->getParent(); + } + if (S.DelayedDiagnostics.shouldDelayDiagnostics() && !IsFriendDeclaration) { S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); return Sema::AR_delayed; } diff --git a/clang/test/SemaCXX/PR12361.cpp b/clang/test/SemaCXX/PR12361.cpp new file mode 100644 index 0..95ceb45b7ba04 --- /dev/null +++ b/clang/test/SemaCXX/PR12361.cpp @@ -0,0 +1,30 @@ + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s + // RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s + +class D { +class E{ +class F{}; // expected-note{{implicitly declared private here}} +friend void foo(
[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)
@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, TemplateArgs->asArray(), /*Final=*/false); +if (RelativeToPrimary && +(Function->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization || jcsxky wrote: @sdkrystian but gcc fails on the testcase you provided. https://github.com/llvm/llvm-project/pull/88963 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix a bug on constraint check with template friend function (PR #90646)
jcsxky wrote: > This still doesn't handle cases such as: > > ```c++ > template > concept E = sizeof(T) == sizeof(U) && sizeof(V) == sizeof(W); > > template // T = char > struct A > { > template // U = signed char > struct B > { > template // V = int, W = int, X = > short > requires E // incorrectly substitutes T = int, U = short, > V = int, V = int > static void f(); > }; > }; > > > template // T = int, U = int > struct C > { > template // V = short > struct D > { > friend void A::B::f(); > }; > }; > > template struct C::D; > > extern template void A::B::f(); > ``` > > (which is handled by > [be79079](https://github.com/llvm/llvm-project/commit/be79079507ffbd9b29683498f405dc2c32dd8ba7)) Thanks for your patience and testcases! They really make me understand these related issues more clearly. https://github.com/llvm/llvm-project/pull/90646 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)
@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, TemplateArgs->asArray(), /*Final=*/false); +if (RelativeToPrimary && +(Function->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization || jcsxky wrote: This testcase runs OK before [be79079](https://github.com/llvm/llvm-project/pull/88963/commits/be79079507ffbd9b29683498f405dc2c32dd8ba7) applied and it may not be related to the condition `Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization`. https://github.com/llvm/llvm-project/pull/88963 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix a bug on constraint check with template friend function (PR #90646)
jcsxky wrote: > I agree with @sdkrystian, even though the test crashes for maybe yet another > reason, it demonstrates you can friend a function from a different template > context, so comparing the depths from different branches is not helpful. @mizvekov I missed the case which friend function is declared in an inner class, and [3d27f11](https://github.com/llvm/llvm-project/pull/90646/commits/3d27f11d79b00608bf9135bcc4b4cb859027933a) demonstrates the comparison works fine. https://github.com/llvm/llvm-project/pull/90646 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix a bug on constraint check with template friend function (PR #90646)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/90646 >From 50aa5b64f6d2cf98706bfb4792f274bd071e3b9c Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Wed, 1 May 2024 02:25:04 +0800 Subject: [PATCH 1/2] [Clang][Sema] fix a bug on constraint check with template friend function --- clang/docs/ReleaseNotes.rst| 1 + clang/lib/Sema/SemaTemplateInstantiate.cpp | 14 +++ clang/test/SemaCXX/PR90349.cpp | 43 ++ 3 files changed, 58 insertions(+) create mode 100644 clang/test/SemaCXX/PR90349.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2c5308fbcb319a..ac90e3933798cb 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -630,6 +630,7 @@ Bug Fixes to C++ Support - Fix a bug on template partial specialization with issue on deduction of nontype template parameter whose type is `decltype(auto)`. Fixes (#GH68885). - Clang now correctly treats the noexcept-specifier of a friend function to be a complete-class context. +- Fix a bug on constraint check with template friend function. Fixes (#GH90349). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 3a9fd906b7af86..1805f8f6e5ad90 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -281,6 +281,20 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, if (Function->getPrimaryTemplate()->isMemberSpecialization()) return Response::Done(); +if (Function->getFriendObjectKind()) + if (const ClassTemplateSpecializationDecl *TD = + dyn_cast( + Function->getLexicalDeclContext())) { +const CXXRecordDecl *TemplatePattern = +TD->getTemplateInstantiationPattern(); +const FunctionDecl *FunctionPattern = +Function->getTemplateInstantiationPattern(); +if (TemplatePattern && FunctionPattern && +TemplatePattern->getTemplateDepth() == +FunctionPattern->getTemplateDepth()) + return Response::Done(); + } + // If this function is a generic lambda specialization, we are done. if (!ForConstraintInstantiation && isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) { diff --git a/clang/test/SemaCXX/PR90349.cpp b/clang/test/SemaCXX/PR90349.cpp new file mode 100644 index 00..6a4b5c21e88f3b --- /dev/null +++ b/clang/test/SemaCXX/PR90349.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +// expected-no-diagnostics + +namespace std { +template +concept floating_point = __is_same(T,double) || __is_same(T,float); + +template +concept integral = __is_same(T,int); + +} + +template +class Blob; + +template +Blob MakeBlob(); + +template +class Blob { +private: +Blob() {} + +friend Blob MakeBlob(); +}; + +template +Blob MakeBlob() +{ +return Blob(); +} + +template +Blob FindBlobs() +{ +return MakeBlob(); +} + +int main(int argc, const char * argv[]) { +FindBlobs(); +return 0; +} >From 3d27f11d79b00608bf9135bcc4b4cb859027933a Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Thu, 2 May 2024 20:05:10 +0800 Subject: [PATCH 2/2] continue to handle context instead of finish --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 +- clang/test/SemaCXX/PR90349.cpp | 24 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 1805f8f6e5ad90..22789c72b2c90f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -292,7 +292,7 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, if (TemplatePattern && FunctionPattern && TemplatePattern->getTemplateDepth() == FunctionPattern->getTemplateDepth()) - return Response::Done(); + return Response::UseNextDecl(Function); } // If this function is a generic lambda specialization, we are done. diff --git a/clang/test/SemaCXX/PR90349.cpp b/clang/test/SemaCXX/PR90349.cpp index 6a4b5c21e88f3b..570a49fd2073bb 100644 --- a/clang/test/SemaCXX/PR90349.cpp +++ b/clang/test/SemaCXX/PR90349.cpp @@ -41,3 +41,27 @@ int main(int argc, const char * argv[]) { FindBlobs(); return 0; } + +template +concept D = sizeof(T) == sizeof(U); + +template +struct A +{ +template requires D +static void f(); +}; + +template +struct B +{ +template +struct C +{ +friend void A::f(); +}; +}; + +template struct B::C; + +extern template void A::f(); // crash here ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mai
[clang] [Clang][Sema] Improve support for explicit specializations of constrained member functions & member function templates (PR #88963)
@@ -275,6 +275,13 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, TemplateArgs->asArray(), /*Final=*/false); +if (RelativeToPrimary && +(Function->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization || jcsxky wrote: Is this condition `Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization` necessary? I removed it and all testcases passed. Could you please add a testcase to cover it which would fail without this condition? https://github.com/llvm/llvm-project/pull/88963 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix a bug on constraint check with template friend function (PR #90646)
jcsxky wrote: > ```c++ > template > concept D = sizeof(T) == sizeof(U); > > template > struct A > { > template requires D > static void f(); > }; > > template > struct B > { > template > struct C > { > friend void A::f(); > }; > }; > > template struct B::C; > > extern template void A::f(); // crash here > ``` > > @jcsxky causes crash with and without this patch applied. Thanks for your feedback! This may be another issue. clang trunk crashes with this case. https://github.com/llvm/llvm-project/pull/90646 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix a bug on constraint check with template friend function (PR #90646)
jcsxky wrote: Windows CI failed with some unrelated files. https://github.com/llvm/llvm-project/pull/90646 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix a bug on constraint check with template friend function (PR #90646)
jcsxky wrote: > I'm actually working on constraint checking for function template > specializations in #88963. I don't think this patch is quite right... this > will cause a crash if the befriended function is a member of a class template > specialization. Relative to the changes in #88963, I believe the correct fix > would be to change line 278 to: > > ```c++ > if (RelativeToPrimary && > (Function->getTemplateSpecializationKind() == > TSK_ExplicitSpecialization || > (Function->getFriendObjectKind() && > !Function->getPrimaryTemplate()->getFriendObjectKind( > return Response::UseNextDecl(Function); > ``` > > I added a commit to #88963 which makes this change > ([be79079](https://github.com/llvm/llvm-project/commit/be79079507ffbd9b29683498f405dc2c32dd8ba7)) > > cc @erichkeane Only when the friend function doesn't use any other new template parameters, i.e. their depth is equal can we skip to add the outer arguments to `MTAL`. > this will cause a crash if the befriended function is a member of a class > template specialization Could you please provide a testcase? https://github.com/llvm/llvm-project/pull/90646 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix a bug on constraint check with template friend function (PR #90646)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/90646 attempt to fix https://github.com/llvm/llvm-project/issues/90349 Skip to add outer class template arguments to `MTAL` when the friend function has the same depth with its lexical context(`CXXRecordDecl`). >From e2785999ed38cd3b0addcf28d9122ecf8100d908 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744...@qq.com> Date: Wed, 1 May 2024 02:25:04 +0800 Subject: [PATCH] [Clang][Sema] fix a bug on constraint check with template friend function --- clang/docs/ReleaseNotes.rst| 1 + clang/lib/Sema/SemaTemplateInstantiate.cpp | 14 +++ clang/test/SemaCXX/PR90349.cpp | 43 ++ 3 files changed, 58 insertions(+) create mode 100644 clang/test/SemaCXX/PR90349.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c11f117cd6e8b4..ec10c82a3a5403 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -627,6 +627,7 @@ Bug Fixes to C++ Support - Fix a bug on template partial specialization with issue on deduction of nontype template parameter whose type is `decltype(auto)`. Fixes (#GH68885). - Clang now correctly treats the noexcept-specifier of a friend function to be a complete-class context. +- Fix a bug on constraint check with template friend function. Fixes (#GH90349). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 3a9fd906b7af86..1805f8f6e5ad90 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -281,6 +281,20 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, if (Function->getPrimaryTemplate()->isMemberSpecialization()) return Response::Done(); +if (Function->getFriendObjectKind()) + if (const ClassTemplateSpecializationDecl *TD = + dyn_cast( + Function->getLexicalDeclContext())) { +const CXXRecordDecl *TemplatePattern = +TD->getTemplateInstantiationPattern(); +const FunctionDecl *FunctionPattern = +Function->getTemplateInstantiationPattern(); +if (TemplatePattern && FunctionPattern && +TemplatePattern->getTemplateDepth() == +FunctionPattern->getTemplateDepth()) + return Response::Done(); + } + // If this function is a generic lambda specialization, we are done. if (!ForConstraintInstantiation && isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) { diff --git a/clang/test/SemaCXX/PR90349.cpp b/clang/test/SemaCXX/PR90349.cpp new file mode 100644 index 00..6a4b5c21e88f3b --- /dev/null +++ b/clang/test/SemaCXX/PR90349.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +// expected-no-diagnostics + +namespace std { +template +concept floating_point = __is_same(T,double) || __is_same(T,float); + +template +concept integral = __is_same(T,int); + +} + +template +class Blob; + +template +Blob MakeBlob(); + +template +class Blob { +private: +Blob() {} + +friend Blob MakeBlob(); +}; + +template +Blob MakeBlob() +{ +return Blob(); +} + +template +Blob FindBlobs() +{ +return MakeBlob(); +} + +int main(int argc, const char * argv[]) { +FindBlobs(); +return 0; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix a bug on template partial specialization with issue on deduction of nontype template parameter (PR #90376)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/90376 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix a bug on template partial specialization with issue on deduction of nontype template parameter (PR #90376)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/90376 >From c5c67ed879fc58e5371de6fc8296b7b6f653a072 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Sun, 28 Apr 2024 14:24:30 +0800 Subject: [PATCH] [Clang][Sema] Fix a bug on template partial specialization with issue on deduction of nontype tempalte parameter --- clang/docs/ReleaseNotes.rst | 2 ++ clang/include/clang/Sema/Sema.h | 10 ++ clang/lib/Sema/SemaTemplate.cpp | 19 +++ clang/lib/Sema/SemaTemplateDeduction.cpp | 10 ++ clang/test/SemaCXX/PR68885.cpp | 21 + 5 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 clang/test/SemaCXX/PR68885.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 98c80b6017f604..1abc00a25f1f42 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -612,6 +612,8 @@ Bug Fixes to C++ Support - Fix CTAD for ``std::initializer_list``. This allows ``std::initializer_list{1, 2, 3}`` to be deduced as ``std::initializer_list`` as intended. - Fix a bug on template partial specialization whose template parameter is `decltype(auto)`. +- Fix a bug on template partial specialization with issue on deduction of nontype template parameter + whose type is `decltype(auto)`. Fixes (#GH68885). Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1ca523ec88c2f9..809b9c4498f697 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9249,7 +9249,8 @@ class Sema final : public SemaBase { void NoteTemplateParameterLocation(const NamedDecl &Decl); ExprResult BuildExpressionFromDeclTemplateArgument( - const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc); + const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, + NamedDecl *TemplateParam = nullptr); ExprResult BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg, SourceLocation Loc); @@ -9572,9 +9573,10 @@ class Sema final : public SemaBase { bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg); - TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, -QualType NTTPType, -SourceLocation Loc); + TemplateArgumentLoc + getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, +SourceLocation Loc, +NamedDecl *TemplateParam = nullptr); /// Get a template argument mapping the given template parameter to itself, /// e.g. for X in \c template, this would return an expression template diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ed5507c0ec0100..3c2a5a4ac47e69 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8438,10 +8438,9 @@ void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) { /// declaration and the type of its corresponding non-type template /// parameter, produce an expression that properly refers to that /// declaration. -ExprResult -Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, - QualType ParamType, - SourceLocation Loc) { +ExprResult Sema::BuildExpressionFromDeclTemplateArgument( +const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, +NamedDecl *TemplateParam) { // C++ [temp.param]p8: // // A non-type template-parameter of type "array of T" or @@ -8508,6 +8507,18 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, } else { assert(ParamType->isReferenceType() && "unexpected type for decl template argument"); +if (NonTypeTemplateParmDecl *NTTP = +dyn_cast_if_present(TemplateParam)) { + QualType TemplateParamType = NTTP->getType(); + const AutoType *AT = TemplateParamType->getAs(); + if (AT && AT->isDecltypeAuto()) { +RefExpr = new (getASTContext()) SubstNonTypeTemplateParmExpr( +ParamType->getPointeeType(), RefExpr.get()->getValueKind(), +RefExpr.get()->getExprLoc(), RefExpr.get(), VD, NTTP->getIndex(), +/*PackIndex=*/std::nullopt, +/*RefParam=*/true); + } +} } // At this point we should have the right value category. diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index c3815bca038554..e93f7bd842e444 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2639,7 +2639,8 @@ static bool isSameTemplateArg(ASTContext &Context, /// argumen
[clang] [Clang][Sema] fix a bug on template partial specialization (PR #89862)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/89862 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix a bug on template partial specialization (PR #89862)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/89862 >From 242b88a37f08bb66bcdde5e5b30c43553107d29c Mon Sep 17 00:00:00 2001 From: huqizhi Date: Wed, 24 Apr 2024 09:37:53 +0800 Subject: [PATCH] [Clang][Sema] fix a bug on template partial specialization --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaTemplate.cpp | 2 +- ...dentical-type-primary-partial-specialization.cpp | 13 + 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/identical-type-primary-partial-specialization.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4c0fe5bcf6b122..98c80b6017f604 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -611,6 +611,7 @@ Bug Fixes to C++ Support immediate function context. - Fix CTAD for ``std::initializer_list``. This allows ``std::initializer_list{1, 2, 3}`` to be deduced as ``std::initializer_list`` as intended. +- Fix a bug on template partial specialization whose template parameter is `decltype(auto)`. Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index bbcb7c33a98579..ed5507c0ec0100 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -7706,7 +7706,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // FIXME: The language rules don't say what happens in this case. // FIXME: We get an opaque dependent type out of decltype(auto) if the // expression is merely instantiation-dependent; is this enough? -if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) { +if (Arg->isTypeDependent()) { auto *AT = dyn_cast(DeducedT); if (AT && AT->isDecltypeAuto()) { SugaredConverted = TemplateArgument(Arg); diff --git a/clang/test/SemaCXX/identical-type-primary-partial-specialization.cpp b/clang/test/SemaCXX/identical-type-primary-partial-specialization.cpp new file mode 100644 index 00..ad51ca8252ef50 --- /dev/null +++ b/clang/test/SemaCXX/identical-type-primary-partial-specialization.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s + +template +struct S { // expected-note {{previous definition is here}} +static constexpr int i = 42; +}; + +template +struct S { // expected-error {{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}} \ + // expected-error {{redefinition of 'S'}} +static constexpr int i = 0; +}; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix a bug on template partial specialization with issue on deduction of nontype tempalte parameter (PR #90376)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/90376 >From 947096950049ac7047a26335a993e48c1fa5c16d Mon Sep 17 00:00:00 2001 From: huqizhi Date: Sun, 28 Apr 2024 14:24:30 +0800 Subject: [PATCH] [Clang][Sema] Fix a bug on template partial specialization with issue on deduction of nontype tempalte parameter --- clang/docs/ReleaseNotes.rst | 2 ++ clang/include/clang/Sema/Sema.h | 10 ++ clang/lib/Sema/SemaTemplate.cpp | 19 +++ clang/lib/Sema/SemaTemplateDeduction.cpp | 10 ++ clang/test/SemaCXX/PR68885.cpp | 21 + 5 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 clang/test/SemaCXX/PR68885.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 64a523a6f25fc2..64533f94815eb3 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -590,6 +590,8 @@ Bug Fixes to C++ Support - Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235) - Fixed bug in which the body of a consteval lambda within a template was not parsed as within an immediate function context. +- Fix a bug on template partial specialization with issue on deduction of nontype tempalte parameter + whose type is `decltype(auto)`. Fixes (#GH68885). Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1ca523ec88c2f9..809b9c4498f697 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9249,7 +9249,8 @@ class Sema final : public SemaBase { void NoteTemplateParameterLocation(const NamedDecl &Decl); ExprResult BuildExpressionFromDeclTemplateArgument( - const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc); + const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, + NamedDecl *TemplateParam = nullptr); ExprResult BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg, SourceLocation Loc); @@ -9572,9 +9573,10 @@ class Sema final : public SemaBase { bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg); - TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, -QualType NTTPType, -SourceLocation Loc); + TemplateArgumentLoc + getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, +SourceLocation Loc, +NamedDecl *TemplateParam = nullptr); /// Get a template argument mapping the given template parameter to itself, /// e.g. for X in \c template, this would return an expression template diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index bbcb7c33a98579..04f87fff550370 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8438,10 +8438,9 @@ void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) { /// declaration and the type of its corresponding non-type template /// parameter, produce an expression that properly refers to that /// declaration. -ExprResult -Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, - QualType ParamType, - SourceLocation Loc) { +ExprResult Sema::BuildExpressionFromDeclTemplateArgument( +const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, +NamedDecl *TemplateParam) { // C++ [temp.param]p8: // // A non-type template-parameter of type "array of T" or @@ -8508,6 +8507,18 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, } else { assert(ParamType->isReferenceType() && "unexpected type for decl template argument"); +if (NonTypeTemplateParmDecl *NTTP = +dyn_cast_if_present(TemplateParam)) { + QualType TemplateParamType = NTTP->getType(); + const AutoType *AT = TemplateParamType->getAs(); + if (AT && AT->isDecltypeAuto()) { +RefExpr = new (getASTContext()) SubstNonTypeTemplateParmExpr( +ParamType->getPointeeType(), RefExpr.get()->getValueKind(), +RefExpr.get()->getExprLoc(), RefExpr.get(), VD, NTTP->getIndex(), +/*PackIndex=*/std::nullopt, +/*RefParam=*/true); + } +} } // At this point we should have the right value category. diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index c3815bca038554..e93f7bd842e444 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2639,7 +2639,8 @@ static bool isSameTemplateArg(ASTContext &Context, /// arg
[clang] [Clang][Sema] Fix a bug on template partial specialization with issue on deduction of nontype tempalte parameter (PR #90376)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/90376 >From cb7acd79aea4af3e92b5317e55fb43cabc7ebb40 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Sun, 28 Apr 2024 14:24:30 +0800 Subject: [PATCH] [Clang][Sema] Fix a bug on template partial specialization with issue on deduction of nontype tempalte parameter --- clang/docs/ReleaseNotes.rst | 2 ++ clang/include/clang/Sema/Sema.h | 10 ++ clang/lib/Sema/SemaTemplate.cpp | 19 +++ clang/lib/Sema/SemaTemplateDeduction.cpp | 10 ++ clang/test/SemaCXX/PR68885.cpp | 21 + 5 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 clang/test/SemaCXX/PR68885.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 64a523a6f25fc2..64533f94815eb3 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -590,6 +590,8 @@ Bug Fixes to C++ Support - Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235) - Fixed bug in which the body of a consteval lambda within a template was not parsed as within an immediate function context. +- Fix a bug on template partial specialization with issue on deduction of nontype tempalte parameter + whose type is `decltype(auto)`. Fixes (#GH68885). Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1ca523ec88c2f9..809b9c4498f697 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9249,7 +9249,8 @@ class Sema final : public SemaBase { void NoteTemplateParameterLocation(const NamedDecl &Decl); ExprResult BuildExpressionFromDeclTemplateArgument( - const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc); + const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, + NamedDecl *TemplateParam = nullptr); ExprResult BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg, SourceLocation Loc); @@ -9572,9 +9573,10 @@ class Sema final : public SemaBase { bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg); - TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, -QualType NTTPType, -SourceLocation Loc); + TemplateArgumentLoc + getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, +SourceLocation Loc, +NamedDecl *TemplateParam = nullptr); /// Get a template argument mapping the given template parameter to itself, /// e.g. for X in \c template, this would return an expression template diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index bbcb7c33a98579..c91002592781c8 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8438,10 +8438,9 @@ void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) { /// declaration and the type of its corresponding non-type template /// parameter, produce an expression that properly refers to that /// declaration. -ExprResult -Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, - QualType ParamType, - SourceLocation Loc) { +ExprResult Sema::BuildExpressionFromDeclTemplateArgument( +const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, +NamedDecl *TemplateParam) { // C++ [temp.param]p8: // // A non-type template-parameter of type "array of T" or @@ -8508,6 +8507,18 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, } else { assert(ParamType->isReferenceType() && "unexpected type for decl template argument"); +if (NonTypeTemplateParmDecl *NTTP = +dyn_cast_if_present(TemplateParam)) { + QualType TemplateParamType = NTTP->getType(); + const AutoType *AT = TemplateParamType->getAs(); + if (AT && AT->isDecltypeAuto()) { +RefExpr = new (getASTContext()) SubstNonTypeTemplateParmExpr( +ParamType->getPointeeType(), RefExpr.get()->getValueKind(), +RefExpr.get()->getExprLoc(), RefExpr.get(), VD, /*Index=*/0, +/*PackIndex=*/std::nullopt, +/*RefParam=*/true); + } +} } // At this point we should have the right value category. diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index c3815bca038554..e93f7bd842e444 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2639,7 +2639,8 @@ static bool isSameTemplateArg(ASTContext &Context, /// argument
[clang] [Clang][Sema] Fix a bug on template partial specialization with issue on deduction of nontype tempalte parameter (PR #90376)
jcsxky wrote: Windows CI failed with an unrelated file. https://github.com/llvm/llvm-project/pull/90376 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits