Skip to content

Commit 3f9b92d

Browse files
iainstru
authored andcommitted
[C++20][Modules] Handle template declarations in header units.
This addresses part of #60079 The test for external functions was not considering function templates. Differential Revision: https://reviews.llvm.org/D142704 (cherry picked from commit cdd44e2)
1 parent 006720b commit 3f9b92d

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13088,9 +13088,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
1308813088
// C++ [module.import/6] external definitions are not permitted in header
1308913089
// units.
1309013090
if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
13091-
VDecl->isThisDeclarationADefinition() &&
13091+
!VDecl->isInvalidDecl() && VDecl->isThisDeclarationADefinition() &&
1309213092
VDecl->getFormalLinkage() == Linkage::ExternalLinkage &&
13093-
!VDecl->isInline()) {
13093+
!VDecl->isInline() && !VDecl->isTemplated() &&
13094+
!isa<VarTemplateSpecializationDecl>(VDecl)) {
1309413095
Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit);
1309513096
VDecl->setInvalidDecl();
1309613097
}
@@ -15259,9 +15260,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
1525915260
// FIXME: Consider an alternate location for the test where the inlined()
1526015261
// state is complete.
1526115262
if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
15263+
!FD->isInvalidDecl() && !FD->isInlined() &&
15264+
BodyKind != FnBodyKind::Delete && BodyKind != FnBodyKind::Default &&
1526215265
FD->getFormalLinkage() == Linkage::ExternalLinkage &&
15263-
!FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete &&
15264-
BodyKind != FnBodyKind::Default && !FD->isInlined()) {
15266+
!FD->isTemplated() && !FD->isTemplateInstantiation()) {
1526515267
assert(FD->isThisDeclarationADefinition());
1526615268
Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);
1526715269
FD->setInvalidDecl();

clang/test/CXX/module/module.import/p6.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ int ok_var_decl;
2222

2323
int bad_var_definition = 3; // expected-error {{non-inline external definitions are not permitted in C++ header units}}
2424

25+
/* The cases below should compile without diagnostics. */
26+
2527
class A {
2628
public:
2729
// This is a declaration instead of definition.
@@ -36,3 +38,32 @@ struct S {
3638
S(S&);
3739
};
3840
S::S(S&) = default;
41+
42+
template <class _X>
43+
_X tmpl_var_ok_0 = static_cast<_X>(-1);
44+
45+
template <typename _T>
46+
constexpr _T tmpl_var_ok_1 = static_cast<_T>(42);
47+
48+
inline int a = tmpl_var_ok_1<int>;
49+
50+
template <typename _Tp,
51+
template <typename> class _T>
52+
constexpr int tmpl_var_ok_2 = _T<_Tp>::value ? 42 : 6174 ;
53+
54+
template<class _Ep>
55+
int tmpl_OK (_Ep) { return 0; }
56+
57+
template <class _T1>
58+
bool
59+
operator==(_T1& , _T1& ) { return false; }
60+
61+
constexpr long one_k = 1000L;
62+
63+
template <class ..._Args>
64+
void* tmpl_fn_ok
65+
(_Args ...__args) { return nullptr; }
66+
67+
inline int foo (int a) {
68+
return tmpl_OK (a);
69+
}

0 commit comments

Comments
 (0)