iains created this revision.
Herald added a project: All.
iains added reviewers: dblaikie, ChuanqiXu.
iains published this revision for review.
iains added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

@dblaikie - I suspect that this would be useful on the llvm-16 release branch, 
and so I've added you as a reviewer, if you have some chance to look ..
 (I do not think @ChuanqiXu is available until February).

The issue here is that the function decl is extracted from function templates 
(and looks just like any other function definition at this point), so that we 
need to remember that it came from a template.


This addresses part of https://github.com/llvm/llvm-project/issues/60079

The test for external functions was not considering function templates.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142704

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CXX/module/module.import/p6.cpp


Index: clang/test/CXX/module/module.import/p6.cpp
===================================================================
--- clang/test/CXX/module/module.import/p6.cpp
+++ clang/test/CXX/module/module.import/p6.cpp
@@ -22,6 +22,8 @@
 
 int bad_var_definition = 3;  // expected-error {{non-inline external 
definitions are not permitted in C++ header units}}
 
+/* The cases below should compile without diagnostics.  */
+
 class A {
 public:
     // This is a declaration instead of definition.
@@ -36,3 +38,10 @@
   S(S&);
 };
 S::S(S&) = default;
+
+template<class _Ep>
+int tmpl_OK (_Ep) { return 0; }
+
+template <class _T1>
+bool
+operator==(_T1& , _T1& ) { return false; }
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -15108,10 +15108,12 @@
   }
 
   FunctionDecl *FD = nullptr;
+  bool IsFnTemplate = false;
 
-  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
     FD = FunTmpl->getTemplatedDecl();
-  else
+    IsFnTemplate = true;
+  } else
     FD = cast<FunctionDecl>(D);
 
   // Do not push if it is a lambda because one is already pushed when building
@@ -15260,7 +15262,7 @@
   // state is complete.
   if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
       FD->getFormalLinkage() == Linkage::ExternalLinkage &&
-      !FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete &&
+      !FD->isInvalidDecl() && !IsFnTemplate && BodyKind != FnBodyKind::Delete 
&&
       BodyKind != FnBodyKind::Default && !FD->isInlined()) {
     assert(FD->isThisDeclarationADefinition());
     Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);


Index: clang/test/CXX/module/module.import/p6.cpp
===================================================================
--- clang/test/CXX/module/module.import/p6.cpp
+++ clang/test/CXX/module/module.import/p6.cpp
@@ -22,6 +22,8 @@
 
 int bad_var_definition = 3;  // expected-error {{non-inline external definitions are not permitted in C++ header units}}
 
+/* The cases below should compile without diagnostics.  */
+
 class A {
 public:
     // This is a declaration instead of definition.
@@ -36,3 +38,10 @@
   S(S&);
 };
 S::S(S&) = default;
+
+template<class _Ep>
+int tmpl_OK (_Ep) { return 0; }
+
+template <class _T1>
+bool
+operator==(_T1& , _T1& ) { return false; }
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -15108,10 +15108,12 @@
   }
 
   FunctionDecl *FD = nullptr;
+  bool IsFnTemplate = false;
 
-  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
     FD = FunTmpl->getTemplatedDecl();
-  else
+    IsFnTemplate = true;
+  } else
     FD = cast<FunctionDecl>(D);
 
   // Do not push if it is a lambda because one is already pushed when building
@@ -15260,7 +15262,7 @@
   // state is complete.
   if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
       FD->getFormalLinkage() == Linkage::ExternalLinkage &&
-      !FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete &&
+      !FD->isInvalidDecl() && !IsFnTemplate && BodyKind != FnBodyKind::Delete &&
       BodyKind != FnBodyKind::Default && !FD->isInlined()) {
     assert(FD->isThisDeclarationADefinition());
     Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to