llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (offsetof) <details> <summary>Changes</summary> * In `Sema::BuildExpressionFromDeclTemplateArgument`, qualify names of explicit object member functions, and treat them as lvalues when the parameter is a reference. * Mangle explicit object member functions appearing as template arguments same as static member functions. (This fixes an assertion failure/incorrect mangling for Itanium ABI and a crash when mangling for MS ABI.) Fixes #<!-- -->106660 --- Full diff: https://github.com/llvm/llvm-project/pull/133748.diff 6 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+1) - (modified) clang/lib/AST/ItaniumMangle.cpp (+3-1) - (modified) clang/lib/AST/MicrosoftMangle.cpp (+1-1) - (modified) clang/lib/Sema/SemaTemplate.cpp (+15-3) - (added) clang/test/CodeGenCXX/mangle-ms-deducing-this.cpp (+46) - (modified) clang/test/SemaCXX/cxx2b-deducing-this.cpp (+39) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index daad01919ecd4..86c8e9e64b158 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -374,6 +374,7 @@ Bug Fixes to C++ Support - Clang no longer crashes when establishing subsumption between some constraint expressions. (#GH122581) - Clang now issues an error when placement new is used to modify a const-qualified variable in a ``constexpr`` function. (#GH131432) +- Fixed some issues related to the use of (pointers to) explicit object member functions as template arguments. (#GH106660) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 49a04861ae25d..3371dd9d65185 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -6279,7 +6279,9 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { ASTContext &Ctx = Context.getASTContext(); APValue Value; - if (D->isCXXInstanceMember()) + if (auto *Method = dyn_cast<CXXMethodDecl>(D); + Method ? Method->isImplicitObjectMemberFunction() + : D->isCXXInstanceMember()) // Simple pointer-to-member with no conversion. Value = APValue(D, /*IsDerivedMember=*/false, /*Path=*/{}); else if (D->getType()->isArrayType() && diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 7e964124a9fec..28aea62905fe4 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1805,7 +1805,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, TA.getParamTypeForDecl()); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); - if (MD && MD->isInstance()) { + if (MD && MD->isImplicitObjectMemberFunction()) { mangleMemberFunctionPointer( MD->getParent()->getMostRecentNonInjectedDecl(), MD, cast<NonTypeTemplateParmDecl>(Parm), TA.getParamTypeForDecl()); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index be81b6a46b2c0..2bf94d10f5f8a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -7518,9 +7518,9 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument( ValueDecl *VD = Arg.getAsDecl(); CXXScopeSpec SS; - if (ParamType->isMemberPointerType()) { - // If this is a pointer to member, we need to use a qualified name to - // form a suitable pointer-to-member constant. + if (VD->isCXXInstanceMember()) { + // If this is a non-static member, we need to use a qualified name to + // form a suitable pointer or pointer-to-member expression. assert(VD->getDeclContext()->isRecord() && (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) || isa<IndirectFieldDecl>(VD))); @@ -7558,6 +7558,18 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument( } else { assert(ParamType->isReferenceType() && "unexpected type for decl template argument"); + + if (auto *Method = dyn_cast<CXXMethodDecl>(VD); + Method && Method->isExplicitObjectMemberFunction()) { + // If the argument is an explicit object member function, + // RefExpr is currently a prvalue. Make it an lvalue. + RefExpr = ImplicitCastExpr::Create( + Context, RefExpr.get()->getType(), CK_NoOp, RefExpr.get(), + /*BasePath=*/nullptr, VK_LValue, /*FPO=*/{}); + if (RefExpr.isInvalid()) + return ExprError(); + } + if (NonTypeTemplateParmDecl *NTTP = dyn_cast_if_present<NonTypeTemplateParmDecl>(TemplateParam)) { QualType TemplateParamType = NTTP->getType(); diff --git a/clang/test/CodeGenCXX/mangle-ms-deducing-this.cpp b/clang/test/CodeGenCXX/mangle-ms-deducing-this.cpp new file mode 100644 index 0000000000000..fb36cc914eb9b --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-ms-deducing-this.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 %s -std=c++23 -triple=x86_64-linux -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -std=c++23 -triple=x86_64-win32 -emit-llvm -o - | FileCheck %s --check-prefix MS + +namespace GH106660 { + +template<auto> void f1(); +template<auto&> void f2(); +template<int (*)(int)> void f3(); +template<int (&)(int)> void f4(); + +struct X { + int f(this auto); + int f(this int); +}; + +void test() { + // CHECK: call void @_ZN8GH1066602f1ITnDaXadL_ZNHS_1X1fIiEEiT_EEEEvv + // MS: call void @"??$f1@$1??$f@H@X@GH106660@@SAH_VH@Z@GH106660@@YAXXZ" + f1<&X::f<int>>(); + // CHECK-NEXT: call void @_ZN8GH1066602f1ITnDaXadL_ZNHS_1X1fEiEEEEvv + // MS-NEXT: call void @"??$f1@$1?f@X@GH106660@@SAH_VH@Z@GH106660@@YAXXZ" + f1<static_cast<int (*)(int)>(&X::f)>(); + + // CHECK-NEXT: call void @_ZN8GH1066602f2ITnRDaL_ZNHS_1X1fIiEEiT_EEEvv + // MS-NEXT: call void @"??$f2@$1??$f@H@X@GH106660@@SAH_VH@Z@GH106660@@YAXXZ" + f2<*&X::f<int>>(); + // CHECK-NEXT: call void @_ZN8GH1066602f2ITnRDaL_ZNHS_1X1fEiEEEvv + // MS-NEXT: call void @"??$f2@$1?f@X@GH106660@@SAH_VH@Z@GH106660@@YAXXZ" + f2<*static_cast<int (*)(int)>(&X::f)>(); + + // CHECK-NEXT: call void @_ZN8GH1066602f3IXadL_ZNHS_1X1fIiEEiT_EEEEvv + // MS-NEXT: call void @"??$f3@$1??$f@H@X@GH106660@@SAH_VH@Z@GH106660@@YAXXZ" + f3<&X::f<int>>(); + // CHECK-NEXT: call void @_ZN8GH1066602f3IXadL_ZNHS_1X1fEiEEEEvv + // MS-NEXT: call void @"??$f3@$1?f@X@GH106660@@SAH_VH@Z@GH106660@@YAXXZ" + f3<static_cast<int (*)(int)>(&X::f)>(); + + // CHECK-NEXT: call void @_ZN8GH1066602f4IL_ZNHS_1X1fIiEEiT_EEEvv + // MS-NEXT: call void @"??$f4@$1??$f@H@X@GH106660@@SAH_VH@Z@GH106660@@YAXXZ" + f4<*&X::f<int>>(); + // CHECK-NEXT: call void @_ZN8GH1066602f4IL_ZNHS_1X1fEiEEEvv + // MS-NEXT: call void @"??$f4@$1?f@X@GH106660@@SAH_VH@Z@GH106660@@YAXXZ" + f4<*static_cast<int (*)(int)>(&X::f)>(); +} + +} // namespace GH106660 diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp index 6f17ce7275456..570a3e9953bf1 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -1118,6 +1118,45 @@ struct C4 { }; } +namespace GH106660 { + +template<auto X> constexpr int A = X(1); +template<auto& X> constexpr int Ar = X(2); +template<int (*X)(int)> constexpr int B = X(3); +template<int (&X)(int)> constexpr int Br = X(4); +template<auto X> using C = decltype(X(1)); +template<auto& X> using Cr = decltype(X(2)); +template<int (*X)(int)> using D = decltype(X(3)); +template<int (&X)(int)> using Dr = decltype(X(4)); +template<auto X> using E = decltype((X)); +template<auto& X> using Er = decltype((X)); +template<int (*X)(int)> using F = decltype((X)); +template<int (&X)(int)> using Fr = decltype((X)); + +struct S { + constexpr int f(this int i) noexcept { + return i * 2; + } +}; + +static_assert(A<&S::f> == 2); +static_assert(Ar<*&S::f> == 4); +static_assert(B<&S::f> == 6); +static_assert(Br<*&S::f> == 8); + +using W = C<&S::f>; +using X = Cr<*&S::f>; +using Y = D<&S::f>; +using Z = Dr<*&S::f>; + +template<class> class R {}; +R<int (*)(int) noexcept> w = R<E<&S::f>>(); +R<int (&)(int) noexcept> x = R<Er<*&S::f>>(); +R<int (*)(int)> y = R<F<&S::f>>(); +R<int (&)(int)> z = R<Fr<*&S::f>>(); + + +} // namespace GH106660 namespace GH112559 { struct Wrap {}; `````````` </details> https://github.com/llvm/llvm-project/pull/133748 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits