// { dg-additional-options "-fmodule-header" } // { dg-module-cmi !{} } // external linkage variables or functions in header units must // not have non-inline definitions struct S { int x; }; int x_err; // { dg-error "external linkage definition" } int y_err = 123; // { dg-error "external linkage definition" } auto [d_err] = S{}; // { dg-error "external linkage definition" } void f_err() {} // { dg-error "external linkage definition" } struct Err { Err(); void m(); static void s(); static int x; static int y; }; Err::Err() = default; // { dg-error "external linkage definition" } void Err::m() {} // { dg-error "external linkage definition" } void Err::s() {} // { dg-error "external linkage definition" } int Err::x; // { dg-error "external linkage definition" } int Err::y = 123; // { dg-error "external linkage definition" } // No definition, OK extern int y_decl; void f_decl(); template struct DeductionGuide {}; DeductionGuide() -> DeductionGuide; struct NoDefStatics { enum E { V }; static const int x = 123; static const E e = V; }; // But these have definitions again (though the error locations aren't great) struct YesDefStatics { enum E { V }; static const int x = 123; // { dg-error "external linkage definition" } static const E e = V; // { dg-error "external linkage definition" } }; const int YesDefStatics::x; const YesDefStatics::E YesDefStatics::e; // Inline decls are OK inline int x_inl; inline int y_inl = 123; inline void f_inl() {} constexpr void g_inl() {} void h_inl() = delete; struct Inl { void m() {} static void s() {} static inline int x; static inline int y = 123; }; // Internal linkage decls are OK static int x_internal; static int y_internal = 123; namespace { auto [d_internal] = S{}; } static void f_internal() {} namespace { struct Internal { void m(); static void s(); static int x; static int y; }; void Internal::m() {} void Internal::s() {} int Internal::x; int Internal::y = 123; } // Function-scope entities are OK inline void f_static() { static int x_static; static int y_static = 123; thread_local int x_thread_local; thread_local int y_thread_local = 123; #if __cplusplus >= 202002L static auto [d_static] = S{}; thread_local auto [d_thread_local] = S{}; #endif x_static = y_static; x_thread_local = y_thread_local; } // Templates (not functions or variables) are OK template int x_tpl; template int y_tpl = 123; template void f_tpl() {} struct Template_Body { template void m(); template static void s(); template static int x; template static int y; }; template void Template_Body::m() {} template void Template_Body::s() {} template int Template_Body::x; template int Template_Body::y = 123; template struct Template_Type { void m(); static void s(); static int x; static int y; }; template void Template_Type::m() {} template void Template_Type::s() {} template int Template_Type::x; template int Template_Type::y = 123; // Implicit instantiations are OK inline void instantiate_tmpls() { x_tpl = y_tpl; f_tpl(); Template_Body{}.m(); Template_Body::s(); Template_Body::x = Template_Body::y; using TT = Template_Type; TT{}.m(); TT::s(); TT::x = TT::y; } // Explicit instantiations are also OK (extern or otherwise) template int x_tpl; template int y_tpl; template void f_tpl(); template void Template_Body::m(); template void Template_Body::s(); template int Template_Body::x; template int Template_Body::y; template void Template_Type::m(); template void Template_Type::s(); template int Template_Type::x; template int Template_Type::y; extern template int x_tpl; extern template int y_tpl; extern template void f_tpl(); extern template void Template_Body::m(); extern template void Template_Body::s(); extern template int Template_Body::x; extern template int Template_Body::y; extern template void Template_Type::m(); extern template void Template_Type::s(); extern template int Template_Type::x; extern template int Template_Type::y; // But explicit specialisations are not (though note [temp.expl.spec] p13) template <> int x_tpl; // { dg-error "inline" } template <> int y_tpl = 123; // { dg-error "inline" } template <> void f_tpl() {} // { dg-error "inline" } template <> void Template_Body::m() {} // { dg-error "inline" } template <> void Template_Body::s() {} // { dg-error "inline" } template <> int Template_Body::x; // { dg-bogus "inline" "not a definition" } template <> int Template_Body::y = 123; // { dg-error "inline" } template <> void Template_Type::m() {} // { dg-error "inline" } template <> void Template_Type::s() {} // { dg-error "inline" } template <> int Template_Type::x; // { dg-bogus "inline" "not a definition" } template <> int Template_Type::y = 123; // { dg-error "inline" }