@@ -10833,6 +10833,10 @@ grokfndecl (tree ctype,
have one: the restriction that you can't repeat a deduction guide
makes them more like a definition anyway. */
DECL_INITIAL (decl) = void_node;
+ /* But to ensure that external-linkage deduction guides in header units
+ don't fall afoul of [module.import] p6, mark them as inline to give
+ the same effect as them not having a definition. */
+ DECL_DECLARED_INLINE_P (decl) = true;
break;
default:
break;
@@ -19943,6 +19943,24 @@ check_module_decl_linkage (tree decl)
if (!module_has_cmi_p ())
return;
+ /* A header unit shall not contain a definition of a non-inline function
+ or variable (not template) whose name has external linkage. */
+ if (header_module_p ()
+ && !processing_template_decl
+ && ((TREE_CODE (decl) == FUNCTION_DECL
+ && !DECL_DECLARED_INLINE_P (decl)
+ && DECL_INITIAL (decl))
+ || (TREE_CODE (decl) == VAR_DECL
+ && !DECL_INLINE_VAR_P (decl)
+ && DECL_INITIALIZED_P (decl)
+ && !DECL_IN_AGGR_P (decl)))
+ && !(DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INSTANTIATION (decl))
+ && decl_linkage (decl) == lk_external)
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "external linkage definition of %qD in header module must "
+ "be declared %<inline%>", decl);
+
/* An internal-linkage declaration cannot be generally be exported.
But it's OK to export any declaration from a header unit, including
internal linkage declarations. */
new file mode 100644
@@ -0,0 +1,172 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi !{} }
+// external linkage variables or functions in header units must
+// not have non-inline definitions
+
+int x_err; // { dg-error "external linkage definition" }
+int y_err = 123; // { 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 <typename> struct DeductionGuide {};
+DeductionGuide() -> DeductionGuide<int>;
+
+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;
+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;
+
+ x_static = y_static;
+ x_thread_local = y_thread_local;
+}
+
+// Templates (not functions or variables) are OK
+template <typename> int x_tpl;
+template <typename> int y_tpl = 123;
+template <typename> void f_tpl() {}
+
+struct Template_Body {
+ template <typename> void m();
+ template <typename> static void s();
+ template <typename> static int x;
+ template <typename> static int y;
+};
+template <typename> void Template_Body::m() {}
+template <typename> void Template_Body::s() {}
+template <typename> int Template_Body::x;
+template <typename> int Template_Body::y = 123;
+
+template <typename> struct Template_Type {
+ void m();
+ static void s();
+ static int x;
+ static int y;
+};
+template <typename T> void Template_Type<T>::m() {}
+template <typename T> void Template_Type<T>::s() {}
+template <typename T> int Template_Type<T>::x;
+template <typename T> int Template_Type<T>::y = 123;
+
+// Implicit instantiations are OK
+inline void instantiate_tmpls() {
+ x_tpl<int> = y_tpl<int>;
+ f_tpl<int>();
+
+ Template_Body{}.m<int>();
+ Template_Body::s<int>();
+ Template_Body::x<int> = Template_Body::y<int>;
+
+ using TT = Template_Type<int>;
+ TT{}.m();
+ TT::s();
+ TT::x = TT::y;
+}
+
+// Explicit instantiations are also OK (extern or otherwise)
+template int x_tpl<char>;
+template int y_tpl<char>;
+template void f_tpl<char>();
+
+template void Template_Body::m<char>();
+template void Template_Body::s<char>();
+template int Template_Body::x<char>;
+template int Template_Body::y<char>;
+
+template void Template_Type<char>::m();
+template void Template_Type<char>::s();
+template int Template_Type<char>::x;
+template int Template_Type<char>::y;
+
+extern template int x_tpl<double>;
+extern template int y_tpl<double>;
+extern template void f_tpl<double>();
+
+extern template void Template_Body::m<double>();
+extern template void Template_Body::s<double>();
+extern template int Template_Body::x<double>;
+extern template int Template_Body::y<double>;
+
+extern template void Template_Type<double>::m();
+extern template void Template_Type<double>::s();
+extern template int Template_Type<double>::x;
+extern template int Template_Type<double>::y;
+
+// But explicit specialisations are not (though note [temp.expl.spec] p13)
+template <> int x_tpl<short>; // { dg-error "inline" }
+template <> int y_tpl<short> = 123; // { dg-error "inline" }
+template <> void f_tpl<short>() {} // { dg-error "inline" }
+
+template <> void Template_Body::m<short>() {} // { dg-error "inline" }
+template <> void Template_Body::s<short>() {} // { dg-error "inline" }
+template <> int Template_Body::x<short>; // { dg-bogus "inline" "not a definition" }
+template <> int Template_Body::y<short> = 123; // { dg-error "inline" }
+
+template <> void Template_Type<short>::m() {} // { dg-error "inline" }
+template <> void Template_Type<short>::s() {} // { dg-error "inline" }
+template <> int Template_Type<short>::x; // { dg-bogus "inline" "not a definition" }
+template <> int Template_Type<short>::y = 123; // { dg-error "inline" }
@@ -6,7 +6,7 @@
#undef FIVE // no effect
import "macro-4_a.H";
-int a;
+inline int a;
#undef THREE
#undef FOUR
#define FOUR 4c
@@ -19,4 +19,4 @@ struct tuple {
= typename _TupleConstraints<Ts...>::template __constructible<Us...>;
};
-tuple<int, int> t;
+inline tuple<int, int> t;
@@ -6,7 +6,7 @@ template<int I> int Fn ()
return I;
}
-template<> int Fn<1> ()
+template<> inline int Fn<1> ()
{
return 0;
}
@@ -3,4 +3,4 @@
module M; // { dg-error "module-declaration not permitted" }
-int i;
+inline int i;
@@ -1,4 +1,4 @@
// { dg-additional-options -fmodule-header }
// { dg-module-cmi {} }
-int i;
+inline int i;
@@ -1,5 +1,5 @@
-int ary[4];
+inline int ary[4];
extern int unb[];
typedef int z[0];