[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
[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)
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 (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 (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 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 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 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 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)
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: > ```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] 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)
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] 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] 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: > 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] [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] [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 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 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] [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] [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)
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] 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)
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)
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][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][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: > 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] Fix issue on requires expression with templated base class member function (PR #85198)
jcsxky wrote: > Ah, I had missed (thanks github review tool!) that the 'ImplicitObjectMember' > part already existed. Sorry for that. Never mind! Partly because I didn't make it more clear due to my poor expression . https://github.com/llvm/llvm-project/pull/85198 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix issue on requires expression with templated base class member function (PR #85198)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/85198 >From 0076d87897371f3467c49818a7789cedda27e485 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Thu, 14 Mar 2024 16:32:36 +0800 Subject: [PATCH] [Clang][Sema] Fix issue on requires expression with templated base class member function --- clang/docs/ReleaseNotes.rst| 1 + clang/lib/Sema/SemaExpr.cpp| 3 ++- clang/test/SemaCXX/PR84020.cpp | 23 +++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/PR84020.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index dc108785f6cc99..76701dc723b6c3 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -538,6 +538,7 @@ Bug Fixes to C++ Support object parameter. Fixes (#GH70604), (#GH79754), (#GH84163), (#GH84425), (#GH86054), (#GH86398), and (#GH86399). - Fix a crash when deducing ``auto`` from an invalid dereference (#GH88329). +- Fix a crash in requires expression with templated base class member function. Fixes (#GH84020). Bug Fixes to AST Handling ^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 24f354f1c72498..189764cb4b6b08 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7739,7 +7739,8 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } if (CXXMethodDecl *Method = dyn_cast_or_null(FDecl)) -if (Method->isImplicitObjectMemberFunction()) +if (!isa(CurContext) && +Method->isImplicitObjectMemberFunction()) return ExprError(Diag(LParenLoc, diag::err_member_call_without_object) << Fn->getSourceRange() << 0); diff --git a/clang/test/SemaCXX/PR84020.cpp b/clang/test/SemaCXX/PR84020.cpp new file mode 100644 index 00..8ea5dcc4527ae7 --- /dev/null +++ b/clang/test/SemaCXX/PR84020.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s +// RUN: %clang_cc1 -std=c++23 -verify %s +// expected-no-diagnostics + +struct B { +template +void foo(); + +void bar(); +}; + +template +struct A : T { +auto foo() { +static_assert(requires { T::template foo(); }); +static_assert(requires { T::bar(); }); +} +}; + +int main() { +A a; +a.foo(); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Fix issue on requires expression with templated base class member function (PR #85198)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/85198 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] set declaration invalid earlier to prevent crash in calculating record layout (PR #87173)
jcsxky wrote: gently ping. @erichkeane @shafik Any opinions on this pr? https://github.com/llvm/llvm-project/pull/87173 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] set declaration invalid earlier to prevent crash in calculating record layout (PR #87173)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/87173 >From 19b2cab0c84a934910f65536a0627045d30b9729 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Sun, 31 Mar 2024 09:38:05 +0800 Subject: [PATCH] [Clang][Sema] set declaration invalid earlier to prevent crash in calculating record layout --- clang/docs/ReleaseNotes.rst | 2 ++ clang/include/clang/Sema/Scope.h | 6 ++ clang/lib/Parse/ParseDeclCXX.cpp | 5 + clang/lib/Sema/SemaDecl.cpp | 7 +++ clang/test/SemaCXX/PR75221.cpp | 6 ++ 5 files changed, 26 insertions(+) create mode 100644 clang/test/SemaCXX/PR75221.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c19ad9fba58f37..6c51c2d1f483ce 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -536,6 +536,8 @@ Bug Fixes to C++ Support Fixes (#GH70604), (#GH79754), (#GH84163), (#GH84425), (#GH86054), (#GH86398), and (#GH86399). - Fix a crash when deducing ``auto`` from an invalid dereference (#GH88329). - Fix a crash in requires expression with templated base class member function. Fixes (#GH84020). +- Fix a crash caused by defined struct in a type alias template when the structure + has fields with dependent type. Fixes (#GH75221). Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 099c2739e8603a..1752a25111a775 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -156,6 +156,9 @@ class Scope { /// This is the scope of an OpenACC Compute Construct, which restricts /// jumping into/out of it. OpenACCComputeConstructScope = 0x1000, + +/// This is a scope of type alias declaration. +TypeAliasScope = 0x2000, }; private: @@ -580,6 +583,9 @@ class Scope { /// if/switch/while/for statement. bool isControlScope() const { return getFlags() & Scope::ControlScope; } + /// Determine whether this scope is a type alias scope. + bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; } + /// 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/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 51fd64b2d01aa7..8e0e8682482933 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -799,6 +799,11 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( ProhibitAttributes(PrefixAttrs); Decl *DeclFromDeclSpec = nullptr; +Scope *CurScope = getCurScope(); +if (CurScope) + CurScope->setFlags(Scope::ScopeFlags::TypeAliasScope | + CurScope->getFlags()); + Decl *AD = ParseAliasDeclarationAfterDeclarator( TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec); return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1bde99d6fce740..356abe09a5ca62 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19529,6 +19529,13 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Okay, we successfully defined 'Record'. if (Record) { bool Completed = false; +if (S) { + Scope *Parent = S->getParent(); + if (Parent && Parent->isTypeAliasScope() && + Parent->isTemplateParamScope()) +Record->setInvalidDecl(); +} + if (CXXRecord) { if (!CXXRecord->isInvalidDecl()) { // Set access bits correctly on the directly-declared conversions. diff --git a/clang/test/SemaCXX/PR75221.cpp b/clang/test/SemaCXX/PR75221.cpp new file mode 100644 index 00..b342e347c5606a --- /dev/null +++ b/clang/test/SemaCXX/PR75221.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -verify -std=c++11 -fsyntax-only %s + +template using foo = struct foo { // expected-error {{'foo' cannot be defined in a type alias template}} + T size = 0; +}; +foo a; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] set declaration invalid earlier to prevent crash in calculating record layout (PR #87173)
https://github.com/jcsxky closed https://github.com/llvm/llvm-project/pull/87173 ___ 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 created https://github.com/llvm/llvm-project/pull/89862 attempt to fix https://github.com/llvm/llvm-project/issues/68885#issuecomment-1764201896 Deduction of NTTP whose type is `decltype(auto)` would create an implicit cast expression to dependent type and makes the type of primary template definition (`InjectedClassNameSpecialization`) and its partial specialization different. Prevent emitting cast expression to make clang knows their types are identical by removing `CTAK == CTAK_Deduced` when the type is `decltype(auto)`. >From 9b3e69844033a99be0eef90e816b9dff3e64c901 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 3db558a1c11a3f..27341fb0e3a772 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -561,6 +561,7 @@ Bug Fixes to C++ Support - Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()`` function returns a large or negative value. Fixes (#GH89407). - Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235) +- 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 4bda31ba67c02d..345d77849b49d0 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] 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)
@@ -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 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)
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)
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][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][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][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)
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][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][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 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)
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 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] [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)
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] [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] 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] 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 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)
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 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)
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)
@@ -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)
@@ -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); // 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)
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)
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 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] 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] 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][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][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)
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)
@@ -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)
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,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)
@@ -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] [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)
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] [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][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 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 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 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 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 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 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)
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 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] 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] 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][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] 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)
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 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)
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 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)
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)
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][ASTImporter] fix clash when import `VarTemplateDecl` in record (PR #67522)
https://github.com/jcsxky created https://github.com/llvm/llvm-project/pull/67522 [clang][ASTImporter] fix clash when import `VarTemplateDecl` in record VarTemplateDecl in Record isn't a definition, when imported, it will crash in `ASTContext::setTemplateOrSpecializationInfo` due to setting specialization while it already exists. This patch skip this specific case. >From 0a00f5c846cb53a96133bc8050be74672c2c8343 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Wed, 27 Sep 2023 15:32:10 +0800 Subject: [PATCH] [clang][ASTImporter] fix clash when import `VarTemplateDecl` in record --- clang/lib/AST/ASTImporter.cpp | 6 +- clang/unittests/AST/ASTImporterTest.cpp | 96 - 2 files changed, 48 insertions(+), 54 deletions(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c7c2aecc8b179a4..b207c39cdf90154 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6236,10 +6236,12 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // The Decl in the "From" context has a definition, but in the // "To" context we already have a definition. VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate); -if (D->isThisDeclarationADefinition() && FoundDef) + +if ((D->isThisDeclarationADefinition() && FoundDef) || +FoundTemplate->getDeclContext()->isRecord()) // FIXME Check for ODR error if the two definitions have // different initializers? - return Importer.MapImported(D, FoundDef); + return Importer.MapImported(D, FoundTemplate); FoundByLookup = FoundTemplate; break; diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index c90b5aaeb624306..f2fafaf4329b740 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -4355,58 +4355,6 @@ TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) { EXPECT_TRUE(Imported->getPreviousDecl()); } -TEST_P(ImportFriendClasses, SkipComparingFriendTemplateDepth) { - Decl *ToTU = getToTuDecl( - R"( - template - class A; - - template - class A { - public: -template -friend class A; - -A(T x) :x(x) {} - - private: -T x; - }; - )", - Lang_CXX11); - - auto *Fwd = FirstDeclMatcher().match( - ToTU, - classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A"); - Decl *FromTU = getTuDecl( - R"( - template - class A; - - template - class A { - public: -template -friend class A; - -A(T x) : x(x) {} - - private: -T x; - }; - - A a1(0); - )", - Lang_CXX11, "input1.cc"); - auto *FromA = FirstDeclMatcher().match( - FromTU, - classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A"); - auto *ToA = Import(FromA, Lang_CXX11); - EXPECT_TRUE(ToA); - EXPECT_EQ(Fwd->getTemplatedDecl()->getTypeForDecl(), -ToA->getTemplatedDecl()->getTypeForDecl()); -} - TEST_P(ImportFriendClasses, ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) { Decl *ToTU = getToTuDecl( @@ -4988,6 +4936,50 @@ TEST_P(ASTImporterOptionSpecificTestBase, } } +TEST_P(ImportFriendClasses, RecordVarTemplateDecl) { + Decl *ToTU = getToTuDecl( + R"( + template + class A { + public: +template +struct B { + static U Value; +}; + +template +static constexpr bool X = !B::Value; + }; + )", + Lang_CXX14); + + auto *Fwd = FirstDeclMatcher().match( + ToTU, varTemplateDecl(hasName("X"))); + Decl *FromTU = getTuDecl( + R"( + template + class A { + public: +template +struct B { + static U Value; +}; + +template +static constexpr bool X = !B::Value; + }; + )", + Lang_CXX14, "input1.cc"); + auto *FromA = FirstDeclMatcher().match( + FromTU, varTemplateDecl(hasName("X"))); + auto *ToA = Import(FromA, Lang_CXX11); + EXPECT_TRUE(ToA); + EXPECT_EQ(Fwd->getTemplatedDecl(), +ToA->getTemplatedDecl()); + EXPECT_EQ(Fwd->getTemplatedDecl()->getDefinition(), +ToA->getTemplatedDecl()->getDefinition()); +} + TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) { constexpr auto Code = R"( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImporter] fix clash when import `VarTemplateDecl` in record (PR #67522)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/67522 >From 77224ec6297a4fb9a86f2634f4a0278b49e81625 Mon Sep 17 00:00:00 2001 From: huqizhi Date: Wed, 27 Sep 2023 15:32:10 +0800 Subject: [PATCH] [clang][ASTImporter] fix clash when import `VarTemplateDecl` in record --- clang/lib/AST/ASTImporter.cpp | 5 +- clang/unittests/AST/ASTImporterTest.cpp | 96 - 2 files changed, 48 insertions(+), 53 deletions(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c7c2aecc8b179a4..441c61c16917bea 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6236,10 +6236,13 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // The Decl in the "From" context has a definition, but in the // "To" context we already have a definition. VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate); -if (D->isThisDeclarationADefinition() && FoundDef) + +if ((D->isThisDeclarationADefinition() && FoundDef)) // FIXME Check for ODR error if the two definitions have // different initializers? return Importer.MapImported(D, FoundDef); +if (FoundTemplate->getDeclContext()->isRecord()) + return Importer.MapImported(D, FoundTemplate); FoundByLookup = FoundTemplate; break; diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index c90b5aaeb624306..f2fafaf4329b740 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -4355,58 +4355,6 @@ TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) { EXPECT_TRUE(Imported->getPreviousDecl()); } -TEST_P(ImportFriendClasses, SkipComparingFriendTemplateDepth) { - Decl *ToTU = getToTuDecl( - R"( - template - class A; - - template - class A { - public: -template -friend class A; - -A(T x) :x(x) {} - - private: -T x; - }; - )", - Lang_CXX11); - - auto *Fwd = FirstDeclMatcher().match( - ToTU, - classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A"); - Decl *FromTU = getTuDecl( - R"( - template - class A; - - template - class A { - public: -template -friend class A; - -A(T x) : x(x) {} - - private: -T x; - }; - - A a1(0); - )", - Lang_CXX11, "input1.cc"); - auto *FromA = FirstDeclMatcher().match( - FromTU, - classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A"); - auto *ToA = Import(FromA, Lang_CXX11); - EXPECT_TRUE(ToA); - EXPECT_EQ(Fwd->getTemplatedDecl()->getTypeForDecl(), -ToA->getTemplatedDecl()->getTypeForDecl()); -} - TEST_P(ImportFriendClasses, ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) { Decl *ToTU = getToTuDecl( @@ -4988,6 +4936,50 @@ TEST_P(ASTImporterOptionSpecificTestBase, } } +TEST_P(ImportFriendClasses, RecordVarTemplateDecl) { + Decl *ToTU = getToTuDecl( + R"( + template + class A { + public: +template +struct B { + static U Value; +}; + +template +static constexpr bool X = !B::Value; + }; + )", + Lang_CXX14); + + auto *Fwd = FirstDeclMatcher().match( + ToTU, varTemplateDecl(hasName("X"))); + Decl *FromTU = getTuDecl( + R"( + template + class A { + public: +template +struct B { + static U Value; +}; + +template +static constexpr bool X = !B::Value; + }; + )", + Lang_CXX14, "input1.cc"); + auto *FromA = FirstDeclMatcher().match( + FromTU, varTemplateDecl(hasName("X"))); + auto *ToA = Import(FromA, Lang_CXX11); + EXPECT_TRUE(ToA); + EXPECT_EQ(Fwd->getTemplatedDecl(), +ToA->getTemplatedDecl()); + EXPECT_EQ(Fwd->getTemplatedDecl()->getDefinition(), +ToA->getTemplatedDecl()->getDefinition()); +} + TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) { constexpr auto Code = R"( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ASTImporter] fix clash when import `VarTemplateDecl` in record (PR #67522)
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/67522 >From f158c9bca3461452b3b2b316f616f08b39e6228e Mon Sep 17 00:00:00 2001 From: huqizhi Date: Wed, 27 Sep 2023 15:32:10 +0800 Subject: [PATCH] [clang][ASTImporter] fix clash when import `VarTemplateDecl` in record --- clang/lib/AST/ASTImporter.cpp | 3 + clang/unittests/AST/ASTImporterTest.cpp | 96 - 2 files changed, 47 insertions(+), 52 deletions(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c7c2aecc8b179a4..b06cd9f0a3113dd 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6236,10 +6236,13 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // The Decl in the "From" context has a definition, but in the // "To" context we already have a definition. VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate); + if (D->isThisDeclarationADefinition() && FoundDef) // FIXME Check for ODR error if the two definitions have // different initializers? return Importer.MapImported(D, FoundDef); +if (FoundTemplate->getDeclContext()->isRecord()) + return Importer.MapImported(D, FoundTemplate); FoundByLookup = FoundTemplate; break; diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index c90b5aaeb624306..f2fafaf4329b740 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -4355,58 +4355,6 @@ TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) { EXPECT_TRUE(Imported->getPreviousDecl()); } -TEST_P(ImportFriendClasses, SkipComparingFriendTemplateDepth) { - Decl *ToTU = getToTuDecl( - R"( - template - class A; - - template - class A { - public: -template -friend class A; - -A(T x) :x(x) {} - - private: -T x; - }; - )", - Lang_CXX11); - - auto *Fwd = FirstDeclMatcher().match( - ToTU, - classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A"); - Decl *FromTU = getTuDecl( - R"( - template - class A; - - template - class A { - public: -template -friend class A; - -A(T x) : x(x) {} - - private: -T x; - }; - - A a1(0); - )", - Lang_CXX11, "input1.cc"); - auto *FromA = FirstDeclMatcher().match( - FromTU, - classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName("A"); - auto *ToA = Import(FromA, Lang_CXX11); - EXPECT_TRUE(ToA); - EXPECT_EQ(Fwd->getTemplatedDecl()->getTypeForDecl(), -ToA->getTemplatedDecl()->getTypeForDecl()); -} - TEST_P(ImportFriendClasses, ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) { Decl *ToTU = getToTuDecl( @@ -4988,6 +4936,50 @@ TEST_P(ASTImporterOptionSpecificTestBase, } } +TEST_P(ImportFriendClasses, RecordVarTemplateDecl) { + Decl *ToTU = getToTuDecl( + R"( + template + class A { + public: +template +struct B { + static U Value; +}; + +template +static constexpr bool X = !B::Value; + }; + )", + Lang_CXX14); + + auto *Fwd = FirstDeclMatcher().match( + ToTU, varTemplateDecl(hasName("X"))); + Decl *FromTU = getTuDecl( + R"( + template + class A { + public: +template +struct B { + static U Value; +}; + +template +static constexpr bool X = !B::Value; + }; + )", + Lang_CXX14, "input1.cc"); + auto *FromA = FirstDeclMatcher().match( + FromTU, varTemplateDecl(hasName("X"))); + auto *ToA = Import(FromA, Lang_CXX11); + EXPECT_TRUE(ToA); + EXPECT_EQ(Fwd->getTemplatedDecl(), +ToA->getTemplatedDecl()); + EXPECT_EQ(Fwd->getTemplatedDecl()->getDefinition(), +ToA->getTemplatedDecl()->getDefinition()); +} + TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) { constexpr auto Code = R"( ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits