[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 2 05:23:29 PDT 2024
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/86817
>From e84e4b6fedb5a643082cd38d0e10d910b299f73f Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 27 Mar 2024 11:23:19 -0400
Subject: [PATCH] [Clang][Sema] Fix explicit specializations of member function
templates with a deduced return type
---
.../clang-tidy/infrastructure/diagnostic.cpp | 4 +-
clang/docs/ReleaseNotes.rst | 2 +
clang/lib/Sema/SemaDecl.cpp | 46 ++++++++++++-------
.../SemaCXX/deduced-return-type-cxx14.cpp | 18 ++++++++
4 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index d0efc5ca763753..57d930b26e64c0 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -25,7 +25,7 @@
// RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s
// RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined,clang-diagnostic-literal-conversion' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 -Wno-macro-redefined | FileCheck --check-prefix=CHECK7 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602 | FileCheck -check-prefix=CHECK8 -implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602
// CHECK1: error: no input files [clang-diagnostic-error]
// CHECK1: error: no such file or directory: '{{.*}}nonexistent.cpp' [clang-diagnostic-error]
@@ -68,6 +68,4 @@ auto S<>::foo(auto)
{
return 1;
}
-// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error]
-// CHECK8: note: previous declaration is here
#endif
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b2faab1f1525b2..3a84ff16a1e4d4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -483,6 +483,8 @@ Bug Fixes to C++ Support
following the first `::` were ignored).
- Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757).
- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757).
+- Fixed a bug that prevented member function templates of class templates declared with a deduced return type
+ from being explicitly specialized for a given implicit instantiation of the class template.
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6ff85c0c5c29da..5c1152896559b5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10124,23 +10124,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
}
- if (getLangOpts().CPlusPlus14 &&
- (NewFD->isDependentContext() ||
- (isFriend && CurContext->isDependentContext())) &&
- NewFD->getReturnType()->isUndeducedType()) {
- // If the function template is referenced directly (for instance, as a
- // member of the current instantiation), pretend it has a dependent type.
- // This is not really justified by the standard, but is the only sane
- // thing to do.
- // FIXME: For a friend function, we have not marked the function as being
- // a friend yet, so 'isDependentContext' on the FD doesn't work.
- const FunctionProtoType *FPT =
- NewFD->getType()->castAs<FunctionProtoType>();
- QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
- NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
- FPT->getExtProtoInfo()));
- }
-
// C++ [dcl.fct.spec]p3:
// The inline specifier shall not appear on a block scope function
// declaration.
@@ -12112,6 +12095,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
CheckConstPureAttributesUsage(*this, NewFD);
+ // C++ [dcl.spec.auto.general]p12:
+ // Return type deduction for a templated function with a placeholder in its
+ // declared type occurs when the definition is instantiated even if the
+ // function body contains a return statement with a non-type-dependent
+ // operand.
+ //
+ // C++ [temp.dep.expr]p3:
+ // An id-expression is type-dependent if it is a template-id that is not a
+ // concept-id and is dependent; or if its terminal name is:
+ // - [...]
+ // - associated by name lookup with one or more declarations of member
+ // functions of a class that is the current instantiation declared with a
+ // return type that contains a placeholder type,
+ // - [...]
+ //
+ // If this is a templated function with a placeholder in its return type,
+ // make the placeholder type dependent since it won't be deduced until the
+ // definition is instantiated. We do this here because it needs to happen
+ // for implicitly instantiated member functions/member function templates.
+ if (getLangOpts().CPlusPlus14 &&
+ (NewFD->isDependentContext() &&
+ NewFD->getReturnType()->isUndeducedType())) {
+ const FunctionProtoType *FPT =
+ NewFD->getType()->castAs<FunctionProtoType>();
+ QualType NewReturnType = SubstAutoTypeDependent(FPT->getReturnType());
+ NewFD->setType(Context.getFunctionType(NewReturnType, FPT->getParamTypes(),
+ FPT->getExtProtoInfo()));
+ }
+
// C++11 [dcl.constexpr]p8:
// A constexpr specifier for a non-static member function that is not
// a constructor declares that member function to be const.
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 431d77ca785b8e..c33e07088ba32f 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -237,6 +237,24 @@ namespace Templates {
int (S::*(*p)())(double) = f;
int (S::*(*q)())(double) = f<S, double>;
}
+
+ template<typename T>
+ struct MemberSpecialization {
+ auto f();
+ template<typename U> auto f(U);
+ template<typename U> auto *f(U);
+ };
+
+ template<>
+ auto MemberSpecialization<int>::f();
+
+ template<>
+ template<typename U>
+ auto MemberSpecialization<int>::f(U);
+
+ template<>
+ template<typename U>
+ auto *MemberSpecialization<int>::f(U);
}
auto fwd_decl_using();
More information about the cfe-commits
mailing list