llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Serosh (Serosh-commits)

<details>
<summary>Changes</summary>

Mark invalid friend definitions with `setInvalidDecl()` and skip the redecl 
chain search in `InstantiateFunctionDefinition` for friend-instantiated 
functions, which don't follow standard template redecl rules
fixes #<!-- -->185341

---
Full diff: https://github.com/llvm/llvm-project/pull/186398.diff


4 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+1) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+3) 
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+4-1) 
- (added) clang/test/SemaCXX/gh185341.cpp (+17) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 613d87668be18..330c46b2eaaf3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -243,6 +243,7 @@ Bug Fixes to Attribute Support
 
 Bug Fixes to C++ Support
 ^^^^^^^^^^^^^^^^^^^^^^^^
+- Fixed a crash when a function template is defined as a non-template friend 
with a global scope qualifier. (#GH185341)
 - Fixed a crash when instantiating ``requires`` expressions involving 
substitution failures in C++ concepts. (#GH176402)
 - Fixed a crash when a default argument is passed to an explicit object 
parameter. (#GH176639)
 - Fixed a crash when diagnosing an invalid static member function with an 
explicit object parameter (#GH177741)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 5837ecd6b9163..d966a3c1a25fd 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -18452,10 +18452,12 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
         DB << SS.getScopeRep();
         if (DC->isFileContext())
           DB << FixItHint::CreateRemoval(SS.getRange());
+        ND->setInvalidDecl();
 
         // Friend function defined in a local class.
       } else if (FunctionContainingLocalClass) {
         Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
+        ND->setInvalidDecl();
 
         // Per [basic.pre]p4, a template-id is not a name. Therefore, if we 
have
         // a template-id, the function name is not unqualified because these is
@@ -18465,6 +18467,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
         // and diagnose them as such.
       } else if (isTemplateId) {
         Diag(NameInfo.getBeginLoc(), diag::err_friend_specialization_def);
+        ND->setInvalidDecl();
       }
     }
 
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e74c41517ecbf..9e1416bac212c 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5563,6 +5563,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation 
PointOfInstantiation,
     // corresponding declaration of the function.
     assert(ExistingDefn->isThisDeclarationInstantiatedFromAFriendDefinition());
     Function = const_cast<FunctionDecl*>(ExistingDefn);
+    if (Function->isInvalidDecl())
+      return;
   }
 
 #ifndef NDEBUG
@@ -5888,7 +5890,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation 
PointOfInstantiation,
         Primary &&
         !isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function) &&
         Function->getTemplateSpecializationKind() !=
-            TSK_ExplicitSpecialization) {
+            TSK_ExplicitSpecialization &&
+        !Function->isThisDeclarationInstantiatedFromAFriendDefinition()) {
       auto It = llvm::find_if(Primary->redecls(),
                               [](const RedeclarableTemplateDecl *RTD) {
                                 return cast<FunctionTemplateDecl>(RTD)
diff --git a/clang/test/SemaCXX/gh185341.cpp b/clang/test/SemaCXX/gh185341.cpp
new file mode 100644
index 0000000000000..fb3ae259ccd6e
--- /dev/null
+++ b/clang/test/SemaCXX/gh185341.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
+
+
+template<class>
+struct D;
+
+template<class T>
+void foo(D<T>);
+
+template<class T>
+struct D {
+  friend void ::foo(D) {} // expected-error {{friend function definition 
cannot be qualified with '::'}}
+};
+
+int main() {
+  foo(D<int>{});
+}
\ No newline at end of file

``````````

</details>


https://github.com/llvm/llvm-project/pull/186398
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to