[clang] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" (PR #111173)
@@ -4159,7 +4159,7 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization .dyn_cast()) { -return Info->getTemplate(); +return Info->getTemplate()->getMostRecentDecl(); sdkrystian wrote: CC @zyn0217 & @erichkeane https://github.com/llvm/llvm-project/pull/73 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" (PR #111173)
@@ -4159,7 +4159,7 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization .dyn_cast()) { -return Info->getTemplate(); +return Info->getTemplate()->getMostRecentDecl(); sdkrystian wrote: @mizvekov I reverted the change where `getPrimaryTemplate` returns the most recent declaration & changed `getTemplateInstantiationPattern` to use the most recent declaration of the primary template instead in d312bd464bae21d127f468075cb78178f782ca9a. https://github.com/llvm/llvm-project/pull/73 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" (PR #111173)
@@ -4159,7 +4159,7 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization .dyn_cast()) { -return Info->getTemplate(); +return Info->getTemplate()->getMostRecentDecl(); sdkrystian wrote: > Why do we need to get the most recent declaration in all these places? @mizvekov One of the changes made by this patch is to set the `isMemberSpecialization` flag on a per-declaration basis. This ensures that `getTemplateInstantiationArgs` behaves correctly for implicitly instantiated declarations that are explicitly specialized for an implicitly instantiated specialization of their enclosing class template. When we look up the name of a template, we typically find the most recent declaration of that template. If that declaration is an explicit specialization of a member template, we use the correct declaration when we try to find the definition of that template. However, if the member template is explicitly specialized _after_ we lookup its name, we end up with an expression naming the implicitly instantiated in-class declaration of that template. If we call `getTemplateInstantiationPattern` on that declaration, it will incorrectly return the pattern from the primary template. https://github.com/llvm/llvm-project/pull/73 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" (PR #111173)
sdkrystian wrote: @zyn0217 I have quite a few test cases I'll be adding soon https://github.com/llvm/llvm-project/pull/73 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" (PR #111173)
sdkrystian wrote: @erichkeane All changes made since the last review are in dfa5179f07b5a85c1daafd93b9f1d4bed9b4e27b https://github.com/llvm/llvm-project/pull/73 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" (PR #111173)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/73 >From 51f84ce80ddda9e12591f263a24a19238fc69cb8 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 23 Sep 2024 10:51:21 -0400 Subject: [PATCH 1/2] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/AST/DeclTemplate.h| 66 +- clang/include/clang/Sema/Sema.h | 25 +- clang/lib/AST/DeclTemplate.cpp| 30 +- clang/lib/Sema/SemaConcept.cpp| 29 +- clang/lib/Sema/SemaDecl.cpp | 31 +- clang/lib/Sema/SemaDeclCXX.cpp| 4 +- clang/lib/Sema/SemaTemplate.cpp | 179 +++-- clang/lib/Sema/SemaTemplateDeduction.cpp | 33 +- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 45 +- clang/lib/Sema/SemaTemplateInstantiate.cpp| 712 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 46 +- clang/lib/Serialization/ASTReader.cpp | 3 +- clang/lib/Serialization/ASTReaderDecl.cpp | 18 +- clang/lib/Serialization/ASTWriterDecl.cpp | 17 +- .../temp/temp.constr/temp.constr.decl/p4.cpp | 175 + 16 files changed, 762 insertions(+), 654 deletions(-) create mode 100644 clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 44d5f348ed2d54..fdb1a5942e4157 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -473,6 +473,9 @@ Bug Fixes to C++ Support containing outer unexpanded parameters were not correctly expanded. (#GH101754) - Fixed a bug in constraint expression comparison where the ``sizeof...`` expression was not handled properly in certain friend declarations. (#GH93099) +- Clang now uses the correct set of template argument lists when comparing the constraints of + out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of + a class template. (#GH102320) Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 687715a22e9fd3..05739f39d2a496 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -781,15 +781,11 @@ class RedeclarableTemplateDecl : public TemplateDecl, EntryType *Entry, void *InsertPos); struct CommonBase { -CommonBase() : InstantiatedFromMember(nullptr, false) {} +CommonBase() {} /// The template from which this was most /// directly instantiated (or null). -/// -/// The boolean value indicates whether this template -/// was explicitly specialized. -llvm::PointerIntPair - InstantiatedFromMember; +RedeclarableTemplateDecl *InstantiatedFromMember = nullptr; /// If non-null, points to an array of specializations (including /// partial specializations) known only by their external declaration IDs. @@ -809,14 +805,19 @@ class RedeclarableTemplateDecl : public TemplateDecl, }; /// Pointer to the common data shared by all declarations of this - /// template. - mutable CommonBase *Common = nullptr; + /// template, and a flag indicating if the template is a member + /// specialization. + mutable llvm::PointerIntPair Common; + + CommonBase *getCommonPtrInternal() const { return Common.getPointer(); } /// Retrieves the "common" pointer shared by all (re-)declarations of /// the same template. Calling this routine may implicitly allocate memory /// for the common pointer. CommonBase *getCommonPtr() const; + void setCommonPtr(CommonBase *C) const { Common.setPointer(C); } + virtual CommonBase *newCommon(ASTContext &C) const = 0; // Construct a template decl with name, parameters, and templated element. @@ -857,15 +858,12 @@ class RedeclarableTemplateDecl : public TemplateDecl, /// template<> template /// struct X::Inner { /* ... */ }; /// \endcode - bool isMemberSpecialization() const { -return getCommonPtr()->InstantiatedFromMember.getInt(); - } + bool isMemberSpecialization() const { return Common.getInt(); } /// Note that this member template is a specialization. void setMemberSpecialization() { -assert(getCommonPtr()->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); -getCommonPtr()->InstantiatedFromMember.setInt(true); +assert(!isMemberSpecialization() && "already a member specialization"); +Common.setInt(true); } /// Retrieve the member template from which this template was @@ -905,12 +903,12 @@ class RedeclarableTemplateDecl : public TemplateDecl, /// void X::f(T, U); /// \endcode RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const { -return getCommonPtr()->InstantiatedFrom
[clang] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" (PR #111173)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/73 Reapplies #106585, fixing an issue where non-dependent names of member templates appearing prior to that member template being explicitly specialized for an implicitly instantiated class template specialization would incorrectly use the definition of the explicitly specialized member template. >From 14fe45b5e42f3993757f691a9f09899dcba8fb5b Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 23 Sep 2024 10:51:21 -0400 Subject: [PATCH 1/2] Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" This reverts commit 1818ca5c4ae87ed222a18177caa7c8dde6c67efa. --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/AST/DeclTemplate.h| 66 +- clang/include/clang/Sema/Sema.h | 25 +- clang/lib/AST/DeclTemplate.cpp| 30 +- clang/lib/Sema/SemaConcept.cpp| 29 +- clang/lib/Sema/SemaDecl.cpp | 31 +- clang/lib/Sema/SemaDeclCXX.cpp| 4 +- clang/lib/Sema/SemaTemplate.cpp | 179 +++-- clang/lib/Sema/SemaTemplateDeduction.cpp | 33 +- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 45 +- clang/lib/Sema/SemaTemplateInstantiate.cpp| 713 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 46 +- clang/lib/Serialization/ASTReader.cpp | 3 +- clang/lib/Serialization/ASTReaderDecl.cpp | 18 +- clang/lib/Serialization/ASTWriterDecl.cpp | 17 +- .../temp/temp.constr/temp.constr.decl/p4.cpp | 175 + 16 files changed, 763 insertions(+), 654 deletions(-) create mode 100644 clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b47e06cb0c5d68..14867a029581e9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -424,6 +424,9 @@ Bug Fixes to C++ Support - Fixed an assertion failure in debug mode, and potential crashes in release mode, when diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter. - Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326) +- Clang now uses the correct set of template argument lists when comparing the constraints of + out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of + a class template. (#GH102320) Bug Fixes to AST Handling ^ diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 687715a22e9fd3..05739f39d2a496 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -781,15 +781,11 @@ class RedeclarableTemplateDecl : public TemplateDecl, EntryType *Entry, void *InsertPos); struct CommonBase { -CommonBase() : InstantiatedFromMember(nullptr, false) {} +CommonBase() {} /// The template from which this was most /// directly instantiated (or null). -/// -/// The boolean value indicates whether this template -/// was explicitly specialized. -llvm::PointerIntPair - InstantiatedFromMember; +RedeclarableTemplateDecl *InstantiatedFromMember = nullptr; /// If non-null, points to an array of specializations (including /// partial specializations) known only by their external declaration IDs. @@ -809,14 +805,19 @@ class RedeclarableTemplateDecl : public TemplateDecl, }; /// Pointer to the common data shared by all declarations of this - /// template. - mutable CommonBase *Common = nullptr; + /// template, and a flag indicating if the template is a member + /// specialization. + mutable llvm::PointerIntPair Common; + + CommonBase *getCommonPtrInternal() const { return Common.getPointer(); } /// Retrieves the "common" pointer shared by all (re-)declarations of /// the same template. Calling this routine may implicitly allocate memory /// for the common pointer. CommonBase *getCommonPtr() const; + void setCommonPtr(CommonBase *C) const { Common.setPointer(C); } + virtual CommonBase *newCommon(ASTContext &C) const = 0; // Construct a template decl with name, parameters, and templated element. @@ -857,15 +858,12 @@ class RedeclarableTemplateDecl : public TemplateDecl, /// template<> template /// struct X::Inner { /* ... */ }; /// \endcode - bool isMemberSpecialization() const { -return getCommonPtr()->InstantiatedFromMember.getInt(); - } + bool isMemberSpecialization() const { return Common.getInt(); } /// Note that this member template is a specialization. void setMemberSpecialization() { -assert(getCommonPtr()->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); -getCommonPtr()->InstantiatedFromMem
[clang] [Clang][Sema] fix noexecpt mismatch of friend declaration (PR #102267)
@@ -4698,7 +4698,22 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. Sema::ContextRAII savedContext(*this, Decl); + + FunctionDecl *Source = Proto->getExtProtoInfo().ExceptionSpec.SourceTemplate; + FunctionTemplateDecl *SourceTemplate = Source->getDescribedFunctionTemplate(); + llvm::SmallDenseMap InstTemplateParams; + if (CurrentInstantiationScope && SourceTemplate) +if (TemplateParameterList *TPL = SourceTemplate->getTemplateParameters()) + for (NamedDecl *TemplateParam : *TPL) +if (auto *Found = +CurrentInstantiationScope->findInstantiationOf(TemplateParam)) + if (auto *InstTemplateParam = Found->dyn_cast()) +InstTemplateParams[TemplateParam] = InstTemplateParam; + sdkrystian wrote: Yeah, we should wait until I reland #106585 and then we can fix this. What we can then do is normalize the exception specification the same way we normalize constraints prior to comparing them. https://github.com/llvm/llvm-project/pull/102267 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
sdkrystian wrote: @zyn0217 I plan to reapply the patch after addressing the issues discussed above, but I have to get some more pressing work stuff done first :) https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
sdkrystian wrote: Another example using class templates: ```cpp template struct A { template struct B; }; template<> template struct A<0>::B : A<1>::B { }; template<> template struct A<1>::B { static constexpr bool x = true; }; static_assert(A<0>::B::x); // error: implicit instantiation of undefined template 'A<1>::B' ``` This currently results in a crash on trunk. With this patch applied, we instantiate the undefined class template declared in the definition of `A` and complain. These differences in behavior arise from the fact that we bind names to the most recent redeclaration of an entity when creating `Expr` nodes that refer to that entity. In the above example, the explicit specialization of `A<1>::B` is declared after it is referenced in the explicit specialization of `A<0>::B`, resulting in the initial declaration being used to instantiate `B`. IMO this behavior is correct per [[temp.expl.spec] p7](http://eel.is/c++draft/temp.expl.spec#7): > If a template, a member template or a member of a class template is > explicitly specialized, a declaration of that specialization shall be > reachable from every use of that specialization that would cause an implicit > instantiation to take place, in every translation unit in which such a use > occurs; no diagnostic is required. However, I would like to know what @erichkeane, @mizvekov, and @zygoloid think. In any case, the QT example can be fixed by reordering the explicit specialization such that each specialization is declared before being referenced. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
sdkrystian wrote: Reduced further to: ```cpp template struct A { template static constexpr bool f(); }; template<> template constexpr bool A<0>::f() { return A<1>::f(); // note: undefined function 'f' cannot be used in a constant expression } template<> template constexpr bool A<1>::f() { return true; } static_assert(A<0>::f()); // error: static assertion expression is not an integral constant expression ``` https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
sdkrystian wrote: I've manually reduced the standalone reproducer to the following: ```cpp template struct A { template static constexpr bool f(); }; template<> template constexpr bool A<0>::f() { return A<1>::f(); } template<> template constexpr bool A<1>::f() { return true; } template constexpr bool g() { return A::template f(); // note: undefined function 'f' cannot be used in a constant expression } template bool g<0>(); static_assert(g<1>()); // error: static assertion expression is not an integral constant expression ``` The error does not occur if the explicit instantiation definition (i.e. `template bool g<0>()`) is removed. I'm looking into it. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix false warning on reinterpret_casting unknown template type (PR #109430)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/109430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix false warning on reinterpret_casting unknown template type (PR #109430)
https://github.com/sdkrystian requested changes to this pull request. https://github.com/llvm/llvm-project/pull/109430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Fix false warning on reinterpret_casting unknown template type (PR #109430)
@@ -2092,6 +2092,10 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, } } + if (SrcTy->isTemplateTypeParmType() || DestTy->isTemplateTypeParmType()) { sdkrystian wrote: This should probably be`if (SrcTy->isDependentType() || DestTy->isDependentType())`. Otherwise we will continue to warn for the following: ```cpp template void f(T** x) { *reinterpret_cast(x); } ``` https://github.com/llvm/llvm-project/pull/109430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)" (PR #109422)
sdkrystian wrote: > Does this need a release note? I don't think so, since this fixes a bug introduced in the same release. > Also, can you point out the 'diff' from the previous commit? The condition of [the assert in `SemaExprCXX.cpp`](https://github.com/llvm/llvm-project/pull/109422/files#diff-1420e9cbc74252d1c2e98a97f80d3741bb4a44e8469d326ba3aa337260ee9800R8009) was changed from `BaseType->isDependentType()` to `Base->isTypeDependent()`, as was the condition on [line 1318 in `SemaExprMember.cpp`](https://github.com/llvm/llvm-project/pull/109422/files#diff-666d45282070e66014f8fb70e6c089762ea67ad4891f9819fdf5f8a5d5a0f570R1318). > I'm really not a fan of the 'out' parameter, I'd prefer perhaps returning a > `std::pair` + structured binding. WDYT? My initial solution was to return `ExprEmpty()`, but I changed to using an out parameter in response to review feedback (I don't like out parameters either). https://github.com/llvm/llvm-project/pull/109422 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)" (PR #109422)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/109422 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)" (PR #109422)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/109422 >From d1b0cad696cca10c28ba32c290bc220ee917b48d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 15 Aug 2024 11:27:34 -0400 Subject: [PATCH 1/8] Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)" --- clang/include/clang/Sema/Sema.h | 3 +-- clang/lib/Sema/SemaExprCXX.cpp| 25 --- clang/lib/Sema/SemaOverload.cpp | 14 +++ clang/lib/Sema/TreeTransform.h| 4 +-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 24 ++ 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 68c782a15c6f1b..040584f53a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10639,8 +10639,7 @@ class Sema final : public SemaBase { /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. - ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, + ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound = nullptr); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 14feafd1e6b17f..f6e09f62cd3782 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7966,18 +7966,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, QualType BaseType = Base->getType(); MayBePseudoDestructor = false; - if (BaseType->isDependentType()) { -// If we have a pointer to a dependent type and are using the -> operator, -// the object type is the type that the pointer points to. We might still -// have enough information about that type to do something useful. -if (OpKind == tok::arrow) - if (const PointerType *Ptr = BaseType->getAs()) -BaseType = Ptr->getPointeeType(); - -ObjectType = ParsedType::make(BaseType); -MayBePseudoDestructor = true; -return Base; - } // C++ [over.match.oper]p8: // [...] When operator->returns, the operator-> is applied to the value @@ -7992,7 +7980,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { if (OperatorArrows.size() >= getLangOpts().ArrowDepth) { Diag(OpLoc, diag::err_operator_arrow_depth_exceeded) << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange(); @@ -8003,7 +7991,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } Result = BuildOverloadedArrowExpr( - S, Base, OpLoc, + Base, OpLoc, // When in a template specialization and on the first loop iteration, // potentially give the default diagnostic (with the fixit in a // separate note) instead of having the error reported back to here @@ -8029,7 +8017,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. +assert(BaseType->isDependentType()); +BaseType = Context.DependentTy; +break; } + Base = Result.get(); if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) OperatorArrows.push_back(OpCall->getDirectCallee()); @@ -8067,7 +8062,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (!BaseType->isRecordType()) { + if (!BaseType->getAsRecordDecl()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 861b0a91240b3b..c09059f4c5510b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15878,10 +15878,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } -ExprResult -Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, -
[clang] Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)" (PR #109422)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/109422 Reapplies #104458, fixing a bug that occurs when a templated class declares `operator->` to return a non-dependent class type. >From d1b0cad696cca10c28ba32c290bc220ee917b48d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 15 Aug 2024 11:27:34 -0400 Subject: [PATCH 1/7] Reapply "[Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (#104458)" --- clang/include/clang/Sema/Sema.h | 3 +-- clang/lib/Sema/SemaExprCXX.cpp| 25 --- clang/lib/Sema/SemaOverload.cpp | 14 +++ clang/lib/Sema/TreeTransform.h| 4 +-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 24 ++ 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 68c782a15c6f1b..040584f53a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10639,8 +10639,7 @@ class Sema final : public SemaBase { /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. - ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, + ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound = nullptr); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 14feafd1e6b17f..f6e09f62cd3782 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7966,18 +7966,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, QualType BaseType = Base->getType(); MayBePseudoDestructor = false; - if (BaseType->isDependentType()) { -// If we have a pointer to a dependent type and are using the -> operator, -// the object type is the type that the pointer points to. We might still -// have enough information about that type to do something useful. -if (OpKind == tok::arrow) - if (const PointerType *Ptr = BaseType->getAs()) -BaseType = Ptr->getPointeeType(); - -ObjectType = ParsedType::make(BaseType); -MayBePseudoDestructor = true; -return Base; - } // C++ [over.match.oper]p8: // [...] When operator->returns, the operator-> is applied to the value @@ -7992,7 +7980,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { if (OperatorArrows.size() >= getLangOpts().ArrowDepth) { Diag(OpLoc, diag::err_operator_arrow_depth_exceeded) << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange(); @@ -8003,7 +7991,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } Result = BuildOverloadedArrowExpr( - S, Base, OpLoc, + Base, OpLoc, // When in a template specialization and on the first loop iteration, // potentially give the default diagnostic (with the fixit in a // separate note) instead of having the error reported back to here @@ -8029,7 +8017,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. +assert(BaseType->isDependentType()); +BaseType = Context.DependentTy; +break; } + Base = Result.get(); if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) OperatorArrows.push_back(OpCall->getDirectCallee()); @@ -8067,7 +8062,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (!BaseType->isRecordType()) { + if (!BaseType->getAsRecordDecl()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 861b0a91240b3b..c09059f4c5510b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15878,10 +15878,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCa
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -585,8 +585,8 @@ static bool CheckConstraintSatisfaction( ArrayRef TemplateArgs = TemplateArgsLists.getNumSubstitutedLevels() > 0 - ? TemplateArgsLists.getOutermost() - : ArrayRef {}; + ? TemplateArgsLists.getInnermost() sdkrystian wrote: Yeah, the old implementation was just wrong. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
sdkrystian wrote: @porglezomp Sorry, I'm currently at cppcon but I'll try reland it when I have a moment. https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -585,8 +585,8 @@ static bool CheckConstraintSatisfaction( ArrayRef TemplateArgs = TemplateArgsLists.getNumSubstitutedLevels() > 0 - ? TemplateArgsLists.getOutermost() - : ArrayRef {}; + ? TemplateArgsLists.getInnermost() sdkrystian wrote: The innermost template arguments are the ones that actually pertain to the template we are instantiating... the outermost arguments pertain to some unrelated containing template. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
sdkrystian wrote: Ping @erichkeane https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] fix noexecpt mismatch of friend declaration (PR #102267)
sdkrystian wrote: @ericniebler Once I merge #106585, I have a follow up patch ready that will fix #101330. https://github.com/llvm/llvm-project/pull/102267 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
sdkrystian wrote: I have a fix, so I'll reapply this sometime today. https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/104458 >From 11f67c73a8de04ce94dbed467de043668234e202 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 15 Aug 2024 11:27:34 -0400 Subject: [PATCH 1/5] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation --- clang/include/clang/Sema/Sema.h | 3 +-- clang/lib/Sema/SemaExprCXX.cpp| 25 --- clang/lib/Sema/SemaOverload.cpp | 14 +++ clang/lib/Sema/TreeTransform.h| 4 +-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 24 ++ 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 68c782a15c6f1b..040584f53a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10639,8 +10639,7 @@ class Sema final : public SemaBase { /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. - ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, + ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound = nullptr); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 14feafd1e6b17f..f6e09f62cd3782 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7966,18 +7966,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, QualType BaseType = Base->getType(); MayBePseudoDestructor = false; - if (BaseType->isDependentType()) { -// If we have a pointer to a dependent type and are using the -> operator, -// the object type is the type that the pointer points to. We might still -// have enough information about that type to do something useful. -if (OpKind == tok::arrow) - if (const PointerType *Ptr = BaseType->getAs()) -BaseType = Ptr->getPointeeType(); - -ObjectType = ParsedType::make(BaseType); -MayBePseudoDestructor = true; -return Base; - } // C++ [over.match.oper]p8: // [...] When operator->returns, the operator-> is applied to the value @@ -7992,7 +7980,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { if (OperatorArrows.size() >= getLangOpts().ArrowDepth) { Diag(OpLoc, diag::err_operator_arrow_depth_exceeded) << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange(); @@ -8003,7 +7991,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } Result = BuildOverloadedArrowExpr( - S, Base, OpLoc, + Base, OpLoc, // When in a template specialization and on the first loop iteration, // potentially give the default diagnostic (with the fixit in a // separate note) instead of having the error reported back to here @@ -8029,7 +8017,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. +assert(BaseType->isDependentType()); +BaseType = Context.DependentTy; +break; } + Base = Result.get(); if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) OperatorArrows.push_back(OpCall->getDirectCallee()); @@ -8067,7 +8062,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (!BaseType->isRecordType()) { + if (!BaseType->getAsRecordDecl()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 861b0a91240b3b..c09059f4c5510b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15878,10 +15878,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } -ExprResult -Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, - bool *NoAr
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/104458 >From 11f67c73a8de04ce94dbed467de043668234e202 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 15 Aug 2024 11:27:34 -0400 Subject: [PATCH 1/4] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation --- clang/include/clang/Sema/Sema.h | 3 +-- clang/lib/Sema/SemaExprCXX.cpp| 25 --- clang/lib/Sema/SemaOverload.cpp | 14 +++ clang/lib/Sema/TreeTransform.h| 4 +-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 24 ++ 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 68c782a15c6f1b..040584f53a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10639,8 +10639,7 @@ class Sema final : public SemaBase { /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. - ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, + ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound = nullptr); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 14feafd1e6b17f..f6e09f62cd3782 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7966,18 +7966,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, QualType BaseType = Base->getType(); MayBePseudoDestructor = false; - if (BaseType->isDependentType()) { -// If we have a pointer to a dependent type and are using the -> operator, -// the object type is the type that the pointer points to. We might still -// have enough information about that type to do something useful. -if (OpKind == tok::arrow) - if (const PointerType *Ptr = BaseType->getAs()) -BaseType = Ptr->getPointeeType(); - -ObjectType = ParsedType::make(BaseType); -MayBePseudoDestructor = true; -return Base; - } // C++ [over.match.oper]p8: // [...] When operator->returns, the operator-> is applied to the value @@ -7992,7 +7980,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { if (OperatorArrows.size() >= getLangOpts().ArrowDepth) { Diag(OpLoc, diag::err_operator_arrow_depth_exceeded) << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange(); @@ -8003,7 +7991,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } Result = BuildOverloadedArrowExpr( - S, Base, OpLoc, + Base, OpLoc, // When in a template specialization and on the first loop iteration, // potentially give the default diagnostic (with the fixit in a // separate note) instead of having the error reported back to here @@ -8029,7 +8017,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. +assert(BaseType->isDependentType()); +BaseType = Context.DependentTy; +break; } + Base = Result.get(); if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) OperatorArrows.push_back(OpCall->getDirectCallee()); @@ -8067,7 +8062,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (!BaseType->isRecordType()) { + if (!BaseType->getAsRecordDecl()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 861b0a91240b3b..c09059f4c5510b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15878,10 +15878,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } -ExprResult -Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, - bool *NoAr
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
@@ -7981,7 +7969,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { sdkrystian wrote: Perhaps it would be worth introducing `Type::isCXXRecord` for this check. We do it quite often... @cor3ntin WDYT? https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
@@ -7981,7 +7969,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { sdkrystian wrote: It's essentially a shortcut for `BaseType->isRecordType() || isa(BaseType->getCanonicalTypeInternal())` https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/104458 >From a719de89be6af3607f67baddd8868f8e0fc7882f Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 15 Aug 2024 11:27:34 -0400 Subject: [PATCH 1/3] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation --- clang/include/clang/Sema/Sema.h | 3 +-- clang/lib/Sema/SemaExprCXX.cpp| 25 --- clang/lib/Sema/SemaOverload.cpp | 14 +++ clang/lib/Sema/TreeTransform.h| 4 +-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 24 ++ 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0358259945c796..023b99db41db42 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10639,8 +10639,7 @@ class Sema final : public SemaBase { /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. - ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, + ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound = nullptr); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index b7531581d37ff0..45c0d0e22d9605 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7955,18 +7955,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, QualType BaseType = Base->getType(); MayBePseudoDestructor = false; - if (BaseType->isDependentType()) { -// If we have a pointer to a dependent type and are using the -> operator, -// the object type is the type that the pointer points to. We might still -// have enough information about that type to do something useful. -if (OpKind == tok::arrow) - if (const PointerType *Ptr = BaseType->getAs()) -BaseType = Ptr->getPointeeType(); - -ObjectType = ParsedType::make(BaseType); -MayBePseudoDestructor = true; -return Base; - } // C++ [over.match.oper]p8: // [...] When operator->returns, the operator-> is applied to the value @@ -7981,7 +7969,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { if (OperatorArrows.size() >= getLangOpts().ArrowDepth) { Diag(OpLoc, diag::err_operator_arrow_depth_exceeded) << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange(); @@ -7992,7 +7980,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } Result = BuildOverloadedArrowExpr( - S, Base, OpLoc, + Base, OpLoc, // When in a template specialization and on the first loop iteration, // potentially give the default diagnostic (with the fixit in a // separate note) instead of having the error reported back to here @@ -8018,7 +8006,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. +assert(BaseType->isDependentType()); +BaseType = Context.DependentTy; +break; } + Base = Result.get(); if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) OperatorArrows.push_back(OpCall->getDirectCallee()); @@ -8056,7 +8051,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (!BaseType->isRecordType()) { + if (!BaseType->getAsRecordDecl()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 95551173df91a5..6170ae579fd2a0 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15876,10 +15876,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } -ExprResult -Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, - bool *NoAr
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
@@ -7939,7 +7927,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. sdkrystian wrote: @cor3ntin Pushed changes that do what you described https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
@@ -7939,7 +7927,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. sdkrystian wrote: > I have 2 concerns with that > 1/ It's a bit too clever of an interface Although I agree it's an imperfect interface, this is more of a "transitional" fix. Ideally we will build the full AST for calls to members of the current instantiation in the future. For now, the usage of `ExprEmpty` in this patch isn't unfounded so I think it's "good enough". Alternatively I can add a `bool& IsDependent` out parameter to implement this functionality. > 2/ We should make sure this can only happens in Sema, right? I wonder if we > need an ActOnOverloadedArrowExpr to wrap that logic such that (it would > duplicate the lookup code but i think that's a better outcome) I'm not entirely sure what this means. Are you saying that we should expect the result to _not_ be `ExprEmpty` during instantiation? https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
sdkrystian wrote: @cor3ntin Excellent, then I think this is good to go https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
sdkrystian wrote: Ping @mizvekov https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
sdkrystian wrote: @cor3ntin After giving it another look, I think the existing tests are sufficient (the tests updated by this PR were written by me to test this exact scenario). WDYT? https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -2112,6 +2078,33 @@ DeclResult Sema::CheckClassTemplate( NewClass->setLexicalDeclContext(CurContext); NewTemplate->setLexicalDeclContext(CurContext); + // Ensure that the template parameter lists are compatible. Skip this check + // for a friend in a dependent context: the template parameter list itself + // could be dependent. + if (ShouldAddRedecl && PrevClassTemplate && + !TemplateParameterListsAreEqual( + NewTemplate, TemplateParams, PrevClassTemplate, + PrevClassTemplate->getTemplateParameters(), + /*Complain=*/true, TPL_TemplateMatch)) +return true; + + // Check the template parameter list of this declaration, possibly + // merging in the template parameter list from the previous class + // template declaration. Skip this check for a friend in a dependent + // context, because the template parameter list might be dependent. + if (ShouldAddRedecl && + CheckTemplateParameterList( + TemplateParams, + PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() +: nullptr, + (SS.isSet() && SemanticContext && SemanticContext->isRecord() && + SemanticContext->isDependentContext()) + ? TPC_ClassTemplateMember + : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate + : TPC_ClassTemplate, + SkipBody)) sdkrystian wrote: @zyn0217 Since this is existing code which I moved, I would prefer to keep it as-is and perhaps address this in some future NFC patch. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -33,11 +33,12 @@ class D{}; // expected-note{{previous definition is here}} template class D{}; // 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 'D'}} -template requires C1 // expected-note{{previous template declaration is here}} -class E{}; +template requires C1 +class E{}; // expected-note{{previous definition is here}} -template // expected-error{{requires clause differs in template redeclaration}} +template sdkrystian wrote: I can move the point at which we emit the redefinition error to be after the check for equivalent _template-heads_, if you'd like. Then we would get the "requires clause differs in template redeclaration" error instead. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
sdkrystian wrote: > Also, do you plan to fix #102320 in this or the follow-up patches? @zyn0217 This patch (in its current state) fixes #102320 :) https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -1669,25 +1640,43 @@ namespace { ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, LambdaScopeInfo *LSI) { +#if 1 CXXMethodDecl *MD = LSI->CallOperator; - for (ParmVarDecl *PVD : MD->parameters()) { -assert(PVD && "null in a parameter list"); -if (!PVD->hasDefaultArg()) - continue; -Expr *UninstExpr = PVD->getUninstantiatedDefaultArg(); -// FIXME: Obtain the source location for the '=' token. -SourceLocation EqualLoc = UninstExpr->getBeginLoc(); -if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) { - // If substitution fails, the default argument is set to a - // RecoveryExpr that wraps the uninstantiated default argument so - // that downstream diagnostics are omitted. - ExprResult ErrorResult = SemaRef.CreateRecoveryExpr( - UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), - { UninstExpr }, UninstExpr->getType()); - if (ErrorResult.isUsable()) -PVD->setDefaultArg(ErrorResult.get()); + // if (MD->getParentFunctionOrMethod()) { + if (true) { +#if 0 +NamedDecl *Pattern = MD; + std::optional> Innermost; +if (FunctionTemplateDecl *FTD = MD->getDescribedFunctionTemplate()) { + Pattern = FTD; + Innermost = FTD->getInjectedTemplateArgs(); +} +MultiLevelTemplateArgumentList MLTAL = +SemaRef.getTemplateInstantiationArgs(Pattern, Pattern->getLexicalDeclContext(), + /*Final=*/false, Innermost, + /*RelativeToPrimary=*/true); +#endif +; sdkrystian wrote: This is leftover from when I was experimenting with correctly substituting lambda default arguments. It proved to be too much work, so I abandoned that effort. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -171,374 +139,379 @@ bool isLambdaEnclosedByTypeAliasDecl( .TraverseType(Underlying); } -// Add template arguments from a variable template instantiation. -Response -HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec, - MultiLevelTemplateArgumentList &Result, - bool SkipForSpecialization) { - // For a class-scope explicit specialization, there are no template arguments - // at this level, but there may be enclosing template arguments. - if (VarTemplSpec->isClassScopeExplicitSpecialization()) -return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec); - - // We're done when we hit an explicit specialization. - if (VarTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization && - !isa(VarTemplSpec)) -return Response::Done(); - - // If this variable template specialization was instantiated from a - // specialized member that is a variable template, we're done. - assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?"); - llvm::PointerUnion - Specialized = VarTemplSpec->getSpecializedTemplateOrPartial(); - if (VarTemplatePartialSpecializationDecl *Partial = - Specialized.dyn_cast()) { -if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); -if (Partial->isMemberSpecialization()) - return Response::Done(); - } else { -VarTemplateDecl *Tmpl = Specialized.get(); -if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); -if (Tmpl->isMemberSpecialization()) - return Response::Done(); +struct TemplateInstantiationArgumentCollecter +: DeclVisitor { + Sema &S; + MultiLevelTemplateArgumentList &Result; + std::optional> Innermost; + bool RelativeToPrimary; + bool ForConstraintInstantiation; + + TemplateInstantiationArgumentCollecter( + Sema &S, MultiLevelTemplateArgumentList &Result, + std::optional> Innermost, + bool RelativeToPrimary, bool ForConstraintInstantiation) + : S(S), Result(Result), Innermost(Innermost), +RelativeToPrimary(RelativeToPrimary), +ForConstraintInstantiation(ForConstraintInstantiation) {} + + Decl *Done() { return nullptr; } + + Decl *ChangeDecl(const Decl *D) { +RelativeToPrimary = false; +return const_cast(D); } - return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec); -} -// If we have a template template parameter with translation unit context, -// then we're performing substitution into a default template argument of -// this template template parameter before we've constructed the template -// that will own this template template parameter. In this case, we -// use empty template parameter lists for all of the outer templates -// to avoid performing any substitutions. -Response -HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP, - MultiLevelTemplateArgumentList &Result) { - for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I) -Result.addOuterTemplateArguments(std::nullopt); - return Response::Done(); -} + Decl *ChangeDecl(const DeclContext *DC) { +return ChangeDecl(Decl::castFromDeclContext(DC)); + } -Response HandlePartialClassTemplateSpec( -const ClassTemplatePartialSpecializationDecl *PartialClassTemplSpec, -MultiLevelTemplateArgumentList &Result, bool SkipForSpecialization) { - if (!SkipForSpecialization) - Result.addOuterRetainedLevels(PartialClassTemplSpec->getTemplateDepth()); - return Response::Done(); -} + Decl *UseNextDecl(const Decl *D) { return ChangeDecl(D->getDeclContext()); } -// Add template arguments from a class template instantiation. -Response -HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec, -MultiLevelTemplateArgumentList &Result, -bool SkipForSpecialization) { - if (!ClassTemplSpec->isClassScopeExplicitSpecialization()) { -// We're done when we hit an explicit specialization. -if (ClassTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization && -!isa(ClassTemplSpec)) - return Response::Done(); + Decl *DontClearRelativeToPrimaryNextDecl(const Decl *D) { +return const_cast(Decl::castFromDeclContext(D->getDeclContext())); + } -if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - const_cast(ClassTemplSpec), - ClassTemplSpec->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + void AddInnermostTemplateArguments(const Decl *D) { +assert(Innermost); +Result.addOuterTemplateArguments(const_cast(D), *Innermost, + /*Final=*/false); +Innermost.reset(); + } -
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -1056,16 +1052,20 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { assert(FD->getFriendObjectKind() && "Must be a friend!"); + FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate(); // The logic for non-templates is handled in ASTContext::isSameEntity, so we // don't have to bother checking 'DependsOnEnclosingTemplate' for a // non-function-template. - assert(FD->getDescribedFunctionTemplate() && - "Non-function templates don't need to be checked"); + assert(FTD && "Non-function templates don't need to be checked"); SmallVector ACs; - FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); + FTD->getAssociatedConstraints(ACs); +#if 0 sdkrystian wrote: Yup. There are still a few others I need to clean up https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -317,7 +317,8 @@ struct ConvertConstructorToDeductionGuideTransform { } if (NestedPattern) - OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template); + OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs( + /*D=*/nullptr, Template->getDeclContext()); sdkrystian wrote: This is an artifact from when I was figuring out the implementation... I'll revert this change. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Refactor collection of multi-level template argument lists (PR #106585)
@@ -809,8 +809,9 @@ class RedeclarableTemplateDecl : public TemplateDecl, }; /// Pointer to the common data shared by all declarations of this - /// template. - mutable CommonBase *Common = nullptr; + /// template, and a flag indicating if the template is a member + /// specialization. + mutable llvm::PointerIntPair Common; sdkrystian wrote: > Do you think it is more appropriate to move the flag to > `Common->InstantiatedFromMember`? That way the flag won't be scattered, right? I moved the flag here because we want to set the flag before we know whether it is a redeclaration. https://github.com/llvm/llvm-project/pull/106585 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
sdkrystian wrote: @cor3ntin What's the deadline? https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
sdkrystian wrote: > Can you please add more details in your summary about the problem and how the > PR will fix the problem. @shafik I will once I get back to this PR. > @sdkrystian do you plan to add more tests? @cor3ntin I do, I just haven't gotten around to it yet :) https://github.com/llvm/llvm-project/pull/104458 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Rebuild template parameters for out-of-line template definitions and partial specializations (PR #104030)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/104030 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Rebuild template parameters for out-of-line template definitions and partial specializations (PR #104030)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/104030 >From 14db4ba124a36ea778515fe0228ae959081f6d65 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 14 Aug 2024 09:00:30 -0400 Subject: [PATCH 1/3] [Clang][Sema] Rebuild template parameters for out-of-line template definitions and partial specializations --- clang/lib/Sema/SemaDecl.cpp | 6 + clang/lib/Sema/SemaTemplate.cpp | 20 ++-- .../test/CXX/temp/temp.decls/temp.mem/p1.cpp | 112 +- 3 files changed, 129 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 503e93f9257137..b0ccbbe34b70c3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7502,6 +7502,12 @@ NamedDecl *Sema::ActOnVariableDeclarator( /*never a friend*/ false, IsMemberSpecialization, Invalid); if (TemplateParams) { + if (DC->isDependentContext()) { +ContextRAII SavedContext(*this, DC); +if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + Invalid = true; + } + if (!TemplateParams->size() && D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) { // There is an extraneous 'template<>' for this variable. Complain diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 992565701d40ca..f8f41d0bafffc3 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8089,13 +8089,14 @@ DeclResult Sema::ActOnClassTemplateSpecialization( return true; } + DeclContext *DC = ClassTemplate->getDeclContext(); + bool isMemberSpecialization = false; bool isPartialSpecialization = false; if (SS.isSet()) { if (TUK != TagUseKind::Reference && TUK != TagUseKind::Friend && -diagnoseQualifiedDeclaration(SS, ClassTemplate->getDeclContext(), - ClassTemplate->getDeclName(), +diagnoseQualifiedDeclaration(SS, DC, ClassTemplate->getDeclName(), TemplateNameLoc, &TemplateId, /*IsMemberSpecialization=*/false)) return true; @@ -8117,6 +8118,12 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (TemplateParams && CheckTemplateDeclScope(S, TemplateParams)) return true; + if (TemplateParams && DC->isDependentContext()) { +ContextRAII SavedContext(*this, DC); +if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + return true; + } + if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; @@ -8282,9 +8289,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( = cast_or_null(PrevDecl); ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create( -Context, Kind, ClassTemplate->getDeclContext(), KWLoc, -TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted, -CanonType, PrevPartial); +Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams, +ClassTemplate, CanonicalConverted, CanonType, PrevPartial); Partial->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { @@ -8306,8 +8312,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Create a new class template specialization declaration node for // this explicit specialization or friend declaration. Specialization = ClassTemplateSpecializationDecl::Create( -Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, -ClassTemplate, CanonicalConverted, PrevDecl); +Context, Kind, DC, KWLoc, TemplateNameLoc, ClassTemplate, +CanonicalConverted, PrevDecl); Specialization->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Specialization, SS); if (TemplateParameterLists.size() > 0) { diff --git a/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp index b48e145e1468db..64b1274419e35d 100644 --- a/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s template struct A { static T cond; @@ -35,3 +34,112 @@ namespace PR6376 { Z z0; } + +namespace OutOfLine { + template + struct A { +struct B { }; + +template +void f(); + +template +void g() { } // expected-note {{previous definition is here}} + +template +static int x; + +template +static int x; + +template +static constexpr int x = 0; // expected-note {{previous definition is here}} + +template +struct C; + +template +struct C; + +templ
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
sdkrystian wrote: @cor3ntin This wouldn't fix [the case that abseil users complained about](https://github.com/llvm/llvm-project/pull/98547#issuecomment-2224998395) (example reduced from [the source](https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/compressed_tuple.h#L256)): ```cpp template class CompressedTuple : private internal_compressed_tuple::CompressedTupleImpl< CompressedTuple, absl::index_sequence_for, internal_compressed_tuple::ShouldAnyUseBase()> { template using StorageT = internal_compressed_tuple::Storage, I>; public: template constexpr ElemT&& get() && { return std::move(*this).StorageT::get(); } }; ``` Moreover, this fails to address cases where the base class declares a non-static data member with the same name as the class template: ```cpp template struct A { int A; }; template struct B : A { bool f() { return this->A < 1; // '<' would be interpreted as the start of a template argument list } }; ``` I think that implementing CWG1835's resolution as it stands is our best option. Doing so results in the most consistent behavior (e.g. 'use template when the object expression is dependent'), the most obvious fixes to achieve the intended interpretation (i.e. 'add `template` prior to the intended template name' [as opposed to surrounding the class member access expression in parentheses]). Given that we can now identify _almost_ all cases where `template` is missing with this patch and issue a warning, and that these cases wouldn't be resolved by any of the proposed compromises, I think our best option is to simply implement the resolution with enhanced recovery/ https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
sdkrystian wrote: CWG reviewed [CWG2920](https://cplusplus.github.io/CWG/issues/2920.html) during the 08-16 teleconference: > The resolution for [issue > 1835](https://cplusplus.github.io/CWG/issues/1835.html) in P1787 has > addressed real concerns. CWG recognizes that real-world code now no longer > compiles, although the fix for the affected source code is trivial. A limited > exception to support some of the existing code might be feasible. CWG > solicits a paper with specification and analysis. [The meeting minutes](https://wiki.edg.com/bin/view/Wg21telecons2024/Teleconference2024-08-16#CWG2920) portray a general feeling of apathy from CWG for code broken by the resolution. With the enhanced detection and recovery from missing `template` keywords implemented in this PR (see [my comment](https://github.com/llvm/llvm-project/pull/100425#issuecomment-2258973782) for examples; all cases reported by users are addressed), I feel that we can go ahead with relanding this patch. WDYT @AaronBallman, @cor3ntin, and @mizvekov? https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/104458 >From 9f4fb3fb8df6d0981723ce9b8da809d9f2284348 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 15 Aug 2024 11:27:34 -0400 Subject: [PATCH 1/2] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation --- clang/include/clang/Sema/Sema.h | 3 +-- clang/lib/Sema/SemaExprCXX.cpp| 25 --- clang/lib/Sema/SemaOverload.cpp | 14 +++ clang/lib/Sema/TreeTransform.h| 4 +-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 24 ++ 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 25cb6c8fbf6104..b9c5c5e4b92ed9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10616,8 +10616,7 @@ class Sema final : public SemaBase { /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. - ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, + ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound = nullptr); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 124435330ca104..d33d635ff76c5b 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7876,18 +7876,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, QualType BaseType = Base->getType(); MayBePseudoDestructor = false; - if (BaseType->isDependentType()) { -// If we have a pointer to a dependent type and are using the -> operator, -// the object type is the type that the pointer points to. We might still -// have enough information about that type to do something useful. -if (OpKind == tok::arrow) - if (const PointerType *Ptr = BaseType->getAs()) -BaseType = Ptr->getPointeeType(); - -ObjectType = ParsedType::make(BaseType); -MayBePseudoDestructor = true; -return Base; - } // C++ [over.match.oper]p8: // [...] When operator->returns, the operator-> is applied to the value @@ -7902,7 +7890,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { if (OperatorArrows.size() >= getLangOpts().ArrowDepth) { Diag(OpLoc, diag::err_operator_arrow_depth_exceeded) << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange(); @@ -7913,7 +7901,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } Result = BuildOverloadedArrowExpr( - S, Base, OpLoc, + Base, OpLoc, // When in a template specialization and on the first loop iteration, // potentially give the default diagnostic (with the fixit in a // separate note) instead of having the error reported back to here @@ -7939,7 +7927,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. +assert(BaseType->isDependentType()); +BaseType = Context.DependentTy; +break; } + Base = Result.get(); if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) OperatorArrows.push_back(OpCall->getDirectCallee()); @@ -7977,7 +7972,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (!BaseType->isRecordType()) { + if (!BaseType->getAsRecordDecl()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 52f640eb96b73b..4340181f316560 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15864,10 +15864,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } -ExprResult -Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, - bool *NoAr
[clang] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation (PR #104458)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/104458 Fixes #104268. Still need tests. >From 9f4fb3fb8df6d0981723ce9b8da809d9f2284348 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 15 Aug 2024 11:27:34 -0400 Subject: [PATCH] [Clang][Sema] Use the correct lookup context when building overloaded 'operator->' in the current instantiation --- clang/include/clang/Sema/Sema.h | 3 +-- clang/lib/Sema/SemaExprCXX.cpp| 25 --- clang/lib/Sema/SemaOverload.cpp | 14 +++ clang/lib/Sema/TreeTransform.h| 4 +-- .../temp.res/temp.dep/temp.dep.type/p4.cpp| 24 ++ 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 25cb6c8fbf6104..b9c5c5e4b92ed9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10616,8 +10616,7 @@ class Sema final : public SemaBase { /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> /// (if one exists), where @c Base is an expression of class type and /// @c Member is the name of the member we're trying to find. - ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, + ExprResult BuildOverloadedArrowExpr(Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound = nullptr); ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 124435330ca104..d33d635ff76c5b 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7876,18 +7876,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, QualType BaseType = Base->getType(); MayBePseudoDestructor = false; - if (BaseType->isDependentType()) { -// If we have a pointer to a dependent type and are using the -> operator, -// the object type is the type that the pointer points to. We might still -// have enough information about that type to do something useful. -if (OpKind == tok::arrow) - if (const PointerType *Ptr = BaseType->getAs()) -BaseType = Ptr->getPointeeType(); - -ObjectType = ParsedType::make(BaseType); -MayBePseudoDestructor = true; -return Base; - } // C++ [over.match.oper]p8: // [...] When operator->returns, the operator-> is applied to the value @@ -7902,7 +7890,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SmallVector OperatorArrows; CTypes.insert(Context.getCanonicalType(BaseType)); -while (BaseType->isRecordType()) { +while (BaseType->getAsRecordDecl()) { if (OperatorArrows.size() >= getLangOpts().ArrowDepth) { Diag(OpLoc, diag::err_operator_arrow_depth_exceeded) << StartingType << getLangOpts().ArrowDepth << Base->getSourceRange(); @@ -7913,7 +7901,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } Result = BuildOverloadedArrowExpr( - S, Base, OpLoc, + Base, OpLoc, // When in a template specialization and on the first loop iteration, // potentially give the default diagnostic (with the fixit in a // separate note) instead of having the error reported back to here @@ -7939,7 +7927,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, } } return ExprError(); + } else if (Result.isUnset()) { +// BuildOverloadedArrowExpr returns an empty expression to indicate +// that we need to build a dependent overloaded arrow expression. +assert(BaseType->isDependentType()); +BaseType = Context.DependentTy; +break; } + Base = Result.get(); if (CXXOperatorCallExpr *OpCall = dyn_cast(Base)) OperatorArrows.push_back(OpCall->getDirectCallee()); @@ -7977,7 +7972,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (!BaseType->isRecordType()) { + if (!BaseType->getAsRecordDecl()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 52f640eb96b73b..4340181f316560 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15864,10 +15864,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } -ExprResult -Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, -
[clang] [Clang][Sema] Rebuild template parameters for out-of-line template definitions and partial specializations (PR #104030)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/104030 We need to rebuild the template parameters of out-of-line definitions/specializations of member templates in the context of the current instantiation for the purposes of declaration matching. We already do this for function templates and class templates, but not variable templates, partial specializations of variable template, and partial specializations of class templates. This patch fixes the latter cases. >From 0b99f8d40fa3e74021e496dfa5000fa51d972704 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 14 Aug 2024 09:00:30 -0400 Subject: [PATCH] [Clang][Sema] Rebuild template parameters for out-of-line template definitions and partial specializations --- clang/lib/Sema/SemaDecl.cpp | 6 + clang/lib/Sema/SemaTemplate.cpp | 20 ++-- .../test/CXX/temp/temp.decls/temp.mem/p1.cpp | 112 +- 3 files changed, 129 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 641b180527da55..4490aed2645951 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7490,6 +7490,12 @@ NamedDecl *Sema::ActOnVariableDeclarator( /*never a friend*/ false, IsMemberSpecialization, Invalid); if (TemplateParams) { + if (DC->isDependentContext()) { +ContextRAII SavedContext(*this, DC); +if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + Invalid = true; + } + if (!TemplateParams->size() && D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) { // There is an extraneous 'template<>' for this variable. Complain diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 29e7978ba5b1f8..78aea38cd35216 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8086,13 +8086,14 @@ DeclResult Sema::ActOnClassTemplateSpecialization( return true; } + DeclContext *DC = ClassTemplate->getDeclContext(); + bool isMemberSpecialization = false; bool isPartialSpecialization = false; if (SS.isSet()) { if (TUK != TagUseKind::Reference && TUK != TagUseKind::Friend && -diagnoseQualifiedDeclaration(SS, ClassTemplate->getDeclContext(), - ClassTemplate->getDeclName(), +diagnoseQualifiedDeclaration(SS, DC, ClassTemplate->getDeclName(), TemplateNameLoc, &TemplateId, /*IsMemberSpecialization=*/false)) return true; @@ -8114,6 +8115,12 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (TemplateParams && CheckTemplateDeclScope(S, TemplateParams)) return true; + if (TemplateParams && DC->isDependentContext()) { +ContextRAII SavedContext(*this, DC); +if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + return true; + } + if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; @@ -8279,9 +8286,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( = cast_or_null(PrevDecl); ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create( -Context, Kind, ClassTemplate->getDeclContext(), KWLoc, -TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted, -CanonType, PrevPartial); +Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams, +ClassTemplate, CanonicalConverted, CanonType, PrevPartial); Partial->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { @@ -8303,8 +8309,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Create a new class template specialization declaration node for // this explicit specialization or friend declaration. Specialization = ClassTemplateSpecializationDecl::Create( -Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, -ClassTemplate, CanonicalConverted, PrevDecl); +Context, Kind, DC, KWLoc, TemplateNameLoc, ClassTemplate, +CanonicalConverted, PrevDecl); Specialization->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Specialization, SS); if (TemplateParameterLists.size() > 0) { diff --git a/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp index b48e145e1468db..64b1274419e35d 100644 --- a/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s template struct A { static T cond; @@ -35,3 +34,112 @@ namespace PR6376 { Z z0; } + +namespace
[clang] [Clang][Sema] fix noexecpt mismatch of friend declaration (PR #102267)
sdkrystian wrote: I don't think this is the right approach. What I think we _should_ be doing is to compare the operands of the _noexcept-specifier_ the same way we compare constraints (i.e. substitute so all references to template parameters have the correct depth and _then_ check whether the substituted expressions are equivalent). WDYT @mizvekov? https://github.com/llvm/llvm-project/pull/102267 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AST][NFC] Store template parameter position for TemplateTypeParmType in TypeBit (PR #102481)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/102481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AST][NFC] Store template parameter position for TemplateTypeParmType in TypeBit (PR #102481)
sdkrystian wrote: @mizvekov [llvm-compile-time-tracker](https://llvm-compile-time-tracker.com/compare.php?from=3e3ea54aada44212b4e273f2fc879a419dea053f&to=77585f02c39d182e6aef60856ec6816d28ce0888&stat=instructions:u) reports a 0.07% improvement in userspace instruction retired. Not bad :). https://github.com/llvm/llvm-project/pull/102481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AST][NFC] Store template parameter position for TemplateTypeParmType in TypeBit (PR #102481)
@@ -6131,52 +6149,30 @@ class BTFTagAttributedType : public Type, public llvm::FoldingSetNode { class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these - // Helper data collector for canonical types. - struct CanonicalTTPTInfo { -unsigned Depth : 15; -unsigned ParameterPack : 1; -unsigned Index : 16; - }; - - union { -// Info for the canonical type. -CanonicalTTPTInfo CanTTPTInfo; - -// Info for the non-canonical type. -TemplateTypeParmDecl *TTPDecl; - }; + // The associated TemplateTypeParmDecl for the non-canonical type. + TemplateTypeParmDecl *TTPDecl; sdkrystian wrote: There are a few other cases where we can tail allocate data for types... I think I'll submit a patch that tail allocates members for a few other `Type` derived classes. https://github.com/llvm/llvm-project/pull/102481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AST][NFC] Store template parameter position for TemplateTypeParmType in TypeBit (PR #102481)
sdkrystian wrote: > LGTM > > Are there any performance numbers worth mentioning? I haven't checked... I'll check with llvm-compile-time-tracker. https://github.com/llvm/llvm-project/pull/102481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AST][NFC] Store template parameter position for TemplateTypeParmType in TypeBit (PR #102481)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/102481 `TemplateTypeParmType` currently stores the depth, index, and whether a template type parameter is a pack in a union of `CanonicalTTPTInfo` and `TemplateTypeParmDecl*`, and only the canonical type stores the position information. These bits can be stored for all `TemplateTypeParmTypes` in `TypeBits` to avoid unnecessary indirection when accessing the position information. >From 77585f02c39d182e6aef60856ec6816d28ce0888 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 8 Aug 2024 10:36:52 -0400 Subject: [PATCH] [Clang][AST][NFC] Store template parameter position for TemplateTypeParmType in TypeBits --- clang/include/clang/AST/Type.h | 72 -- clang/lib/AST/ASTContext.cpp | 6 +-- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 0c886526c61ce..03832cf56dd06 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2134,6 +2134,23 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { unsigned hasTypeDifferentFromDecl : 1; }; + class TemplateTypeParmTypeBitfields { +friend class TemplateTypeParmType; + +LLVM_PREFERRED_TYPE(TypeBitfields) +unsigned : NumTypeBits; + +/// The depth of the template parameter. +unsigned Depth : 15; + +/// Whether this is a template parameter pack. +LLVM_PREFERRED_TYPE(bool) +unsigned ParameterPack : 1; + +/// The index of the template parameter. +unsigned Index : 16; + }; + class SubstTemplateTypeParmTypeBitfields { friend class SubstTemplateTypeParmType; @@ -2257,6 +2274,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { TypeWithKeywordBitfields TypeWithKeywordBits; ElaboratedTypeBitfields ElaboratedTypeBits; VectorTypeBitfields VectorTypeBits; +TemplateTypeParmTypeBitfields TemplateTypeParmTypeBits; SubstTemplateTypeParmTypeBitfields SubstTemplateTypeParmTypeBits; SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits; TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits; @@ -6131,52 +6149,30 @@ class BTFTagAttributedType : public Type, public llvm::FoldingSetNode { class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these - // Helper data collector for canonical types. - struct CanonicalTTPTInfo { -unsigned Depth : 15; -unsigned ParameterPack : 1; -unsigned Index : 16; - }; - - union { -// Info for the canonical type. -CanonicalTTPTInfo CanTTPTInfo; - -// Info for the non-canonical type. -TemplateTypeParmDecl *TTPDecl; - }; + // The associated TemplateTypeParmDecl for the non-canonical type. + TemplateTypeParmDecl *TTPDecl; - /// Build a non-canonical type. - TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) + TemplateTypeParmType(unsigned D, unsigned I, bool PP, + TemplateTypeParmDecl *TTPDecl, QualType Canon) : Type(TemplateTypeParm, Canon, TypeDependence::DependentInstantiation | - (Canon->getDependence() & TypeDependence::UnexpandedPack)), -TTPDecl(TTPDecl) {} - - /// Build the canonical type. - TemplateTypeParmType(unsigned D, unsigned I, bool PP) - : Type(TemplateTypeParm, QualType(this, 0), - TypeDependence::DependentInstantiation | - (PP ? TypeDependence::UnexpandedPack : TypeDependence::None)) { -CanTTPTInfo.Depth = D; -CanTTPTInfo.Index = I; -CanTTPTInfo.ParameterPack = PP; - } - - const CanonicalTTPTInfo& getCanTTPTInfo() const { -QualType Can = getCanonicalTypeInternal(); -return Can->castAs()->CanTTPTInfo; + (PP ? TypeDependence::UnexpandedPack : TypeDependence::None)), +TTPDecl(TTPDecl) { +assert(!TTPDecl == Canon.isNull()); +TemplateTypeParmTypeBits.Depth = D; +TemplateTypeParmTypeBits.Index = I; +TemplateTypeParmTypeBits.ParameterPack = PP; } public: - unsigned getDepth() const { return getCanTTPTInfo().Depth; } - unsigned getIndex() const { return getCanTTPTInfo().Index; } - bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; } - - TemplateTypeParmDecl *getDecl() const { -return isCanonicalUnqualified() ? nullptr : TTPDecl; + unsigned getDepth() const { return TemplateTypeParmTypeBits.Depth; } + unsigned getIndex() const { return TemplateTypeParmTypeBits.Index; } + bool isParameterPack() const { +return TemplateTypeParmTypeBits.ParameterPack; } + TemplateTypeParmDecl *getDecl() const { return TTPDecl; } + IdentifierInfo *getIdentifier() const; bool isSugared() const { return false; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 995d01734eea0..c55d28b506887 100644 ---
[clang] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (PR #100392)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/100392 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (PR #100392)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/100392 >From 2721a3142f4cf7e22eec27f8c209a2a4e8f98519 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 24 Jul 2024 10:15:47 -0400 Subject: [PATCH 1/3] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent --- clang/include/clang/AST/ExprCXX.h | 7 --- clang/lib/AST/ASTImporter.cpp | 5 +++-- clang/lib/AST/ExprCXX.cpp | 19 +++ clang/lib/Sema/SemaCoroutine.cpp | 3 ++- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp| 2 +- clang/lib/Sema/SemaExpr.cpp | 2 +- clang/lib/Sema/SemaExprMember.cpp | 3 ++- clang/lib/Sema/SemaOpenMP.cpp | 6 -- clang/lib/Sema/SemaOverload.cpp | 6 +++--- clang/lib/Sema/SemaTemplate.cpp | 3 ++- clang/lib/Sema/TreeTransform.h| 8 12 files changed, 38 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index f86f1818110e6..847a6ea408e98 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -3229,7 +3229,7 @@ class UnresolvedLookupExpr final const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, bool HasTemplateKWAndArgsInfo); @@ -3248,7 +3248,7 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); // After canonicalization, there may be dependent template arguments in // CanonicalConverted But none of Args is dependent. When any of @@ -3258,7 +3258,8 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, bool KnownDependent); + UnresolvedSetIterator End, bool KnownDependent, + bool KnownInstantiationDependent); static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, unsigned NumResults, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c835b7241ce09..83d8cd73f2cfa 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8633,13 +8633,14 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, -ToDecls.begin(), ToDecls.end(), KnownDependent); +ToDecls.begin(), ToDecls.end(), KnownDependent, +E->isInstantiationDependent()); } return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(), - /*KnownDependent=*/E->isTypeDependent()); + /*KnownDependent=*/E->isTypeDependent(), E->isInstantiationDependent()); } ExpectedStmt diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 6212989e21737..83ce404add5f5 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -402,10 +402,11 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, -UnresolvedSetIterator End, bool KnownDependent) +UnresolvedSetIterator End, bool KnownDependent, +bool KnownInstantiationDependent) : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, - KnownDependent, false, false), + KnownDependent, KnownInstantiationDependent, false), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; } @@ -420,7 +421,7 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, -bool KnownDepende
[clang] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others (PR #101721)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/101721 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others (PR #101721)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/101721 >From dd1c7b5fe3e1c4bca73cc5b4162ae73c3d7783fb Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 2 Aug 2024 11:32:49 -0400 Subject: [PATCH 1/5] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others --- clang/lib/Sema/SemaTemplate.cpp | 80 +++-- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1346a4a3f0012..c96925ba73ae2 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -9062,51 +9062,83 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { if (Previous.empty()) { // Nowhere to look anyway. } else if (FunctionDecl *Function = dyn_cast(Member)) { -SmallVector Candidates; -bool Ambiguous = false; -for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); - I != E; ++I) { - CXXMethodDecl *Method = - dyn_cast((*I)->getUnderlyingDecl()); - if (!Method) +LookupResult::Filter Filter = Previous.makeFilter(); +while (Filter.hasNext()) { + auto *Method = + dyn_cast(Filter.next()->getUnderlyingDecl()); + // Discard any candidates that aren't member functions. + if (!Method) { +Filter.erase(); continue; + } + QualType Adjusted = Function->getType(); if (!hasExplicitCallingConv(Adjusted)) Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType()); + // Discard any candidates with the wrong type. // This doesn't handle deduced return types, but both function // declarations should be undeduced at this point. - if (!Context.hasSameType(Adjusted, Method->getType())) + if (!Context.hasSameType(Adjusted, Method->getType())) { +Filter.erase(); continue; + } + + // Discard any candidates with unsatisfied constraints. if (ConstraintSatisfaction Satisfaction; Method->getTrailingRequiresClause() && (CheckFunctionConstraints(Method, Satisfaction, /*UsageLoc=*/Member->getLocation(), /*ForOverloadResolution=*/true) || - !Satisfaction.IsSatisfied)) -continue; - Candidates.push_back(Method); - FunctionDecl *MoreConstrained = - Instantiation ? getMoreConstrainedFunction( - Method, cast(Instantiation)) -: Method; - if (!MoreConstrained) { -Ambiguous = true; + !Satisfaction.IsSatisfied)) { +Filter.erase(); continue; } - if (MoreConstrained == Method) { -Ambiguous = false; -FoundInstantiation = *I; -Instantiation = Method; -InstantiatedFrom = Method->getInstantiatedFromMemberFunction(); -MSInfo = Method->getMemberSpecializationInfo(); +} +Filter.done(); + +// If we have no candidates left after filtering, we are done. +if (Previous.empty()) + return false; + +// Find the function that is more constrained than every other function it +// has been compared to. +UnresolvedSetIterator Best = Previous.begin(); +CXXMethodDecl *BestMethod = nullptr; +for (UnresolvedSetIterator I = Previous.begin(), E = Previous.end(); I != E; + ++I) { + auto *Method = cast(I->getUnderlyingDecl()); + if (I == Best || + getMoreConstrainedFunction(Method, BestMethod) == Method) { +Best = I; +BestMethod = Method; + } +} + +FoundInstantiation = *Best; +Instantiation = BestMethod; +InstantiatedFrom = BestMethod->getInstantiatedFromMemberFunction(); +MSInfo = BestMethod->getMemberSpecializationInfo(); + +// Make sure the best candidate is more specialized than all of the others. +bool Ambiguous = false; +for (UnresolvedSetIterator I = Previous.begin(), E = Previous.end(); I != E; + ++I) { + auto *Method = cast(I->getUnderlyingDecl()); + if (I != Best && + getMoreConstrainedFunction(Method, BestMethod) != BestMethod) { +Ambiguous = true; +break; } } + if (Ambiguous) { Diag(Member->getLocation(), diag::err_function_member_spec_ambiguous) << Member << (InstantiatedFrom ? InstantiatedFrom : Instantiation); - for (FunctionDecl *Candidate : Candidates) + for (NamedDecl *Candidate : Previous) { +Candidate = Candidate->getUnderlyingDecl(); Diag(Candidate->getLocation(), diag::note_function_member_spec_matched) << Candidate; + } return true; } } else if (isa(Member)) { >From 8d9a4f0fc1da8b376a4c1e5cbf5e868ee20c790a Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 2 Aug 2024 12:
[clang] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others (PR #101721)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/101721 >From 046bf3e993cd8905869cb244ddb7df019b44ae78 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 2 Aug 2024 11:32:49 -0400 Subject: [PATCH 1/5] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others --- clang/lib/Sema/SemaTemplate.cpp | 80 +++-- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 87b1f98bbe5ac..b1c9ec21b152e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -9062,51 +9062,83 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { if (Previous.empty()) { // Nowhere to look anyway. } else if (FunctionDecl *Function = dyn_cast(Member)) { -SmallVector Candidates; -bool Ambiguous = false; -for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); - I != E; ++I) { - CXXMethodDecl *Method = - dyn_cast((*I)->getUnderlyingDecl()); - if (!Method) +LookupResult::Filter Filter = Previous.makeFilter(); +while (Filter.hasNext()) { + auto *Method = + dyn_cast(Filter.next()->getUnderlyingDecl()); + // Discard any candidates that aren't member functions. + if (!Method) { +Filter.erase(); continue; + } + QualType Adjusted = Function->getType(); if (!hasExplicitCallingConv(Adjusted)) Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType()); + // Discard any candidates with the wrong type. // This doesn't handle deduced return types, but both function // declarations should be undeduced at this point. - if (!Context.hasSameType(Adjusted, Method->getType())) + if (!Context.hasSameType(Adjusted, Method->getType())) { +Filter.erase(); continue; + } + + // Discard any candidates with unsatisfied constraints. if (ConstraintSatisfaction Satisfaction; Method->getTrailingRequiresClause() && (CheckFunctionConstraints(Method, Satisfaction, /*UsageLoc=*/Member->getLocation(), /*ForOverloadResolution=*/true) || - !Satisfaction.IsSatisfied)) -continue; - Candidates.push_back(Method); - FunctionDecl *MoreConstrained = - Instantiation ? getMoreConstrainedFunction( - Method, cast(Instantiation)) -: Method; - if (!MoreConstrained) { -Ambiguous = true; + !Satisfaction.IsSatisfied)) { +Filter.erase(); continue; } - if (MoreConstrained == Method) { -Ambiguous = false; -FoundInstantiation = *I; -Instantiation = Method; -InstantiatedFrom = Method->getInstantiatedFromMemberFunction(); -MSInfo = Method->getMemberSpecializationInfo(); +} +Filter.done(); + +// If we have no candidates left after filtering, we are done. +if (Previous.empty()) + return false; + +// Find the function that is more constrained than every other function it +// has been compared to. +UnresolvedSetIterator Best = Previous.begin(); +CXXMethodDecl *BestMethod = nullptr; +for (UnresolvedSetIterator I = Previous.begin(), E = Previous.end(); I != E; + ++I) { + auto *Method = cast(I->getUnderlyingDecl()); + if (I == Best || + getMoreConstrainedFunction(Method, BestMethod) == Method) { +Best = I; +BestMethod = Method; + } +} + +FoundInstantiation = *Best; +Instantiation = BestMethod; +InstantiatedFrom = BestMethod->getInstantiatedFromMemberFunction(); +MSInfo = BestMethod->getMemberSpecializationInfo(); + +// Make sure the best candidate is more specialized than all of the others. +bool Ambiguous = false; +for (UnresolvedSetIterator I = Previous.begin(), E = Previous.end(); I != E; + ++I) { + auto *Method = cast(I->getUnderlyingDecl()); + if (I != Best && + getMoreConstrainedFunction(Method, BestMethod) != BestMethod) { +Ambiguous = true; +break; } } + if (Ambiguous) { Diag(Member->getLocation(), diag::err_function_member_spec_ambiguous) << Member << (InstantiatedFrom ? InstantiatedFrom : Instantiation); - for (FunctionDecl *Candidate : Candidates) + for (NamedDecl *Candidate : Previous) { +Candidate = Candidate->getUnderlyingDecl(); Diag(Candidate->getLocation(), diag::note_function_member_spec_matched) << Candidate; + } return true; } } else if (isa(Member)) { >From ccbd6012a79745e6999ae22aed681dfb80ad4f14 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 2 Aug 2024 12:
[clang] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (PR #100392)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/100392 >From 7d0e70feb5e657c1830901e3ed9a01c1d56c7526 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 24 Jul 2024 10:15:47 -0400 Subject: [PATCH 1/3] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent --- clang/include/clang/AST/ExprCXX.h | 7 --- clang/lib/AST/ASTImporter.cpp | 5 +++-- clang/lib/AST/ExprCXX.cpp | 19 +++ clang/lib/Sema/SemaCoroutine.cpp | 3 ++- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp| 2 +- clang/lib/Sema/SemaExpr.cpp | 2 +- clang/lib/Sema/SemaExprMember.cpp | 3 ++- clang/lib/Sema/SemaOpenMP.cpp | 6 -- clang/lib/Sema/SemaOverload.cpp | 6 +++--- clang/lib/Sema/SemaTemplate.cpp | 3 ++- clang/lib/Sema/TreeTransform.h| 8 12 files changed, 38 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index f86f1818110e6..847a6ea408e98 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -3229,7 +3229,7 @@ class UnresolvedLookupExpr final const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, bool HasTemplateKWAndArgsInfo); @@ -3248,7 +3248,7 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); // After canonicalization, there may be dependent template arguments in // CanonicalConverted But none of Args is dependent. When any of @@ -3258,7 +3258,8 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, bool KnownDependent); + UnresolvedSetIterator End, bool KnownDependent, + bool KnownInstantiationDependent); static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, unsigned NumResults, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 103235547f482..49cbd60cafd0e 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8629,13 +8629,14 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, -ToDecls.begin(), ToDecls.end(), KnownDependent); +ToDecls.begin(), ToDecls.end(), KnownDependent, +E->isInstantiationDependent()); } return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(), - /*KnownDependent=*/E->isTypeDependent()); + /*KnownDependent=*/E->isTypeDependent(), E->isInstantiationDependent()); } ExpectedStmt diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 6212989e21737..83ce404add5f5 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -402,10 +402,11 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, -UnresolvedSetIterator End, bool KnownDependent) +UnresolvedSetIterator End, bool KnownDependent, +bool KnownInstantiationDependent) : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, - KnownDependent, false, false), + KnownDependent, KnownInstantiationDependent, false), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; } @@ -420,7 +421,7 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, -bool KnownDepende
[clang] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (PR #100392)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/100392 >From 7d0e70feb5e657c1830901e3ed9a01c1d56c7526 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 24 Jul 2024 10:15:47 -0400 Subject: [PATCH] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent --- clang/include/clang/AST/ExprCXX.h | 7 --- clang/lib/AST/ASTImporter.cpp | 5 +++-- clang/lib/AST/ExprCXX.cpp | 19 +++ clang/lib/Sema/SemaCoroutine.cpp | 3 ++- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp| 2 +- clang/lib/Sema/SemaExpr.cpp | 2 +- clang/lib/Sema/SemaExprMember.cpp | 3 ++- clang/lib/Sema/SemaOpenMP.cpp | 6 -- clang/lib/Sema/SemaOverload.cpp | 6 +++--- clang/lib/Sema/SemaTemplate.cpp | 3 ++- clang/lib/Sema/TreeTransform.h| 8 12 files changed, 38 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index f86f1818110e6..847a6ea408e98 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -3229,7 +3229,7 @@ class UnresolvedLookupExpr final const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, bool HasTemplateKWAndArgsInfo); @@ -3248,7 +3248,7 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); // After canonicalization, there may be dependent template arguments in // CanonicalConverted But none of Args is dependent. When any of @@ -3258,7 +3258,8 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, bool KnownDependent); + UnresolvedSetIterator End, bool KnownDependent, + bool KnownInstantiationDependent); static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, unsigned NumResults, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 103235547f482..49cbd60cafd0e 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8629,13 +8629,14 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, -ToDecls.begin(), ToDecls.end(), KnownDependent); +ToDecls.begin(), ToDecls.end(), KnownDependent, +E->isInstantiationDependent()); } return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(), - /*KnownDependent=*/E->isTypeDependent()); + /*KnownDependent=*/E->isTypeDependent(), E->isInstantiationDependent()); } ExpectedStmt diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 6212989e21737..83ce404add5f5 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -402,10 +402,11 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, -UnresolvedSetIterator End, bool KnownDependent) +UnresolvedSetIterator End, bool KnownDependent, +bool KnownInstantiationDependent) : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, - KnownDependent, false, false), + KnownDependent, KnownInstantiationDependent, false), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; } @@ -420,7 +421,7 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, -bool KnownDependent)
[clang] [Clang][NFC] Remove trailing whitespace from SemaExpr.cpp (PR #102001)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/102001 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][NFC] Remove trailing whitespace from SemaExpr.cpp (PR #102001)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/102001 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][NFC] Remove trailing whitespace from SemaExpr.cpp (PR #102001)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/102001 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][NFC] Remove trailing whitespace from SemaExpr.cpp (PR #102001)
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/102001 None >From 42012dba14c04b00ea0c8f542a9bfc0983002a9e Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 5 Aug 2024 11:03:04 -0400 Subject: [PATCH] [Clang][NFC] Remove trailing whitespace from SemaExpr.cpp --- clang/lib/Sema/SemaExpr.cpp | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 74c0e01705905..d0ba12fe80f9a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -17008,10 +17008,10 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, if (!isa(E)) E = Result ? ConstantExpr::Create(Context, E, APValue(*Result)) : ConstantExpr::Create(Context, E); - + if (Notes.empty()) return E; - + // If our only note is the usual "invalid subexpression" note, just point // the caret at its location rather than producing an essentially // redundant note. @@ -17020,7 +17020,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, DiagLoc = Notes[0].first; Notes.clear(); } - + if (getLangOpts().CPlusPlus) { if (!Diagnoser.Suppress) { Diagnoser.diagnoseNotICE(*this, DiagLoc) << E->getSourceRange(); @@ -17033,7 +17033,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, Diagnoser.diagnoseFold(*this, DiagLoc) << E->getSourceRange(); for (const PartialDiagnosticAt &Note : Notes) Diag(Note.first, Note.second); - + return E; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (PR #100392)
sdkrystian wrote: > Can we get rid of the whitespace only changes? @cor3ntin I have my editor configured to remove trailing whitespace on save. I'll just merge a commit to `main` that removes the trailing whitespace. > Can we maybe introduce an enum, it's a lot of booleans that will be easy to > mix. Maybe passing ExprDependence would be reasonable here This sounds more like an unrelated refactoring change. I'm going to hold off on doing that in this patch. https://github.com/llvm/llvm-project/pull/100392 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others (PR #101721)
@@ -10465,7 +10466,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Previous)) NewFD->setInvalidDecl(); } -} else if (isMemberSpecialization && isa(NewFD)) { +} else if (isMemberSpecialization && !FunctionTemplate) { sdkrystian wrote: Yes https://github.com/llvm/llvm-project/pull/101721 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others (PR #101721)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/101721 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others (PR #101721)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/101721 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Ensure that the selected candidate for a member function explicit specialization is more constrained than all others (PR #101721)
@@ -7964,8 +7964,9 @@ NamedDecl *Sema::ActOnVariableDeclarator( D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); } else { // If this is an explicit specialization of a static data member, check it. -if (IsMemberSpecialization && !IsVariableTemplateSpecialization && -!NewVD->isInvalidDecl() && CheckMemberSpecialization(NewVD, Previous)) +if (IsMemberSpecialization && !IsVariableTemplate && +!IsVariableTemplateSpecialization && !NewVD->isInvalidDecl() && +CheckMemberSpecialization(NewVD, Previous)) sdkrystian wrote: > Hm, do we not want to do these checks for an explicit specialization of a > member template? Or do we also do those checks somewhere else? `CheckMemberSpecialization` only handles explicit specializations of non-template members specialized for an implicit instantiation of a class template. Explicit specializations of _member templates_ specialized for an implicit instantiation of a class template are handled on the same codepath as normal templates, and we set the correct "instantiated from" template there. https://github.com/llvm/llvm-project/pull/101721 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
@@ -1779,6 +1779,42 @@ void Parser::checkPotentialAngleBracket(ExprResult &PotentialTemplateName) { Priority); } +bool Parser::isMissingTemplateKeywordBeforeScope(bool AnnotateInvalid) { + assert(Tok.is(tok::coloncolon)); + Sema::DisableTypoCorrectionRAII DTC(Actions); + ColonProtectionRAIIObject ColonProtection(*this); + + SourceLocation StartLoc = Tok.getLocation(); + if (TryAnnotateTypeOrScopeToken()) +return true; + if (Tok.isSimpleTypeSpecifier(getLangOpts())) +return false; + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHasErrors=*/false, + /*EnteringContext=*/false); + ExprResult Result = tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false); sdkrystian wrote: @zygoloid Do you otherwise think that it's reasonable to apply this change to _all_ C++ language modes (given the existence of [this thread](https://lists.isocpp.org/core/2024/07/16028.php) on the core reflector resulting from the initial application of this patch _without_ the enhanced identification of missing `template`)? https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
@@ -1779,6 +1779,42 @@ void Parser::checkPotentialAngleBracket(ExprResult &PotentialTemplateName) { Priority); } +bool Parser::isMissingTemplateKeywordBeforeScope(bool AnnotateInvalid) { + assert(Tok.is(tok::coloncolon)); + Sema::DisableTypoCorrectionRAII DTC(Actions); + ColonProtectionRAIIObject ColonProtection(*this); + + SourceLocation StartLoc = Tok.getLocation(); + if (TryAnnotateTypeOrScopeToken()) +return true; + if (Tok.isSimpleTypeSpecifier(getLangOpts())) +return false; + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHasErrors=*/false, + /*EnteringContext=*/false); + ExprResult Result = tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false); sdkrystian wrote: > Parsing the same expression twice could also be problematic in some cases -- > for example, if it contains a lambda, we might assign it the wrong mangling > number. Can we arrange things such that for a valid program, we only parse > the expression once? @zygoloid That already is the case: ```cpp template struct A { constexpr static int x = 0; template using B = A; }; template struct B { constexpr static int x = 0; }; template void f(T t) { t.A<0>::template B::x; // ok, interpreted as '((t.A) < 0) > ::template B::x' // lambda expression is only parsed once t.A<0>::template C::x; // warning: use 'template' keyword to treat 'A' as a dependent template name // lambda expression is parsed twice } ``` https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
@@ -1779,6 +1779,42 @@ void Parser::checkPotentialAngleBracket(ExprResult &PotentialTemplateName) { Priority); } +bool Parser::isMissingTemplateKeywordBeforeScope(bool AnnotateInvalid) { + assert(Tok.is(tok::coloncolon)); + Sema::DisableTypoCorrectionRAII DTC(Actions); + ColonProtectionRAIIObject ColonProtection(*this); + + SourceLocation StartLoc = Tok.getLocation(); + if (TryAnnotateTypeOrScopeToken()) +return true; + if (Tok.isSimpleTypeSpecifier(getLangOpts())) +return false; + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, + /*ObjectHasErrors=*/false, + /*EnteringContext=*/false); + ExprResult Result = tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false); sdkrystian wrote: For a well-formed program, any tentative parsing done here will happen anyways when parsing the second operand of the `>` operator. Only for an _ill-formed_ program (i.e. one where `template` is missing) do we instantiate things that should not be instantiated. As an alternative, we could also just lookup the name immediately following the `::` _nested-name-specifier_ and make the determination based on that. https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
sdkrystian wrote: With these changes, we can now issue warnings for the missing `template` keyword in the _vast_ majority of cases: ```cpp template struct A { int x; }; template struct B { int x; }; template struct C { int x; }; template struct D { int x; }; template constexpr inline int V = I; int y; template void f(T t) { t.A<0>::x;// expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A::x;// expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A>(0)>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A>(0)>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.B<1, true>::x; // expected-warning {{use 'template' keyword to treat 'B' as a dependent template name}} t.C<2, int, 4>::x;// expected-warning {{use 'template' keyword to treat 'C' as a dependent template name}} t.A>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.B<1, V<1>>::x; // expected-warning {{use 'template' keyword to treat 'B' as a dependent template name}} t.C, int, V<3>>::x; // expected-warning {{use 'template' keyword to treat 'C' as a dependent template name}} t.A<1 && T::template f<0>()>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A<(1 > 2)>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A<(1 < 3)>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.B::x < int, 1>::x; // expected-warning {{use 'template' keyword to treat 'x' as a dependent template name}} t.B::x < 0, 1>::x;// expected-error {{no member named 'x' in the global namespace}} // expected-error {{missing 'template' keyword prior to dependent template name 'B'}} t.A<1 < 4>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A::x; // expected-error {{no member named 'x' in the global namespace}} // expected-error {{missing 'template' keyword prior to dependent template name 'A'}} t.A::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A<1 > 4>::x; // expected-error {{no member named 'x' in the global namespace}} t.A<0>::y; // ok, parsed as '((t.A) < 0) > ::y' } ``` Would like to get feedback from @AaronBallman, @cor3ntin, @hokein, and perhaps @zygoloid on this :). I highly doubt the [discussion on the reflector](https://lists.isocpp.org/core/2024/07/16028.php) will result in any mitigation mechanisms being added (see my reply [here](https://lists.isocpp.org/core/2024/07/16039.php)). If any action _is_ taken, the most I foresee would be applying it in C++23 & later. https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
sdkrystian wrote: With these changes, we can now issue warnings for the missing `template` keyword in the _vast_ majority of cases: ```cpp template struct A { int x; }; template struct B { int x; }; template struct C { int x; }; template struct D { int x; }; template constexpr inline int V = I; int y; template void f(T t) { t.A<0>::x;// expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A::x;// expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A>(0)>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A>(0)>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.B<1, true>::x; // expected-warning {{use 'template' keyword to treat 'B' as a dependent template name}} t.C<2, int, 4>::x;// expected-warning {{use 'template' keyword to treat 'C' as a dependent template name}} t.A>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.B<1, V<1>>::x; // expected-warning {{use 'template' keyword to treat 'B' as a dependent template name}} t.C, int, V<3>>::x; // expected-warning {{use 'template' keyword to treat 'C' as a dependent template name}} t.A<1 && T::template f<0>()>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A<(1 > 2)>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A<(1 < 3)>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.B::x < int, 1>::x; // expected-warning {{use 'template' keyword to treat 'x' as a dependent template name}} t.B::x < 0, 1>::x;// expected-error {{no member named 'x' in the global namespace}} // expected-error {{missing 'template' keyword prior to dependent template name 'B'}} t.A<1 < 4>::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A::x; // expected-error {{no member named 'x' in the global namespace}} // expected-error {{missing 'template' keyword prior to dependent template name 'A'}} t.A::x; // expected-warning {{use 'template' keyword to treat 'A' as a dependent template name}} t.A<1 > 4>::x; // expected-error {{no member named 'x' in the global namespace}} t.A<0>::y; // ok, parsed as '((t.A) < 0) > ::y' } ``` Would like to get feedback from @AaronBallman, @cor3ntin, @hokein, and perhaps @zygoloid on this :). I highly doubt the [discussion on the reflector](https://lists.isocpp.org/core/2024/07/16028.php) will result in any mitigation mechanisms being added (see my reply [here](https://lists.isocpp.org/core/2024/07/16039.php)). If any action _is_ taken, the most I foresee would be applying it in C++23 & later. https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
sdkrystian wrote: Also added support for names prefixed with the `template` keyword. https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
https://github.com/sdkrystian edited https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
sdkrystian wrote: I've further improved `isTemplateArgumentList` so we only consider `<` as the start of a potential template-argument-list if it follows an _identifier_ or the name in an _operator-function-id_/_literal-operator-id_ when trying to find the closing `>`. Also, explicit casts (a la `static_cast`) are handled, as are constructs which may either be a _type-id_ or an explicit type conversion (functional notation). https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may declarative (PR #96364)
https://github.com/sdkrystian closed https://github.com/llvm/llvm-project/pull/96364 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may declarative (PR #96364)
sdkrystian wrote: I think this is ready to merge. I have [a branch](https://github.com/sdkrystian/llvm-project/tree/perf/backtrack-raii) which fully implements annotated/unannotated preprocessor backtrack using RAII objects, but I think this is beyond the scope of this PR. https://github.com/llvm/llvm-project/pull/96364 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may declarative (PR #96364)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/96364 >From 496e0cf24b07622bd9354297c20091c2057a55c6 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 12 Jun 2024 14:14:26 -0400 Subject: [PATCH 1/8] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may be declarative --- clang/include/clang/Lex/Preprocessor.h| 14 +++- clang/include/clang/Parse/Parser.h| 13 ++- clang/lib/Lex/PPCaching.cpp | 39 - clang/lib/Parse/ParseCXXInlineMethods.cpp | 41 + clang/lib/Parse/ParseDecl.cpp | 83 --- clang/lib/Parse/ParseExprCXX.cpp | 19 ++--- .../CXX/dcl.decl/dcl.meaning/dcl.mptr/p2.cpp | 64 ++ clang/test/CXX/temp/temp.res/p3.cpp | 10 +-- 8 files changed, 182 insertions(+), 101 deletions(-) create mode 100644 clang/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p2.cpp diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index fc7d0053f2323..b2dbd7d5375b5 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1160,6 +1160,9 @@ class Preprocessor { /// invoked (at which point the last position is popped). std::vector BacktrackPositions; + std::vector> + UnannotatedBacktrackPositions; + /// True if \p Preprocessor::SkipExcludedConditionalBlock() is running. /// This is used to guard against calling this function recursively. /// @@ -1722,7 +1725,7 @@ class Preprocessor { /// at some point after EnableBacktrackAtThisPos. If you don't, caching of /// tokens will continue indefinitely. /// - void EnableBacktrackAtThisPos(); + void EnableBacktrackAtThisPos(bool Unannotated = false); /// Disable the last EnableBacktrackAtThisPos call. void CommitBacktrackedTokens(); @@ -1733,7 +1736,11 @@ class Preprocessor { /// True if EnableBacktrackAtThisPos() was called and /// caching of tokens is on. + bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); } + bool isUnannotatedBacktrackEnabled() const { +return !UnannotatedBacktrackPositions.empty(); + } /// Lex the next token for this preprocessor. void Lex(Token &Result); @@ -1841,8 +1848,9 @@ class Preprocessor { void RevertCachedTokens(unsigned N) { assert(isBacktrackEnabled() && "Should only be called when tokens are cached for backtracking"); -assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back()) - && "Should revert tokens up to the last backtrack position, not more"); +assert(signed(CachedLexPos) - signed(N) >= + signed(BacktrackPositions.back() >> 1) && + "Should revert tokens up to the last backtrack position, not more"); assert(signed(CachedLexPos) - signed(N) >= 0 && "Corrupted backtrack positions ?"); CachedLexPos -= N; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 35bb1a19d40f0..7f5e21127d1e5 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1034,7 +1034,7 @@ class Parser : public CodeCompletionHandler { bool isActive; public: -explicit TentativeParsingAction(Parser &p) +explicit TentativeParsingAction(Parser &p, bool Unannotated = false) : P(p), PrevPreferredType(P.PreferredType) { PrevTok = P.Tok; PrevTentativelyDeclaredIdentifierCount = @@ -1042,7 +1042,7 @@ class Parser : public CodeCompletionHandler { PrevParenCount = P.ParenCount; PrevBracketCount = P.BracketCount; PrevBraceCount = P.BraceCount; - P.PP.EnableBacktrackAtThisPos(); + P.PP.EnableBacktrackAtThisPos(Unannotated); isActive = true; } void Commit() { @@ -1073,13 +1073,11 @@ class Parser : public CodeCompletionHandler { class RevertingTentativeParsingAction : private Parser::TentativeParsingAction { public: -RevertingTentativeParsingAction(Parser &P) -: Parser::TentativeParsingAction(P) {} +using TentativeParsingAction::TentativeParsingAction; + ~RevertingTentativeParsingAction() { Revert(); } }; - class UnannotatedTentativeParsingAction; - /// ObjCDeclContextSwitch - An object used to switch context from /// an objective-c decl context to its enclosing decl context and /// back. @@ -1984,7 +1982,8 @@ class Parser : public CodeCompletionHandler { CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHasErrors, bool EnteringContext, bool *MayBePseudoDestructor = nullptr, bool IsTypename = false, const IdentifierInfo **LastII = nullptr, - bool OnlyNamespace = false, bool InUsingDeclaration = false); + bool OnlyNamespace = false, bool InUsingDeclaration = false, + bool Disambiguation = false); //======// // C++11 5.1.2: Lambda e
[clang] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may declarative (PR #96364)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/96364 >From 691b0d3b23aa89af08ff6b1f4e09ff62c4b36ef6 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 12 Jun 2024 14:14:26 -0400 Subject: [PATCH 1/8] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may be declarative --- clang/include/clang/Lex/Preprocessor.h| 14 +++- clang/include/clang/Parse/Parser.h| 13 ++- clang/lib/Lex/PPCaching.cpp | 39 - clang/lib/Parse/ParseCXXInlineMethods.cpp | 41 + clang/lib/Parse/ParseDecl.cpp | 83 --- clang/lib/Parse/ParseExprCXX.cpp | 19 ++--- .../CXX/dcl.decl/dcl.meaning/dcl.mptr/p2.cpp | 64 ++ clang/test/CXX/temp/temp.res/p3.cpp | 10 +-- 8 files changed, 182 insertions(+), 101 deletions(-) create mode 100644 clang/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p2.cpp diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index fc7d0053f2323..b2dbd7d5375b5 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1160,6 +1160,9 @@ class Preprocessor { /// invoked (at which point the last position is popped). std::vector BacktrackPositions; + std::vector> + UnannotatedBacktrackPositions; + /// True if \p Preprocessor::SkipExcludedConditionalBlock() is running. /// This is used to guard against calling this function recursively. /// @@ -1722,7 +1725,7 @@ class Preprocessor { /// at some point after EnableBacktrackAtThisPos. If you don't, caching of /// tokens will continue indefinitely. /// - void EnableBacktrackAtThisPos(); + void EnableBacktrackAtThisPos(bool Unannotated = false); /// Disable the last EnableBacktrackAtThisPos call. void CommitBacktrackedTokens(); @@ -1733,7 +1736,11 @@ class Preprocessor { /// True if EnableBacktrackAtThisPos() was called and /// caching of tokens is on. + bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); } + bool isUnannotatedBacktrackEnabled() const { +return !UnannotatedBacktrackPositions.empty(); + } /// Lex the next token for this preprocessor. void Lex(Token &Result); @@ -1841,8 +1848,9 @@ class Preprocessor { void RevertCachedTokens(unsigned N) { assert(isBacktrackEnabled() && "Should only be called when tokens are cached for backtracking"); -assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back()) - && "Should revert tokens up to the last backtrack position, not more"); +assert(signed(CachedLexPos) - signed(N) >= + signed(BacktrackPositions.back() >> 1) && + "Should revert tokens up to the last backtrack position, not more"); assert(signed(CachedLexPos) - signed(N) >= 0 && "Corrupted backtrack positions ?"); CachedLexPos -= N; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 35bb1a19d40f0..7f5e21127d1e5 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1034,7 +1034,7 @@ class Parser : public CodeCompletionHandler { bool isActive; public: -explicit TentativeParsingAction(Parser &p) +explicit TentativeParsingAction(Parser &p, bool Unannotated = false) : P(p), PrevPreferredType(P.PreferredType) { PrevTok = P.Tok; PrevTentativelyDeclaredIdentifierCount = @@ -1042,7 +1042,7 @@ class Parser : public CodeCompletionHandler { PrevParenCount = P.ParenCount; PrevBracketCount = P.BracketCount; PrevBraceCount = P.BraceCount; - P.PP.EnableBacktrackAtThisPos(); + P.PP.EnableBacktrackAtThisPos(Unannotated); isActive = true; } void Commit() { @@ -1073,13 +1073,11 @@ class Parser : public CodeCompletionHandler { class RevertingTentativeParsingAction : private Parser::TentativeParsingAction { public: -RevertingTentativeParsingAction(Parser &P) -: Parser::TentativeParsingAction(P) {} +using TentativeParsingAction::TentativeParsingAction; + ~RevertingTentativeParsingAction() { Revert(); } }; - class UnannotatedTentativeParsingAction; - /// ObjCDeclContextSwitch - An object used to switch context from /// an objective-c decl context to its enclosing decl context and /// back. @@ -1984,7 +1982,8 @@ class Parser : public CodeCompletionHandler { CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHasErrors, bool EnteringContext, bool *MayBePseudoDestructor = nullptr, bool IsTypename = false, const IdentifierInfo **LastII = nullptr, - bool OnlyNamespace = false, bool InUsingDeclaration = false); + bool OnlyNamespace = false, bool InUsingDeclaration = false, + bool Disambiguation = false); //======// // C++11 5.1.2: Lambda e
[clang] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may declarative (PR #96364)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/96364 >From 037fb12412e9b3787e91d0a8ca826e098eab4e85 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 12 Jun 2024 14:14:26 -0400 Subject: [PATCH 1/8] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may be declarative --- clang/include/clang/Lex/Preprocessor.h| 14 +++- clang/include/clang/Parse/Parser.h| 13 ++- clang/lib/Lex/PPCaching.cpp | 39 - clang/lib/Parse/ParseCXXInlineMethods.cpp | 41 + clang/lib/Parse/ParseDecl.cpp | 83 --- clang/lib/Parse/ParseExprCXX.cpp | 19 ++--- .../CXX/dcl.decl/dcl.meaning/dcl.mptr/p2.cpp | 64 ++ clang/test/CXX/temp/temp.res/p3.cpp | 10 +-- 8 files changed, 182 insertions(+), 101 deletions(-) create mode 100644 clang/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p2.cpp diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index fc7d0053f2323..b2dbd7d5375b5 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1160,6 +1160,9 @@ class Preprocessor { /// invoked (at which point the last position is popped). std::vector BacktrackPositions; + std::vector> + UnannotatedBacktrackPositions; + /// True if \p Preprocessor::SkipExcludedConditionalBlock() is running. /// This is used to guard against calling this function recursively. /// @@ -1722,7 +1725,7 @@ class Preprocessor { /// at some point after EnableBacktrackAtThisPos. If you don't, caching of /// tokens will continue indefinitely. /// - void EnableBacktrackAtThisPos(); + void EnableBacktrackAtThisPos(bool Unannotated = false); /// Disable the last EnableBacktrackAtThisPos call. void CommitBacktrackedTokens(); @@ -1733,7 +1736,11 @@ class Preprocessor { /// True if EnableBacktrackAtThisPos() was called and /// caching of tokens is on. + bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); } + bool isUnannotatedBacktrackEnabled() const { +return !UnannotatedBacktrackPositions.empty(); + } /// Lex the next token for this preprocessor. void Lex(Token &Result); @@ -1841,8 +1848,9 @@ class Preprocessor { void RevertCachedTokens(unsigned N) { assert(isBacktrackEnabled() && "Should only be called when tokens are cached for backtracking"); -assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back()) - && "Should revert tokens up to the last backtrack position, not more"); +assert(signed(CachedLexPos) - signed(N) >= + signed(BacktrackPositions.back() >> 1) && + "Should revert tokens up to the last backtrack position, not more"); assert(signed(CachedLexPos) - signed(N) >= 0 && "Corrupted backtrack positions ?"); CachedLexPos -= N; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 613bab9120dfc..602a68c2feaff 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1034,7 +1034,7 @@ class Parser : public CodeCompletionHandler { bool isActive; public: -explicit TentativeParsingAction(Parser &p) +explicit TentativeParsingAction(Parser &p, bool Unannotated = false) : P(p), PrevPreferredType(P.PreferredType) { PrevTok = P.Tok; PrevTentativelyDeclaredIdentifierCount = @@ -1042,7 +1042,7 @@ class Parser : public CodeCompletionHandler { PrevParenCount = P.ParenCount; PrevBracketCount = P.BracketCount; PrevBraceCount = P.BraceCount; - P.PP.EnableBacktrackAtThisPos(); + P.PP.EnableBacktrackAtThisPos(Unannotated); isActive = true; } void Commit() { @@ -1073,13 +1073,11 @@ class Parser : public CodeCompletionHandler { class RevertingTentativeParsingAction : private Parser::TentativeParsingAction { public: -RevertingTentativeParsingAction(Parser &P) -: Parser::TentativeParsingAction(P) {} +using TentativeParsingAction::TentativeParsingAction; + ~RevertingTentativeParsingAction() { Revert(); } }; - class UnannotatedTentativeParsingAction; - /// ObjCDeclContextSwitch - An object used to switch context from /// an objective-c decl context to its enclosing decl context and /// back. @@ -1984,7 +1982,8 @@ class Parser : public CodeCompletionHandler { CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHasErrors, bool EnteringContext, bool *MayBePseudoDestructor = nullptr, bool IsTypename = false, const IdentifierInfo **LastII = nullptr, - bool OnlyNamespace = false, bool InUsingDeclaration = false); + bool OnlyNamespace = false, bool InUsingDeclaration = false, + bool Disambiguation = false); //======// // C++11 5.1.2: Lambda e
[clang] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may declarative (PR #96364)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/96364 >From 037fb12412e9b3787e91d0a8ca826e098eab4e85 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 12 Jun 2024 14:14:26 -0400 Subject: [PATCH 1/7] [Clang][Parse] Fix ambiguity with nested-name-specifiers that may be declarative --- clang/include/clang/Lex/Preprocessor.h| 14 +++- clang/include/clang/Parse/Parser.h| 13 ++- clang/lib/Lex/PPCaching.cpp | 39 - clang/lib/Parse/ParseCXXInlineMethods.cpp | 41 + clang/lib/Parse/ParseDecl.cpp | 83 --- clang/lib/Parse/ParseExprCXX.cpp | 19 ++--- .../CXX/dcl.decl/dcl.meaning/dcl.mptr/p2.cpp | 64 ++ clang/test/CXX/temp/temp.res/p3.cpp | 10 +-- 8 files changed, 182 insertions(+), 101 deletions(-) create mode 100644 clang/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p2.cpp diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index fc7d0053f2323..b2dbd7d5375b5 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1160,6 +1160,9 @@ class Preprocessor { /// invoked (at which point the last position is popped). std::vector BacktrackPositions; + std::vector> + UnannotatedBacktrackPositions; + /// True if \p Preprocessor::SkipExcludedConditionalBlock() is running. /// This is used to guard against calling this function recursively. /// @@ -1722,7 +1725,7 @@ class Preprocessor { /// at some point after EnableBacktrackAtThisPos. If you don't, caching of /// tokens will continue indefinitely. /// - void EnableBacktrackAtThisPos(); + void EnableBacktrackAtThisPos(bool Unannotated = false); /// Disable the last EnableBacktrackAtThisPos call. void CommitBacktrackedTokens(); @@ -1733,7 +1736,11 @@ class Preprocessor { /// True if EnableBacktrackAtThisPos() was called and /// caching of tokens is on. + bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); } + bool isUnannotatedBacktrackEnabled() const { +return !UnannotatedBacktrackPositions.empty(); + } /// Lex the next token for this preprocessor. void Lex(Token &Result); @@ -1841,8 +1848,9 @@ class Preprocessor { void RevertCachedTokens(unsigned N) { assert(isBacktrackEnabled() && "Should only be called when tokens are cached for backtracking"); -assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back()) - && "Should revert tokens up to the last backtrack position, not more"); +assert(signed(CachedLexPos) - signed(N) >= + signed(BacktrackPositions.back() >> 1) && + "Should revert tokens up to the last backtrack position, not more"); assert(signed(CachedLexPos) - signed(N) >= 0 && "Corrupted backtrack positions ?"); CachedLexPos -= N; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 613bab9120dfc..602a68c2feaff 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1034,7 +1034,7 @@ class Parser : public CodeCompletionHandler { bool isActive; public: -explicit TentativeParsingAction(Parser &p) +explicit TentativeParsingAction(Parser &p, bool Unannotated = false) : P(p), PrevPreferredType(P.PreferredType) { PrevTok = P.Tok; PrevTentativelyDeclaredIdentifierCount = @@ -1042,7 +1042,7 @@ class Parser : public CodeCompletionHandler { PrevParenCount = P.ParenCount; PrevBracketCount = P.BracketCount; PrevBraceCount = P.BraceCount; - P.PP.EnableBacktrackAtThisPos(); + P.PP.EnableBacktrackAtThisPos(Unannotated); isActive = true; } void Commit() { @@ -1073,13 +1073,11 @@ class Parser : public CodeCompletionHandler { class RevertingTentativeParsingAction : private Parser::TentativeParsingAction { public: -RevertingTentativeParsingAction(Parser &P) -: Parser::TentativeParsingAction(P) {} +using TentativeParsingAction::TentativeParsingAction; + ~RevertingTentativeParsingAction() { Revert(); } }; - class UnannotatedTentativeParsingAction; - /// ObjCDeclContextSwitch - An object used to switch context from /// an objective-c decl context to its enclosing decl context and /// back. @@ -1984,7 +1982,8 @@ class Parser : public CodeCompletionHandler { CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHasErrors, bool EnteringContext, bool *MayBePseudoDestructor = nullptr, bool IsTypename = false, const IdentifierInfo **LastII = nullptr, - bool OnlyNamespace = false, bool InUsingDeclaration = false); + bool OnlyNamespace = false, bool InUsingDeclaration = false, + bool Disambiguation = false); //======// // C++11 5.1.2: Lambda e
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
@@ -767,6 +757,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, else Diag(IdInfo.IdentifierLoc, diag::err_undeclared_var_use) << IdInfo.Identifier; +#endif sdkrystian wrote: Yeah, these changes shouldn't really be part of this PR. Just something I noticed when refactoring `BuildCXXNestedNameSpecifier` that needs to go. I'll address it in another PR. https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (PR #100392)
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/100392 >From c4f8a620a2a4692c9fa27b41f7e86c8cb042e533 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 24 Jul 2024 10:15:47 -0400 Subject: [PATCH] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent --- clang/include/clang/AST/ExprCXX.h | 7 --- clang/lib/AST/ASTImporter.cpp | 5 +++-- clang/lib/AST/ExprCXX.cpp | 19 +++ clang/lib/Sema/SemaCoroutine.cpp | 3 ++- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp| 2 +- clang/lib/Sema/SemaExpr.cpp | 10 +- clang/lib/Sema/SemaExprMember.cpp | 3 ++- clang/lib/Sema/SemaOpenMP.cpp | 6 -- clang/lib/Sema/SemaOverload.cpp | 6 +++--- clang/lib/Sema/SemaTemplate.cpp | 3 ++- clang/lib/Sema/TreeTransform.h| 8 12 files changed, 42 insertions(+), 32 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index f86f1818110e6..847a6ea408e98 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -3229,7 +3229,7 @@ class UnresolvedLookupExpr final const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, bool HasTemplateKWAndArgsInfo); @@ -3248,7 +3248,7 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); // After canonicalization, there may be dependent template arguments in // CanonicalConverted But none of Args is dependent. When any of @@ -3258,7 +3258,8 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, bool KnownDependent); + UnresolvedSetIterator End, bool KnownDependent, + bool KnownInstantiationDependent); static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, unsigned NumResults, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index da1981d8dd05f..f7a0deb9f3556 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8572,13 +8572,14 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, -ToDecls.begin(), ToDecls.end(), KnownDependent); +ToDecls.begin(), ToDecls.end(), KnownDependent, +E->isInstantiationDependent()); } return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(), - /*KnownDependent=*/E->isTypeDependent()); + /*KnownDependent=*/E->isTypeDependent(), E->isInstantiationDependent()); } ExpectedStmt diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index e2c9643151126..76d5f87933136 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -402,10 +402,11 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, -UnresolvedSetIterator End, bool KnownDependent) +UnresolvedSetIterator End, bool KnownDependent, +bool KnownInstantiationDependent) : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, - KnownDependent, false, false), + KnownDependent, KnownInstantiationDependent, false), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; } @@ -420,7 +421,7 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, -bool KnownDep
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
sdkrystian wrote: > I am still concerned about the double error on the `t.A<1 < 4>::x` example. The ideal outcome would be to turn the second error into a note. How feasible to fix you think that is? That's trivial to fix, just need to add a note variant of the "missing template" diagnostic. https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] Reapply "[Clang] Implement resolution for CWG1835 (#92957, #98547)" (PR #100425)
sdkrystian wrote: @AaronBallman @cor3ntin @mizvekov So, I've made improvements to our implementation of `isTemplateArgumentList` that allow us to issue a warning instead of an error for most of the cases where applying the DR breaks existing code: ```cpp template struct A { int x; }; template struct B { int x; }; template struct C { int x; }; template constexpr inline int V = I; int y; template void f(T t) { t.A<0>::x; // warning: use 'template' keyword to treat 'A' as a dependent template name t.B<1, true>::x; // warning: use 'template' keyword to treat 'B' as a dependent template name t.C<2, int, 4>::x; // warning: use 'template' keyword to treat 'C' as a dependent template name t.A>::x;// warning: use 'template' keyword to treat 'A' as a dependent template name t.B<1, V<1>>::x; // warning: use 'template' keyword to treat 'B' as a dependent template name t.C, int, V<3>>::x; // warning: use 'template' keyword to treat 'C' as a dependent template name t.A<(1 > 2)>::x; // warning: use 'template' keyword to treat 'A' as a dependent template name t.A<(1 < 3)>::x; // warning: use 'template' keyword to treat 'A' as a dependent template name t.A<1 < 4>::x; // error: no member named 'x' in the global namespace // error: missing 'template' keyword prior to dependent template name 'A' t.A<1 > 4>::x; // error: no member named 'x' in the global namespace t.A<0>::y; // ok, parsed as '((t.A) < 0) > ::y' } ``` This is accomplished by (attempting to) look past the end of the potential _template-argument-list_, and if the token following the `>` is `::`, we try to parse it as an _id-expression_/type. If it ends up being invalid, then we consider it being an intended template name and we issue the warning. Since we can look past the potential _template-argument-list_ in most cases, we could probably apply CWG1835 in all language modes with minimal impact on existing code. https://github.com/llvm/llvm-project/pull/100425 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits