Skip to content

Commit

Permalink
[C++20][Modules] Handle template declarations in header units.
Browse files Browse the repository at this point in the history
This addresses part of llvm#60079

The test for external functions was not considering function templates.

Differential Revision: https://reviews.llvm.org/D142704
  • Loading branch information
iains committed Feb 2, 2023
1 parent 3810f76 commit cdd44e2
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
10 changes: 6 additions & 4 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
Expand Down
31 changes: 31 additions & 0 deletions clang/test/CXX/module/module.import/p6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
}

0 comments on commit cdd44e2

Please sign in to comment.