[clang] cdd44e2 - [C++20][Modules] Handle template declarations in header units.

Iain Sandoe via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 2 02:51:21 PST 2023


Author: Iain Sandoe
Date: 2023-02-02T10:51:08Z
New Revision: cdd44e2c85542d152aef19cfd1d2ad451d774935

URL: https://github.com/llvm/llvm-project/commit/cdd44e2c85542d152aef19cfd1d2ad451d774935
DIFF: https://github.com/llvm/llvm-project/commit/cdd44e2c85542d152aef19cfd1d2ad451d774935.diff

LOG: [C++20][Modules] Handle template declarations in header units.

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

The test for external functions was not considering function templates.

Differential Revision: https://reviews.llvm.org/D142704

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0cfabed8c7dc..b2bece4d9db0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13090,9 +13090,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
   // C++ [module.import/6] external definitions are not permitted in header
   // units.
   if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
-      VDecl->isThisDeclarationADefinition() &&
+      !VDecl->isInvalidDecl() && VDecl->isThisDeclarationADefinition() &&
       VDecl->getFormalLinkage() == Linkage::ExternalLinkage &&
-      !VDecl->isInline()) {
+      !VDecl->isInline() && !VDecl->isTemplated() &&
+      !isa<VarTemplateSpecializationDecl>(VDecl)) {
     Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit);
     VDecl->setInvalidDecl();
   }
@@ -15261,9 +15262,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
   // FIXME: Consider an alternate location for the test where the inlined()
   // state is complete.
   if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
+      !FD->isInvalidDecl() && !FD->isInlined() &&
+      BodyKind != FnBodyKind::Delete && BodyKind != FnBodyKind::Default &&
       FD->getFormalLinkage() == Linkage::ExternalLinkage &&
-      !FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete &&
-      BodyKind != FnBodyKind::Default && !FD->isInlined()) {
+      !FD->isTemplated() && !FD->isTemplateInstantiation()) {
     assert(FD->isThisDeclarationADefinition());
     Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);
     FD->setInvalidDecl();

diff  --git a/clang/test/CXX/module/module.import/p6.cpp b/clang/test/CXX/module/module.import/p6.cpp
index 4360d3e67385..0ed8b5958dff 100644
--- a/clang/test/CXX/module/module.import/p6.cpp
+++ b/clang/test/CXX/module/module.import/p6.cpp
@@ -22,6 +22,8 @@ int ok_var_decl;
 
 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,32 @@ struct S {
   S(S&);
 };
 S::S(S&) = default;
+
+template <class _X>
+_X tmpl_var_ok_0 = static_cast<_X>(-1);
+
+template <typename _T>
+constexpr _T tmpl_var_ok_1 = static_cast<_T>(42);
+
+inline int a = tmpl_var_ok_1<int>;
+
+template <typename _Tp,
+          template <typename> class _T>
+constexpr int tmpl_var_ok_2 = _T<_Tp>::value ? 42 : 6174 ;
+
+template<class _Ep>
+int tmpl_OK (_Ep) { return 0; }
+
+template <class _T1>
+bool
+operator==(_T1& , _T1& ) { return false; }
+
+constexpr long one_k = 1000L;
+
+template <class ..._Args>
+void* tmpl_fn_ok
+(_Args ...__args) { return nullptr; }
+
+inline int foo (int a) {
+  return tmpl_OK (a);
+}


        


More information about the cfe-commits mailing list