--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export class Base
+{
+public:
+ int m;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module Bar;
+// { dg-module-cmi Bar }
+
+import Foo;
+
+export class Derived : public Base
+{
+private:
+ using Base::m;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import Bar;
+import Foo;
+
+void foo (Derived *d)
+{
+ d->m = 1; // { dg-error "inaccessible within this context" }
+ static_cast<Base *> (d)->m = 1; //ok
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi bob }
+
+export module bob;
+export int massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea (int);
+ export void massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea (float);
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdiagnostics-show-caret" }
+
+import bob;
+void foo ()
+{
+ massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea ();
+}
+
+// { dg-regexp "\n\[^\n]*adhoc-1_b.C:6:74: error: no matching function for call to 'massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea\\(\\)'\n massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea \\(\\);\n \\^$" }
+// { dg-regexp "\nIn module bob, imported at \[^\n]*adhoc-1_b.C:3:\n\[^\n]*adhoc-1_a.C:5:12: note: candidate: 'int massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea@bob\\(int\\)'\n export int massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea \\(int\\);\n \\^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~$" }
+// { dg-regexp "\nIn module bob, imported at \[^\n]*adhoc-1_b.C:3:\n\[^\n]*adhoc-1_a.C:6:188: note: candidate: 'void massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea@bob\\(float\\)'\n\[ \t]*export void massivelongnamethatcausesadhoclocationsokeepaddingcharsyourgettheidea \\(float\\);\n\[ \t]*\\^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~?$" }
+// For some reason dg-regexp inserts a blank line
+// { dg-allow-blank-lines-in-output 1 }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module worker;
+// { dg-module-cmi worker }
+
+namespace details {
+
+export int fn (int x)
+{
+ return x;
+}
+
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module inter;
+// { dg-module-cmi inter }
+
+import worker;
+
+namespace hidden {
+export int fn (int x)
+{
+ return -x;
+}
+}
+
+export template <typename T>
+int TPL (T &t)
+{
+ return fn (t);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import inter;
+
+namespace details
+{
+
+struct X
+{
+
+ int m;
+ X (int m) : m(m)
+ {
+ }
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+}
+
+namespace hidden
+{
+
+struct Y
+{
+
+ int m;
+ Y (int m) : m(m)
+ {
+ }
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+}
+
+int main ()
+{
+ details::X x(2);
+ hidden::Y y(2);
+
+ // details::fn@worker is visible from TPL@inter
+ if (TPL (x) != 2) // instantiate TPL<details::X>(T&)
+ return 1;
+
+ // hidden::fn@inter is visible from TPL@inter
+ if (TPL (y) != -2) // instantiate TPL<hidden::Y>(T&)
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export template <typename T>
+int TPL (T const &t)
+{
+ return frob (t);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module hidden;
+// { dg-module-cmi hidden }
+
+export struct X
+{
+ int m;
+
+ X(int m) :m(m) {}
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+export int frob (int x)
+{
+ return x;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+import hidden;
+
+int main ()
+{
+ X x (2);
+
+ if (frob (x) != 2)
+ return 1;
+
+ if (TPL (x) != 2)
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module worker;
+// { dg-module-cmi worker }
+
+namespace details {
+
+int fn (int x)
+{
+ return x;
+}
+
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module inter;
+// { dg-module-cmi inter }
+
+export template <typename T>
+int TPL (T &t)
+{
+ return fn (t);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import inter;
+import worker;
+
+namespace details
+{
+struct X
+{
+
+ int m;
+ X (int m) : m(m)
+ {
+ }
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+}
+
+int main ()
+{
+ details::X x(2);
+
+ if (fn (x) != 2) // { dg-error "not declared in" }
+ return 1;
+
+ // { dg-regexp "\n\[^\n]*adl-3_b.C:8:13: error: 'fn' was not declared in this scope$" }
+ if (TPL (x) != 2) // { dg-message "required from here" }
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module inter;
+// { dg-module-cmi inter }
+
+namespace hidden {
+// not found via ADL
+int fn (int x);
+
+}
+
+export template <typename T>
+int TPL (T &t)
+{
+ return fn (t);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import inter;
+
+namespace hidden
+{
+
+struct Y
+{
+
+ int m;
+ Y (int m) : m(m)
+ {
+ }
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+}
+
+int main ()
+{
+ hidden::Y y(2);
+
+ // unexported hidden::fn@inter is not visible from TPL@inter
+ if (TPL (y) != -2)
+ return 2;
+
+ return 0;
+}
+
+// ADL fails
+// { dg-regexp {[^\n]*/adl-4_a.C:14:[0-9]*: error: 'fn' was not declared in this scope\n} }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export template <typename T>
+int TPL (T const &t)
+{
+ return frob (t);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module hidden;
+// { dg-module-cmi hidden }
+
+export struct X
+{
+ int m;
+
+ X(int m) :m(m) {}
+
+ operator int () const
+ {
+ return m;
+ }
+};
+
+// Not found via any ADL outside of module hidden
+int frob (int x)
+{
+ return x;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module hidden;
+import foo;
+
+int frob ()
+{
+ X x (2);
+
+ if (frob (x) != 2)
+ return 1;
+
+ if (TPL (x) != 2)
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+import hidden;
+
+int main ()
+{
+ X x (2);
+
+ if (frob (x) != 2)
+ return 1;
+
+ if (TPL (x) != 2)
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodule-header -isystem [srcdir]" }
+// { dg-module-cmi {} }
+
+#ifndef ALIAS_1_A
+#define ALIAS_1_A
+
+int frob ();
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir]" }
+
+// Alias at the header file. We have one CMI file
+import "alias-1_a.H";
+import <alias-1_a.H>;
+
+int main ()
+{
+ frob ();
+}
+
+// { dg-final { scan-lang-dump-times {CMI is } 1 module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+// { dg-module-cmi bob }
+
+export module bob;
+import "alias-1_a.H";
--- /dev/null
+// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+// { dg-module-cmi kevin }
+
+export module kevin;
+import <alias-1_a.H>;
--- /dev/null
+// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+
+import bob;
+import kevin;
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir]" }
+
+import kevin;
+import bob;
--- /dev/null
+// { dg-additional-options "-fmodule-header -isystem [srcdir]/sys" }
+// { dg-module-cmi {} }
+// { dg-module-headers test sys/alias-2_a.H }
+#ifndef ALIAS_2_A
+#define ALIAS_2_A
+
+int frob ();
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir]/sys" }
+
+// These find different headers
+import "alias-2_a.H";
+import <alias-2_a.H>;
+
+int main ()
+{
+ frob ();
+ frob (1);
+}
+
+// { dg-final { scan-lang-dump-times {CMI is} 2 module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export using aint = __attribute__ ((aligned(16))) int;
+
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+struct B
+{
+ aint m;
+};
+
+static_assert (alignof (B) == 16);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module One;
+// { dg-module-cmi One }
+
+export int foo ();
+export char bax ();
+export int quux (float);
+
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import One;
+
+int foo (); // { dg-error "conflicts with import" }
+int bax (); // { dg-error "ambiguating new declaration" }
+int quux (int);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module anon;
+// { dg-module-cmi anon }
+
+export struct foo
+{
+ enum {bob};
+ union
+ {
+ int i;
+ float f;
+ };
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module namer;
+// { dg-module-cmi namer }
+
+import anon;
+
+export inline int &get_int (foo &obj)
+{
+ return obj.i;
+}
+
+export inline float &get_float (foo &obj)
+{
+ return obj.f;
+}
+
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import namer;
+import anon;
+
+int main ()
+{
+ foo obj;
+ int *ip = &get_int (obj);
+ float *fp = &get_float (obj);
+
+ return !((void *)ip == (void *)fp);
+}
--- /dev/null
+
+
+struct __pthread_cond_s
+{
+ union {};
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "anon-2.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "anon-2.h"
+import "anon-2_a.H";
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module thing;
+// { dg-module-cmi "thing" }
+
+export int baz ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import thing;
+
+void bink ()
+{
+ baz ();
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module pop;
+// { dg-module-cmi "pop" }
+export import thing;
+
+void bink ();
+
+void bonk ()
+{
+ baz ();
+ bink ();
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module thing;
+int i;
+import baz; // { dg-error "must be contiguous" }
+
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+int i;
+import bazza;
+// { dg-error "failed to read" "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+#pragma bob
+int i;
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+export module foo;
+// { dg-module-cmi !foo }
+;
+
+#pragma pack(2)
+import baz; // { dg-error "must be contiguous" }
+
+int i;
+
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+#define EXPORT export // { dg-error "only occur after a module" }
+EXPORT module bob; // { dg-error "does not name a type" }
+// { dg-message "not recognized as" "" { target *-*-* } .-1 }
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+#define malcolm kevin
+export module malcolm;
+// { dg-module-cmi kevin }
+
+export class X;
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+#if 1
+export module bob;
+// { dg-module-cmi bob }
+#endif
+
+import kevin;
+
+X *f;
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+#pragma bob
+
+import kevin;
+
+X *f;
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import kevin;
+
+#if 1
+#if 1
+import kevin;
+#endif
+#elif 1
+int i;
+#endif
+
+int j; // end here
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import kevin;
+
+#if 0
+#if 1
+import kevin;
+#endif
+#elif 1
+import kevin;
+#endif
+
+int i; // end here
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+export module stuart;
+// { dg-module-cmi !stuart }
+
+# 6 "atom-preamble-2_f.C" 1
+import kevin; // { dg-error "not be from header" }
+# 8 "" 2
+
+import kevin; // ok
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+#define import import
+import malcolm; // { dg-error "object-like macro" }
+// { dg-error "failed to read" "" { target *-*-* } 0 }
+
+// { dg-prune-output "compilation terminated" }
+// { dg-prune-output "fatal error:" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+#define NAME(X) X;
+
+export module NAME(bob)
+
--- /dev/null
+
+template <typename T> auto frob (T t)
+{
+ return t;
+}
+
+struct Bob
+{
+ operator auto ()
+ {
+ return 0;
+ }
+};
+
+inline auto foo ()
+{
+ return frob (1) + int (Bob ());
+}
+
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "auto-1.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "auto-1.h"
+import "auto-1_a.H";
+
+int bar ()
+{
+ return foo () + frob (0u);
+}
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+
+template<typename _Callable>
+struct _RangeAdaptor
+{
+ constexpr _RangeAdaptor(const _Callable &) { }
+};
+
+template<typename _Callable>
+_RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>;
+
+template<unsigned _Nm>
+inline constexpr _RangeAdaptor elements = [] (auto&& __r) {};
+
--- /dev/null
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "auto-2.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts -fdump-lang-module-alias -fno-module-lazy" }
+
+#include "auto-2.h"
+import "auto-2_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=|this-will-not-work" }
+import unique1.bob;
+// { dg-error "-:failed exec.*mapper.* .*this-will-not-work" "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "compilation terminated" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=not-a-host:3838" }
+import unique2.bob;
+// { dg-error "failed .* mapper 'not-a-host" "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "compilation terminated" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=localhost:172477262" }
+import unique3.bob;
+// { dg-error {failed connecting mapper 'localhost:172477262'} "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "compilation terminated" }
--- /dev/null
+$root .
+module:import partitions/module:import.mod
+module module.mod
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/ben-1.map" }
+// { dg-additional-files ben-1.map }
+
+export module module:import;
+// { dg-module-cmi =partitions/module:import.mod }
+
+export int b() {
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/ben-1.map" }
+// { dg-additional-files ben-1.map }
+
+export module module;
+// { dg-module-cmi =module.mod }
+export import :import;
+
+export int c ()
+{
+ return b ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export struct timex
+{
+ int a;
+ int :32;
+ int :32;
+ int :32;
+ int :32;
+ int :32;
+ int :32;
+};
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import foo;
+
+timex v = {1};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct ting
+{
+ int a;
+ int b : 3;
+ int c : 5;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import foo;
+
+ting v = {1, 2, 3};
--- /dev/null
+typedef signed char __v16qs __attribute__ ((__vector_size__ (16)));
+
+
+inline auto
+_mm_cmplt_epi8 (__v16qs __A, __v16qs __B)
+{
+ return __A < __B;
+}
--- /dev/null
+// { dg-additional-options {-fmodule-header -Wno-psabi} }
+// { dg-module-cmi {} }
+
+#include "bool-1.h"
--- /dev/null
+// { dg-additional-options {-fmodule-header -fno-module-lazy -Wno-psabi} }
+// { dg-module-cmi {} }
+
+#include "bool-1.h"
+import "bool-1_a.H";
--- /dev/null
+// { dg-additional-options {-fmodules-ts -Wno-psabi} }
+
+import "bool-1_b.H";
+
+void frob (signed char __attribute__ ((__vector_size__ (16))) arg)
+{
+ _mm_cmplt_epi8 (arg, arg);
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export int Frob (int a)
+{
+ return -a;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int main ()
+{
+ if (Frob (2) != -2)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias-uid" }
+export module builtin;
+// { dg-module-cmi builtin }
+
+export inline void ary_del (int *ptr)
+{
+ delete[] ptr;
+}
+
+export inline void scalar_del (int *ptr)
+{
+ delete ptr;
+}
+
+// { dg-final { scan-lang-dump {Wrote GMF:-[0-9]* function_decl:'::operator delete'@builtin} module } }
+// { dg-final { scan-lang-dump {Wrote GMF:-[0-9]* function_decl:'::operator delete \[\]'@builtin} module } }
+
+// { dg-final { scan-lang-dump {Writing named:-[0-9]* function_decl:'::operator delete'\n *Wrote[^\n]*\n *Writing:-[0-9]*'s named merge key \(decl\) function_decl:'::operator delete'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+import builtin;
+
+int main ()
+{
+ ary_del (nullptr);
+ scalar_del (nullptr);
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) function_decl:'::operator delete \[\]'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) function_decl:'::operator delete'} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+extern "C"
+{
+ extern int printf (const char *__restrict __format, ...);
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+import builtins;
+
+int main ()
+{
+ length ("");
+ count (1, "", "", nullptr);
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) function_decl:'::__builtin_strlen'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) type_decl:'::__builtin_va_list'} module { target { x86_64-*-linux* } } } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) type_decl:'::va_list'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) type_decl:'::__gnuc_va_list'} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+void* operator new(__SIZE_TYPE__);
+void* operator new[](__SIZE_TYPE__);
+
+void operator delete (void*) noexcept;
+void operator delete[](void*) noexcept;
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+import "builtin-4_a.H";
+
+int main ()
+{
+ operator delete (operator new (10));
+ operator delete[] (operator new[] (10));
+}
+
+// { dg-final { scan-lang-dump {named merge key \(matched\) function_decl:'::operator new'} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) function_decl:'::operator delete'} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) function_decl:'::operator new \[\]'} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) function_decl:'::operator delete \[\]'} module } }
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+extern "C" int printf (char const *, ...);
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+import "builtin-5_a.H";
+
+void foo ()
+{
+ printf ("bob\n");
+}
+
+extern "C" int printf (char const *, int);
+
+// { dg-regexp {[^\n]*builtin-5_b.C:10:[0-9]*: error: conflicting declaration of C function 'int printf\(const char\*, int\)'\nIn module [^\n]*builtin-5_a.H, imported at [^\n]*builtin-5_b.C:3:\n[^\n]*builtin-5_a.H:3:[0-9]*: note: previous declaration 'int printf\(const char\*, ...\)'} }
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(matched\) function_decl:'::printf'} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+extern "C" {
+
+static double sin (double)
+{
+ // extra small angle approximation :)
+ return 0.0;
+}
+
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+
+import "builtin-6_a.H";
+
+int main ()
+{
+ return sin (0.0);
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module_cmi {} }
+
+extern "C"
+{
+extern double nan(const char *);
+inline long double nanl(const char * __x) { return nan(__x); }
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "builtin-7_a.H";
+
+void f ()
+{
+ nanl ("");
+}
--- /dev/null
+// check internals by name unless SCC
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+export module frob;
+// { dg-module-cmi frob }
+
+class X
+{
+ int i;
+};
+
+export X *f ();
+
+// { dg-final { scan-lang-dump {Wrote purview:-[0-9]* type_decl:'::X'} "module" } }
+// { dg-final { scan-lang-dump {Indirect:-[0-9]* decl's type record_type:'::X'} "module" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Const;
+// { dg-module-cmi "Const" }
+
+export constexpr int SQ (int b)
+{
+ return b * b;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import Const;
+
+static_assert (SQ(88) == 88 * 88, "waaa!");
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module sqrt;
+// { dg-module-cmi "sqrt" }
+
+export constexpr unsigned sqrt (unsigned X, unsigned x = 1)
+{
+ // Newton-Raphson, not binary restoring
+ // x <= x - f(x)/f'(x)
+ // f(x) = x^2 - X
+ // f'(x) = 2x
+ // x <= x - (x^2 - X) / 2x
+ // x <= x - x/2 + X/2x
+ // x <= x/2 + X/2x
+ // x <= 1/2(x + X/x)
+ unsigned nx = (x + X/x) / 2;
+ if (nx != x)
+ nx = sqrt (X, nx);
+ return nx;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import sqrt;
+
+static_assert (sqrt(81) == 9, "waaa!");
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Bob;
+// { dg-module-cmi Bob }
+
+export int bob ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Kevin;
+// { dg-module-cmi Kevin }
+
+import Bob;
+
+export int kevin ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Bob; // { dg-message "declared here" }
+// No need to dg-module-cmi
+
+import Kevin;
+// { dg-error "failed to read" "" { target *-*-* } 0 }
+// { dg-error "cannot import module" "" { target *-*-* } 0 }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module;
+import Kevin;
+
+export module Bob; // { dg-error "module already imported" }
+// { dg-message "imported here" "Kevin.nms:" { target *-*-* } 0 }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+namespace Bob
+{
+ struct X;
+ export struct Y {
+ unsigned a;
+ unsigned b;
+ };
+}
+
+export void copy (Bob::Y *, const Bob::Y *);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module One;
+
+struct Bob::X
+{
+ int i;
+};
+
+
+int x = sizeof (Bob::X);
+
+void copy (Bob::Y *dst, Bob::Y const *src)
+{
+ dst->a = src->a;
+ dst->b = src->b;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int y = sizeof (Bob::Y);
+
+unsigned Foo (Bob::Y *ptr)
+{
+ return ptr->a + ptr->b;
+}
+
+int main ()
+{
+ if (y != 2 * sizeof (int))
+ return 1;
+
+ unsigned pun[4];
+ pun[0] = 0xdeadbeef;
+ pun[1] = 0xfeedface;
+ pun[2] = 0x8badf00d;
+ pun[3] = 0xcafed00d;
+
+ copy ((Bob::Y *)pun, (Bob::Y *)&pun[2]);
+
+ if (pun[0] != 0x8badf00d)
+ return 2;
+ if (pun[1] != 0xcafed00d)
+ return 3;
+ if (pun[2] != 0x8badf00d)
+ return 4;
+
+ if (Foo ((Bob::Y *)&pun[1]) != 0xcafed00d + 0x8badf00d)
+ return 5;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// This sequence is for errors
+
+export module One;
+// { dg-module-cmi "One" }
+
+namespace Bob
+{
+ struct X;
+ export struct Y {
+ unsigned a;
+ unsigned b;
+ };
+}
+
+export void copy (Bob::Y *, const Bob::Y *);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int z = sizeof (Bob::X); // { dg-error "not a member of .Bob." }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct X
+{
+ X (int, int);
+ X (int a_)
+ : a(a_), b (a_ << 16)
+ {
+ }
+ int a;
+ int b;
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+export module Two;
+
+export import One;
+
+export inline void Frob (X &q)
+{
+ q.b = q.a;
+}
+
+// { dg-final { scan-lang-dump {Wrote import:-1 type_decl:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Indirect:-2 decl's type record_type:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* type_decl:'::X@One:.'@One} module } }
+// { dg-final { scan-lang-dump {Indirect:-[0-9]* decl's type record_type:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* type_decl:'::X@One:.'@One} module } }
+// { dg-final { scan-lang-dump {Indirect:-[0-9]* decl's type record_type:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Wrote member:-[0-9]* field_decl:'::X@One:.::a'} module } }
+// { dg-final { scan-lang-dump {Wrote member:-[0-9]* field_decl:'::X@One:.::b'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module One;
+
+X::X (int a_, int b_)
+ : a (a_), b (b_)
+{
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+import Two;
+
+int main ()
+{
+ X x (0xdead, 0xbeef);
+
+ if (x.a != 0xdead || x.b != 0xbeef)
+ return 1;
+
+ Frob (x);
+ if (x.b != 0xdead)
+ return 2;
+
+ X y (0xcafe);
+ if (y.a != 0xcafe || y.b != 0xcafe << 16)
+ return 3;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Imported:-1 type_decl:'::X@One:.'@One} module } }
+// { dg-final { scan-lang-dump {Indirect:-2 decl's type record_type:'::X@One:.'} module } }
+// { dg-final { scan-lang-dump {Read member:-[0-9]* field_decl:'::X@One:.::a'} module } }
+// { dg-final { scan-lang-dump {Read member:-[0-9]* field_decl:'::X@One:.::b'} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct base
+{
+ int b;
+
+ base (int b_)
+ : b (b_)
+ {
+ }
+
+};
+
+export struct derived : base
+{
+ int d;
+
+ derived (int b_, int d_)
+ : base (b_), d (d_)
+ {
+ }
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int main ()
+{
+ base b (0xfeed);
+ if (!(b.b == 0xfeed))
+ return 1;
+
+ derived d (0xcafe, 0xbeef);
+ if (!(d.b == 0xcafe && d.d == 0xbeef))
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct base
+{
+ int b;
+
+ base (int b_)
+ : b (b_)
+ {
+ }
+
+ virtual int getter () const;
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module One;
+
+int base::getter () const
+{
+ return b;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int vcall (base *ptr)
+{
+ return ptr->getter ();
+}
+
+int main ()
+{
+ base b (0xfeed);
+
+ if (!(vcall (&b) == 0xfeed))
+ return 1;
+
+ return 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct base
+{
+ int b;
+
+ base (int b_)
+ : b (b_)
+ {
+ }
+
+ virtual int getter () const;
+};
+
+export struct pad
+{
+ int pad;
+ virtual ~pad ();
+};
+
+export struct derived : pad, virtual base
+{
+ derived (int v)
+ :base (v)
+ {
+ }
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module One;
+
+pad::~pad ()
+{
+}
+
+int base::getter () const
+{
+ return b;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import One;
+
+int vcall (derived *ptr)
+{
+ return ptr->getter ();
+}
+
+int main ()
+{
+ derived b (0xfeed);
+
+ if (!(vcall (&b) == 0xfeed))
+ return 1;
+
+ return 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module One;
+// { dg-module-cmi "One" }
+
+export struct base
+{
+ long long b;
+
+ base (int b_)
+ :b (b_)
+ {
+ }
+
+ base ()
+ :b(99)
+ {
+ }
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Two;
+// { dg-module-cmi "Two" }
+import One;
+
+export struct middle : virtual base
+{
+ long long m;
+
+ middle (int b_, int m_)
+ : base (b_), m (m_)
+ {
+ }
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import One;
+import Two;
+
+struct derived : middle
+{
+ long long d;
+
+ derived (int b_, int m_, int d_)
+ : middle (b_, m_), d (d_)
+ {
+ }
+};
+
+int check (derived *d)
+{
+ if ((char *)&d->b != (char *)&d->d + sizeof (long long))
+ return 3;
+ if ((char *)&d->d != (char *)&d->m + sizeof (long long))
+ return 4;
+ return 0;
+}
+
+
+int main ()
+{
+ middle m (1, 2);
+
+
+ if (m.b != 1 || m.m != 2)
+ return 1;
+
+ derived d (1, 2, 3);
+
+ if (d.b != 99 || d.m != 2 || d.d != 3)
+ return 2;
+
+ return check (&d);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+class A;
+
+class B
+{
+};
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+module foo;
+
+// completes class A from interface
+class A
+{
+};
+
+void bill ()
+{
+ A a;
+}
+
+// redeclaration of class B{} from interface
+class B;
+
+void bob ()
+{
+ B b;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::A'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Lazily binding '::B'@'foo' section:} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _CharT >
+struct basic_string
+{
+ template<typename = unsigned> basic_string();
+};
+
+inline basic_string<char>
+to_string ()
+{
+ basic_string<char> __str;
+
+ return __str;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+void frob ()
+{
+ to_string ();
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T>
+requires (!!sizeof (bool (T{})))
+T f1 (T x)
+{ return x; }
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+import foo;
+
+struct X {};
+
+void foo (int i, X &x)
+{
+ f1 (i); // ok
+ f1 (x); // { dg-error "no match" }
+}
+
+// { dg-regexp {[^\n]*concept-1_a.C:7:[0-9]*: error: invalid cast[^\n]*\n} }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T>
+requires (sizeof (T) == 1)
+ char f1 (T x) { return 0; }
+
+export template<typename T>
+requires (sizeof (T) != 1)
+ int f1 (T x) { return 0; }
+
+void foo (int i, char c)
+{
+ static_assert (sizeof (f1 (i)) == sizeof (int));
+ static_assert (sizeof (f1 (c)) == sizeof (char));
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+import foo;
+
+void foo (int i, char c)
+{
+ static_assert (sizeof (f1 (i)) == sizeof (int));
+ static_assert (sizeof (f1 (c)) == sizeof (char));
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo
+{
+export template<typename _Tp>
+concept Addable = requires(_Tp& __t)
+ {
+ __t + __t;
+ };
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+
+import foo;
+
+template <foo::Addable T> T Add (T a, T b)
+{
+ return a + b;
+}
+
+void frob ()
+{
+ Add (1, 2);
+ Add ((int *)0, (int *)0); // { dg-error "no match" }
+}
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+
+template<typename T>
+inline constexpr bool disable = false;
+
+template<typename U>
+concept sized = true;
+
+template<typename V>
+class TPL
+{
+};
+
+template<typename W>
+requires (!sized<W>)
+inline constexpr bool disable<TPL<W>>
+= true;
--- /dev/null
+template<typename T>
+requires (sizeof (T) == 1)
+constexpr int f1 (T x) { return 1; }
+
+template<typename T>
+requires (sizeof (T) != 1)
+constexpr int f1 (T x) { return 0; }
--- /dev/null
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "concept-5.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts -fdump-lang-module-alias" }
+
+#include "concept-5.h"
+import "concept-5_a.H";
+
+static_assert (f1 ('a') == 1);
+static_assert (f1 (0xa) == 0);
+
+// { dg-final { scan-lang-dump-times {named merge key \(matched\) template_decl:'::template f1'} 2 module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+
+template<typename _Callable>
+struct Base
+{
+ Base (const _Callable &)
+ requires true
+ {}
+};
+
+template<typename _Callable>
+struct Derived : Base<_Callable>
+{
+ using Base<_Callable>::Base;
+};
+
+template<typename _Callable>
+Derived (_Callable) -> Derived<_Callable>;
+
+inline Derived all = [] (auto&& __r) {};
--- /dev/null
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "concept-6.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts -fdump-lang-module-alias -fno-module-lazy" }
+
+#include "concept-6.h"
+import "concept-6_a.H";
+
+// { dg-final { scan-lang-dump-times {named merge key \(matched\) function_decl:'::Derived<::._anon_0>::__ct '} 6 module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++20" }
+
+export module M;
+// { dg-module-cmi M }
+
+export template <typename T0>
+struct traits
+{
+ static constexpr int variant = 0;
+};
+
+// #2
+template <typename T2>
+requires requires { typename T2::element_type; }
+struct traits<T2 *>
+{
+ using type = typename T2::element_type;
+ static constexpr int variant = 2;
+};
+
+
+// #1
+template <typename T1>
+struct traits<T1 *>
+{
+ using type = T1;
+ static constexpr int variant = 1;
+};
+
+
+// #3
+template <typename T3>
+requires requires { typename T3::value_type; }
+struct traits<T3 *>
+{
+ using type = typename T3::value_type;
+ static constexpr int variant = 3;
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++20" }
+
+import M;
+
+struct Variant0
+{
+};
+
+
+struct Variant2
+{
+ using element_type = double;
+};
+
+struct Variant3
+{
+ using value_type = float;
+};
+
+void f()
+{
+ using v0 = traits<Variant0>;
+ using v1 = traits<Variant0 *>;
+ using v2 = traits<Variant2 *>;
+ using v3 = traits<Variant3 *>;
+
+ static_assert (v0::variant == 0);
+ static_assert (v1::variant == 1);
+ static_assert (v2::variant == 2);
+ static_assert (v3::variant == 3);
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module frob;
+// { dg-module-cmi "frob" }
+
+export struct A
+{
+ operator int ()
+ {
+ return 0;
+ }
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import frob;
+
+int main ()
+{
+ A a;
+
+ if (static_cast<int> (a))
+ return 1;
+ return 0;
+}
--- /dev/null
+// { dg-do preprocess }
+
+module bob;
+#if 1
+export import stuart;
+#else
+import kevin;
+#endif
+import gru;
+#define EXPORT
+EXPORT import mabel;
+int i;
+
+// { dg-final { scan-file cpp-1.i "cpp-1.C\"\n\n\nmodule bob;\n\nexport import stuart;\n\n\n\nimport gru;\n\n import mabel;\n" } }
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+#define STRING_H
+#define NOPE
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#define STDIO_H
+#define think THIS IS STDIO
+#define CLOSE ]]
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts" }
+
+module bob;
+#pragma GCC unused
+import "./cpp-2_b.H" [[ CLOSE ]];
+import "cpp-2_a.H" [[ CLOSE;
+int i;
+#ifndef NOPE
+import nope;
+#endif
+think
+
+// { dg-final { scan-file cpp-2_c.i {cpp-2_c.C"\n\n\n\nmodule bob;\n#pragma GCC unused\nimport "[^\n]*\./cpp-2_b.H" \[\[ CLOSE ]];\nimport "[^\n]*cpp-2_a.H" \[\[ ]];\n} } }
+// { dg-final { scan-file cpp-2_c.i "int i;" } }
+// { dg-final { scan-file-not cpp-2_c.i "import *nope;" } }
+// { dg-final { scan-file cpp-2_c.i "THIS IS STDIO\n" } }
--- /dev/null
+// { dg-do preprocess }
+
+#define NAME(X) X;
+
+export module NAME(bob)
+
+int i;
+// { dg-final { scan-file cpp-3.i "\nexport module bob;\n" } }
+// { dg-final { scan-file cpp-3.i "\nint i;\n" } }
--- /dev/null
+// { dg-do preprocess }
+
+#if 1
+#include "cpp-4.h"
+#endif
+
+// { dg-final { scan-file cpp-4.i "/cpp-4.h\\\" 1" } }
+// { dg-final { scan-file cpp-4.i "/cpp-4.C\\\" 2" } }
+// { dg-final { scan-file cpp-4.i "import x;\n" } }
+// { dg-final { scan-file cpp-4.i "int" } }
--- /dev/null
+#if 1
+import x;
+int i; // end here in middle of #if (ok)
+#endif
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef AA
+#define AA
+
+#define Q 0
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// missing semicolon
+import "cpp-5_a.H" // { dg-error "expected" }
+
+int main ()
+{
+}
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts" }
+#define Q 0
+#undef Q
+
+import "cpp-5_a.H";
+
+Q
+
+// { dg-final { scan-file cpp-5_c.i {\nimport "[^\n]*cpp-5_a.H";\n\n0\n} } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+#define bibity cpp-6_b.H
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#define bobity cpp-6_b
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+
+#define empty
+#define nop(X) X
+
+ONE bibity bobity
+import <cpp-6_a.H>;
+TWO bibity bobity
+import empty nop(<bibity>);
+THREE bibity bobity
+import empty <bobity.H>;
+FOUR bibity bobity
+
+// { dg-final { scan-file cpp-6_c.i {ONE bibity bobity\n} } }
+// { dg-final { scan-file cpp-6_c.i {TWO cpp-6_b.H bobity\n} } }
+// { dg-final { scan-file cpp-6_c.i {THREE cpp-6_b.H cpp-6_b\n} } }
+// { dg-final { scan-file cpp-6_c.i {FOUR cpp-6_b.H cpp-6_b\n} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -g" }
+
+export module frob;
+// { dg-module-cmi frob }
+
+export struct thingy
+{
+ virtual void X ()
+ {
+ thingy w;
+ }
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts -g" }
+
+import frob;
+
+struct thongy : thingy
+{
+ void X ()
+ {
+ thongy w;
+ }
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+export module foo;
+// { dg-module-cmi foo }
+
+struct tuple { int a, b, c;};
+
+tuple maker ();
+
+export inline int bob ()
+{
+ auto [a, b, c] = maker ();
+
+ return a + b + c;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+import foo;
+
+void x ()
+{
+ bob ();
+}
+
--- /dev/null
+template<bool _Const>
+struct _Iterator
+{
+private:
+ static void mover (const _Iterator &arg = {}) noexcept (noexcept (arg));
+
+public:
+ _Iterator() = default;
+
+ friend void move (const _Iterator &arg2) noexcept (noexcept (mover (arg2)))
+ {}
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "deferred-1.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "deferred-1.h"
+import "deferred-1_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -MD" }
+
+export module m:part;
+// { dg-module-cmi m:part }
+
+// All The Backslashes!
+// { dg-final { scan-file dep-1_a.d {\nm\\:part\.c\+\+m: gcm.cache/m-part\.gcm} } }
+// { dg-final { scan-file dep-1_a.d {\ngcm.cache/m-part\.gcm:| dep-1_a\.o} } }
+// { dg-final { scan-file dep-1_a.d {\n\.PHONY: m\\:part\.c\+\+m} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -MD" }
+export module m;
+// { dg-module-cmi m }
+
+export import :part;
+// { dg-final { scan-file dep-1_b.d {\ndep-1_b\.s gcm.cache/m\.gcm: m\\:part\.c\+\+m} } }
+// { dg-final { scan-file dep-1_b.d {\nm\.c\+\+m: gcm.cache/m\.gcm} } }
+// { dg-final { scan-file dep-1_b.d {\n\.PHONY: m\.c\+\+m} } }
+// { dg-final { scan-file dep-1_b.d {\ngcm.cache/m\.gcm:| dep-1_b.o} } }
+// { dg-final { scan-file dep-1_b.d {\nCXX_IMPORTS \+= m\\:part\.c\+\+m} } }
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -MD" }
+
+module m:part;
+// { dg-module-cmi !m:part }
+
+// All The Backslashes!
+// { dg-final { scan-file dep-2.d {\nm\\:part\.c\+\+m: gcm.cache/m-part\.gcm} } }
+// { dg-final { scan-file dep-2.d {\ngcm.cache/m\\:part\.gcm:| dep-2\.o} } }
+// { dg-final { scan-file dep-2.d {\n\.PHONY: m\\:part\.c\+\+m} } }
+
+// { dg-final { scan-file dep-2.i {\nmodule m:part;\n} } }
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -MD -Mno-modules" }
+
+module m:part;
+// { dg-module-cmi !m:part }
+
+// All The Backslashes!
+// { dg-final { scan-file-not dep-3.d {part\.gcm} } }
+// { dg-final { scan-file-not dep-3.d {part\.c\+\+m} } }
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options -fdirectives-only }
+
+#define major NO NOT ME
+
+#ifdef major
+# undef major
+#else
+# error major not initially defined
+#endif
+
+#ifdef major
+# error major still defined
+#endif
+
+// { dg-final { scan-file dir-only-1.i "#undef major\n" } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#define X 1
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -fdirectives-only -isystem [srcdir]" }
+// a comment
+module; // line
+frob
+export
+import foo; // line
+import 7;
+
+im\
+port \
+sing;
+// comment
+import "dir-only-2_a.H";
+import <dir-only-2_a.H>;
+X
+#if !X
+#error "no X!"
+#endif
+export module bob;
+
+export import q;
+
+// { dg-final { scan-file dir-only-2_b.i {// a comment\nmodule ;\nfrob} } }
+// { dg-final { scan-file dir-only-2_b.i {frob\nexport\nimport foo;\nimport 7;} } }
+// { dg-final { scan-file dir-only-2_b.i {import "[^\n]*/dir-only-2_a.H";\nimport "[^\n]*/dir-only-2_a.H";\nX} } }
+// { dg-final { scan-file dir-only-2_b.i {export module bob;\n\nexport import q;} } }
+// { dg-final { scan-file dir-only-2_b.i {import sing;\n\n\n// comment} } }
--- /dev/null
+# 0 "dir-only-3.C"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 31 "<command-line>"
+# 1 "/usr/include/stdc-predef.h" 1 3 4
+
+# 32 "<command-line>" 2
+# 1 "dir-only-3.C"
+// { dg-additional-options {-fmodules-ts -fpreprocessed -fdirectives-only} }
+// { dg-module-cmi foo }
+module;
+#define foo baz
+export module foo;
+
+class import {};
+
+import
+x;
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fpreprocessed -fdirectives-only} }
+// { dg-module-cmi !foo }
+module;
+#define foo baz
+export module foo;
+
+class import {};
+
+import x; // { dg-error "post-module-declaration" }
+ // { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fpreprocessed} }
+module;
+
+; export module Hello; // { dg-error "global module fragment" }
+// { dg-error "after a module interface" "" { target *-*-* } .-1 }
+// { dg-error "not name a type" "" { target *-*-* } .-2 }
+// { dg-message "not recognized as a module control-line" "" { target *-*-* } .-3 }
+
+void SayHello ();
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+export module enUm;
+// { dg-module-cmi "enUm" }
+
+export enum Bill
+{
+ Zero,
+ One,
+ Three = 3
+};
+
+export enum class Ben
+{
+ Zero,
+ Two = 2,
+ Three
+};
+
+export inline Ben func1 ()
+{
+ return Ben::Three;
+}
+
+export inline Ben func2 ()
+{
+ return Ben (4);
+}
+
+// { dg-final { scan-lang-dump-times {Written enum value '::Ben::Three'} 2 module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import enUm;
+
+Bill x = Three;
+Ben y = Ben::Three;
+
+int main ()
+{
+ if (x != 3)
+ return 1;
+
+ if (int (y) != 3)
+ return 2;
+
+ if (int (func1 ()) != 3)
+ return 3;
+
+ if (int (func2 ()) != 4)
+ return 4;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct X
+{
+ enum q
+ {
+ frob
+ };
+};
+
+export template <int I> struct TPL
+{
+ enum p
+ {
+ u,
+ v = I
+ };
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+int i = X::frob;
+
+int k = TPL<2>::v;
+
+static_assert (!TPL<1>::u);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+// from https://godbolt.org/beta/z/V45BSw
+
+export module m0;
+// { dg-module-cmi m0 }
+namespace m0_ns
+{
+template <typename T> struct s0 {
+ enum t { a };
+};
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module m0;
+
+static_assert (!m0_ns::s0<int>::a);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export template <typename T, typename U>
+struct same
+{
+ enum { value = 0 };
+};
+
+template<typename T>
+struct same <T, T>
+{
+ enum { value = 1 };
+};
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+static_assert (same<int, float>::value == 0);
+static_assert (same<int *, int *>::value == 1);
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+enum
+{
+ Zero,
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import "enum-5_a.H";
+
+int i = Zero;
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+enum { _S_chunk_size = 7 };
+
+template<typename T> T getter ()
+{
+ return _S_chunk_size;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "enum-6_a.H";
+
+int main ()
+{
+ return !(getter<int> () == 7);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+// ICE getting template info of a function-scope enum
+
+template <typename T> void adl (T) {}
+
+template <typename T>
+void frob (T arg)
+{
+ enum class case_conv {none};
+
+ case_conv x = case_conv::none;
+
+ adl (x);
+}
+
+void foo ()
+{
+ frob (1);
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+
+enum : char
+{
+ Foo = 1,
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+
+enum : int
+{
+ Foo = 2,
+};
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fno-module-lazy} }
+
+export module Char;
+
+import "enum-8_a.H";
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fno-module-lazy -fdump-lang-module-alias} }
+
+import "enum-8_b.H";
+
+import Char;
+
+
+// { dg-final { scan-lang-dump {Read:-1's enum merge key \(new\) type_decl:'#null#'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) const_decl:'::._anon_0@[^\n]*/enum-8_b.H:1::Foo'} module } }
+// { dg-final { scan-lang-dump {Read:-1's enum merge key \(new\) type_decl:'#null#'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) const_decl:'::._anon_1@[^\n]*/enum-8_a.H:2::Foo'} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+
+enum ONE {A};
+enum {TWO, THREE};
+enum FOUR {B = 5};
+enum FIVE {C, D, E};
--- /dev/null
+// { dg-additional-options {-fmodules-ts} }
+
+enum ONE {Q};
+enum {TWO, DREI};
+enum FOUR {B = 3};
+enum FIVE {C, D};
+
+import "enum-bad-1_a.H";
+
+
+
+
+
+
+ONE one;
+// { dg-regexp {In module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:5:6: error: definition of 'enum ONE' does not match\n[^\n]*enum-bad-1_b.C:3:6: note: existing definition 'enum ONE'\nIn module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:5:11: note: ... this enumerator 'A'\n[^\n]*enum-bad-1_b.C:3:11: note: enumerator 'Q' does not match ...\n[^\n]*enum-bad-1_b.C:15:1: note: during load of binding '::ONE'\n} }
+
+int i = TWO;
+// { dg-regexp {In module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:6:6: error: definition of 'enum<unnamed>' does not match\n[^\n]*enum-bad-1_b.C:4:6: note: existing definition 'enum<unnamed>'\nIn module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:6:12: note: ... this enumerator 'THREE'\n[^\n]*enum-bad-1_b.C:4:12: note: enumerator 'DREI' does not match ...\n[^\n]*enum-bad-1_b.C:18:9: note: during load of binding '::TWO'\n} }
+
+FOUR four;
+// { dg-regexp {In module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:7:6: error: definition of 'enum FOUR' does not match\n[^\n]*enum-bad-1_b.C:5:6: note: existing definition 'enum FOUR'\nIn module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:7:12: note: ... this enumerator 'B'\n[^\n]*enum-bad-1_b.C:5:12: note: enumerator 'B' does not match ...\n[^\n]*enum-bad-1_b.C:21:1: note: during load of binding '::FOUR'\n} }
+
+FIVE five;
+// { dg-regexp {In module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:8:6: error: definition of 'enum FIVE' does not match\n[^\n]*enum-bad-1_b.C:6:6: note: existing definition 'enum FIVE'\nIn module [^\n]*enum-bad-1_a.H, imported at [^\n]*enum-bad-1_b.C:8:\n[^\n]*enum-bad-1_a.H:8:18: note: additional enumerators beginning with 'E'\n[^\n]*enum-bad-1_b.C:24:1: note: during load of binding '::FIVE'\n} }
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+export int Frob (int, int, long);
+export int Frob (int, long, int);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Bar;
+// { dg-module-cmi "Bar" }
+
+export int Frob (long, int, int);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import Foo;
+
+void One ()
+{
+ Frob (0, 0, 0L);
+ Frob (0, 0L, 0);
+ Frob (0L, 0, 0); // { dg-error "ambiguous" }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, long int, int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, int, long int\)'} }
+}
+
+import Bar;
+
+void Two ()
+{
+ Frob (0L, 0, 0);
+ Frob (0, 0, 0); // { dg-error "ambiguous" }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, long int, int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, int, long int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Bar\(long int, int, int\)'} }
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import Foo;
+import Bar;
+
+
+void Three ()
+{
+ Frob (0L, 0, 0);
+
+ Frob (0, 0, 0); // { dg-error "ambiguous" }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, long int, int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Foo\(int, int, long int\)'} }
+ // { dg-regexp {candidate: 'int Frob@Bar\(long int, int, int\)'} }
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module bill;
+// { dg-module-cmi bill }
+
+// Make sure no deferred parse exception spec detritus remains
+
+template<typename T>
+class bob
+{
+ void frob () noexcept(T::frob ());
+ template<typename U> void frobber (int) noexcept (T::frob ());
+};
+
+
+class bill
+{
+ template<typename U> void frobbest (int) noexcept (U::frob ());
+};
--- /dev/null
+
+// Causes the CMI to have instantiated a deferred noexept spec that
+// the textually included file has not.
+
+typedef long unsigned int size_t;
+
+
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{
+ static constexpr _Tp value = __v;
+ typedef integral_constant<_Tp, __v> type;
+};
+template<typename _Tp, _Tp __v>
+constexpr _Tp integral_constant<_Tp, __v>::value;
+
+template<typename _Head>
+struct _Tuple_impl : _Head
+{
+ _Tuple_impl(_Tuple_impl&& __in)
+ noexcept (integral_constant<bool,
+ noexcept(_Head(static_cast<_Head &&>(*(_Head *) (0))))>::type::value);
+};
+
+template <typename _Dp>
+struct __uniq_ptr_impl
+{
+ __uniq_ptr_impl (__uniq_ptr_impl&& __u) noexcept
+ : _M_t(static_cast <_Tuple_impl<_Dp> &&>(__u._M_t))
+ {}
+
+ _Tuple_impl<_Dp> _M_t;
+};
+
+struct _Impl_deleter {};
+
+typedef __uniq_ptr_impl<_Impl_deleter> up;
+
+inline void frob (up && p)
+{
+ up _M_cmpts (static_cast <up &&> (p));
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "except-2.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "except-2.h"
+import "except-2_a.H";
--- /dev/null
+
+template<typename _Tp>
+struct is_nothrow_move_constructible
+{
+ static constexpr bool value = false;
+};
+
+template<typename _Head>
+struct _Tuple_impl
+{
+ _Tuple_impl () noexcept(is_nothrow_move_constructible<_Head>::value)
+ { }
+};
+
+template<typename T>
+void TPL (_Tuple_impl<T> &) noexcept
+{
+ _Tuple_impl<T> m;
+}
+
+inline void foo (_Tuple_impl<int> &p)
+{
+ TPL<int> (p);
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+// We end up with instantiated noexcept specs in the CMI data matching
+// textually loaded fns with uninstantiated ones. Have to propagate,
+// not reinstantiate.
+#include "except-3.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "except-3.h"
+import "except-3_a.H";
+
+// { dg-final { scan-lang-dump-times {merge key \(new\) function_decl:'::_Tuple_impl<int>::__[cd]t '} 3 module } }
+// { dg-final { scan-lang-dump-times {Propagating instantiated noexcept to '::_Tuple_impl<int>::__ct <int>'} 1 module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#define PROTECT 1
+int foo ();
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module evil;
+// { dg-module-cmi !evil }
+
+export // { dg-error "not part of following" }
+#include "exp-xlate-1_a.H" // { dg-error "must be contiguous" }
+// { dg-prune-output {not writing module} }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module frob;
+// { dg-module-cmi !frob }
+
+int x ();
+export int x (); // { dg-error "conflicting exporting declaration" }
+
+int y;
+export extern int y; // { dg-error "conflicting exporting declaration" }
+
+typedef int z;
+export typedef int z; // { dg-error "conflicting exporting declaration" }
+
+template <typename T> int f (T);
+export template <typename T> int f (T); // { dg-error "conflicting exporting declaration" }
+
+// doesn't go via duplicate_decls so we miss this for now
+class A;
+export class A; // { dg-error "conflicting exporting declaration" "" { xfail *-*-* } }
+
+// { dg-warning "due to errors" "" { target *-*-* } 0 }
--- /dev/null
+// { dg-module-do link }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template <unsigned I> struct TPL
+{
+ int Source ()
+ {
+ return I;
+ }
+};
+
+extern template class TPL<1>;
+
+struct Foo
+{
+ TPL<1> m;
+
+ Foo () {m.Source ();};
+
+};
+
+static Foo __ioinit;
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fmodule-mapper=|@g++-mapper-server} }
+
+// Have to textually include, because we currently get confused about
+// the explicit instantiations and think they conflict
+#include "extern-tpl-1_a.H"
+
+template class TPL<1>;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "extern-tpl-1_a.H";
+
+int main ()
+{
+}
--- /dev/null
+// { dg-module-do link }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template <unsigned I> struct TPL
+{
+ int Source ()
+ {
+ return I;
+ }
+};
+
+extern template class TPL<1>;
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+import "extern-tpl-2_a.H";
+
+struct Foo
+{
+ TPL<1> m;
+
+ Foo () {m.Source ();};
+
+};
+
+static Foo __ioinit;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "extern-tpl-2_a.H";
+
+template class TPL<1>;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "extern-tpl-2_b.H";
+
+int main ()
+{
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++17" }
+export module opt;
+
+// { dg-module-cmi opt }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+
+// { dg-error "language dialect differs" "" { target *-*-* } 0 }
+
+import opt;
+
+// { dg-error "failed to read" "" { target *-*-* } 0 }
+// { dg-prune-output "compilation terminated" }
+// { dg-prune-output "fatal error" }
--- /dev/null
+// { dg-require-weak "" }
+// { dg-additional-options "-fmodules-ts" }
+export module bob;
+// { dg-module-cmi "bob" }
+
+export inline int frob (int a)
+{
+ return -a;
+}
+
+inline int frob (int s, int a)
+{
+ while (s--)
+ a <<= 1;
+ return a;
+}
+
+export int Frob (int s, int a);
+
+// { dg-final { scan-assembler-not "_Z4frobi:" } }
+// { dg-final { scan-assembler-not "_ZW3bobE4frobii:" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module bob;
+
+int Frob (int n, int a)
+{
+ return frob (n, a);
+}
+
+// { dg-final { scan-assembler "_ZW3bobE4frobii:" } }
+// { dg-final { scan-assembler ".weak(_definition)?\[\t ]*_?_ZW3bobE4frobii" } }
+// { dg-final { scan-assembler "_Z4Frobii:" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import bob;
+
+int main ()
+{
+ if (frob (2) != -2)
+ return 1;
+ if (Frob (0, 2) != 2)
+ return 1;
+ if (Frob (2, 2) != 8)
+ return 1;
+ return 0;
+}
+
+// { dg-final { scan-assembler "_Z4frobi:" } }
+// { dg-final { scan-assembler ".weak(_definition)?\[\t ]*_?_Z4frobi" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module bob;
+// { dg-module-cmi "bob" }
+
+export void bob ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module stuart;
+// { dg-module-cmi "stuart" }
+
+export void stuart ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module kevin;
+// { dg-module-cmi "kevin" }
+
+export void kevin ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts --param lazy-modules=1 -fdump-lang-module" }
+
+import bob;
+import stuart;
+import kevin;
+
+int main ()
+{
+ stuart ();
+ bob ();
+ kevin ();
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Freezing 'bob.[^']*'} module } }
+// { dg-final { scan-lang-dump {Freezing 'stuart.[^']*'} module } }
+// { dg-final { scan-lang-dump {Freezing 'kevin.[^']*'} module } }
+// { dg-final { scan-lang-dump {Defrosting 'bob.[^']*'} module } }
+// { dg-final { scan-lang-dump {Defrosting 'stuart.[^']*'} module } }
+// { dg-final { scan-lang-dump {Defrosting 'kevin.[^']*'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export struct peeker
+{
+ static int peek (void *);
+};
+
+
+export class hidey
+{
+protected:
+ int key;
+
+public:
+ hidey (int key) :key (key)
+ {
+ }
+
+ friend class peeker;
+};
+
+export class secret : public hidey
+{
+public:
+ secret (int key) : hidey (key)
+ {
+ }
+};
+
+// hidey, peeker & secret are all in different clusters
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::peeker'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::peeker'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::hidey'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::hidey'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::secret'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::secret'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module bob;
+
+int peeker::peek (void *data)
+{
+ return reinterpret_cast <secret *> (data)->key;
+}
+
+// { dg-final { scan-lang-dump {Class '::hidey@bob:.' befriending record_type:'::peeker@bob:.'} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+int main ()
+{
+ secret s (5);
+
+ if (peeker::peek (&s) != 5)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module bink;
+// { dg-module-cmi bink }
+
+class pusher
+{
+ friend void frob (pusher *){}
+public:
+ pusher (){}
+};
+
+inline void grabber (pusher *p)
+{
+ frob (p);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module bink;
+
+struct other {};
+
+void f (pusher *p, other *q)
+{
+ grabber (p);
+
+ frob (p); // ok, found by ADL
+
+ frob (q); // { dg-error "not declared" }
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi !foo }
+
+namespace bob {
+
+export void corge ();
+void grault ();
+
+export class Q
+{
+ friend void foo ();
+ friend void bar ();
+ friend void corge ();
+ friend void grault ();
+};
+
+export void foo ();
+void bar (); // exported
+
+class R
+{
+ friend void quux ();
+ friend void toto ();
+ friend void corge ();
+ friend void grault ();
+};
+
+export void quux (); // { dg-error "conflicting export" }
+void toto (); // not exported
+
+}
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace bob {
+
+export void corge ();
+void grault ();
+
+export class Q
+{
+ friend void foo ();
+ friend void bar ();
+ friend void corge ();
+ friend void grault ();
+ friend void xyzzy (Q);
+};
+
+export void foo ();
+void bar (); // exported
+
+class R
+{
+ friend void toto ();
+ friend void corge ();
+ friend void grault ();
+ friend void xyzzy (R);
+};
+
+void toto (); // not exported
+export R getR ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+using namespace bob;
+
+void doit ()
+{
+ corge ();
+ foo ();
+ bar ();
+
+ grault (); // { dg-error "not declared" }
+ toto (); // { dg-error "not declared" }
+ xyzzy (); // { dg-error "not declared" }
+
+ xyzzy (getR); // ADL
+ xyzzy (Q{}); // ADL
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+// From Andrew Sutton
+
+export module foo;
+// { dg-module-cmi foo }
+export class A {
+ friend class B;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+// From Andrew Sutton
+
+export module bar;
+import foo;
+
+class B { // { dg-error "in a different module" }
+ B() { object.value = 42; }
+ A object;
+};
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts --param ggc-min-expand=0 --param ggc-min-heapsize=0" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export int bob ();
+
+void frink ()
+{
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module stuart;
+
+export int stuart ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module kevin;
+
+export int kevin ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts --param ggc-min-expand=0 --param ggc-min-heapsize=0" }
+
+import bob;
+import stuart;
+import kevin;
+
+void frob ()
+{
+}
+
+void stuart (int);
+
+void quux ()
+{
+ bob ();
+}
+
+void toto ()
+{
+ stuart (1);
+}
+
+void fido ()
+{
+ stuart ();
+ kevin ();
+}
+
--- /dev/null
+$root .
+frob map-1_a.nms
--- /dev/null
+// { dg-additional-options "-fmodules-ts --param ggc-min-expand=0 --param ggc-min-heapsize=0 -fno-module-lazy -fmodule-mapper=[srcdir]/gc-2.map" }
+// { dg-additional-files map-1.map }
+
+// Make sure the module hash table survives GC
+
+// { dg-module-cmi "=map-1_a.nms" }
+export module frob;
+
+int thing;
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 "gmf" 1
+int bar ();
+# 6 "" 2
+export module thing;
+// { dg-module-cmi "thing" }
+
+export int baz ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import thing;
+
+void bink ()
+{
+ baz ();
+ bar (); // { dg-error "not declared" "" }
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+module;
+
+# 6 "std" 1
+template<typename T>
+class basic_string_view
+{
+public:
+ basic_string_view(const char* __str) noexcept;
+};
+
+# 14 "" 2
+export module hello;
+// { dg-module-cmi hello }
+export void greeter (basic_string_view<char> const &name)
+{
+
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import hello;
+int main (void)
+{
+ greeter ("world");
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading definition of '::template basic_string_view@hello:1'} module } }
+// { dg-final { scan-lang-dump {Read declaration of '::basic_string_view@hello:1<char>'} module } }
+// { dg-final { scan-lang-dump {Read declaration of '::greeter@hello:1'} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#define MACRO(X) X
+
+inline int frob (int x)
+{
+ return x + 2;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module;
+
+import "gmf-2_a.H";
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export inline int MACRO (fn) (int i)
+{
+ return frob (i);
+}
+
+export int (MACRO) (int i);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module Foo;
+
+// We see no frob from primary's GMF
+int frob (int x)
+{
+ return fn (-x);
+}
+
+// We see no macro from primary's GMF
+int MACRO (int i)
+{
+ return frob (i);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import Foo;
+
+// We see no MACRO
+
+int main ()
+{
+ return !(MACRO (5) == -3);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 3 __FILE__ 1
+
+int v1;
+
+# 9 "" 2
+export module b;
+// { dg-module-cmi b }
+
+export inline auto get ()
+{
+ return v1;
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import b;
+
+int main ()
+{
+ get ();
+}
--- /dev/null
+// { dg-additional-options {-fmodule-header -fdump-lang-module-blocks} }
+
+// { dg-module-cmi {} }
+
+class frob;
+
+template<int I> class FROB;
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::frob'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::template FROB'} module } }
--- /dev/null
+// { dg-additional-options {-fmodule-header -fdump-lang-module-blocks} }
+
+// { dg-module-cmi {} }
+
+import "hdr-1_a.H";
+
+class frob
+{
+public:
+ int field;
+};
+
+template<int J>
+class FROB
+{
+public:
+ static constexpr int val = J;
+};
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::frob'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template FROB'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts} }
+
+import "hdr-1_b.H";
+
+int foo (frob *p)
+{
+ return p->field;
+}
+
+int foo (FROB<2> *p)
+{
+ return p->val;
+}
+
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+int bob ();
+
+static int var = bob ();
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+int bob ();
+
+static int var = bob ();
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias} }
+
+import "hdr-init-1_a.H";
+import "hdr-init-1_b.H";
+
+int bob ()
+{
+ static int i;
+
+ return ++i;
+}
+
+int main ()
+{
+ return !(var == 1);
+}
+
+// { dg-final { scan-lang-dump-times {Reading 1 initializers} 2 module } }
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(new\) var_decl:'::var'} module } }
+// { dg-final { scan-lang-dump-times {Reading definition var_decl '::var@[^\n]*/hdr-init-1_a.H:1'} 2 module } }
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(matched\) var_decl:'::var'} module } }
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{};
+
+template<bool __v>
+using __bool_constant = integral_constant<bool, __v>;
+
+template<typename _Tp, typename... _Args>
+struct __is_constructible_impl
+ : public __bool_constant<__is_constructible(_Tp, _Args...)>
+{ };
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+int main ()
+{
+ __is_constructible_impl<bool> x;
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// we ICED on malformed preambles ending at EOF.
+import bob // { dg-error "expected" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+module;
+
+# 6 __FILE__ 1
+struct Bob
+{
+ // inline
+ static auto frob ()
+ {
+ }
+};
+
+# 14 "" 2
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export struct Bill
+{
+ // not inline
+ static auto dob ()
+ {
+ }
+ static inline auto frob ()
+ {
+ }
+};
+
+export inline auto GMF ()
+{
+ return Bob::frob ();
+}
+
+// { dg-final { scan-assembler-not {_ZN3Bob4frobEv:} } }
+// { dg-final { scan-assembler-not {_ZN4Bill4frobEv:} } }
+// { dg-final { scan-assembler {_ZN4Bill3dobEv:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+
+import Foo;
+
+int main ()
+{
+ GMF ();
+ Bill::dob ();
+ Bill::frob ();
+
+ return 0;
+}
+
+// { dg-final { scan-assembler {_ZN3Bob4frobEv:} } }
+// { dg-final { scan-assembler {_ZN4Bill4frobEv:} } }
+// { dg-final { scan-assembler-not {_ZN4Bill3dobEv:} } }
+// { dg-final { scan-assembler {_Z3GMFv:} } }
+
+// { dg-final { scan-assembler {call[ \t]+_?_ZN3Bob4frobEv} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler {call[ \t]+_?_Z3GMFv} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler {call[ \t]+_?_ZN4Bill3dobEv} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler {call[ \t]+_?_ZN4Bill4frobEv} { target i?86-*-* x86_64-*-* } } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module A;
+// { dg-module-cmi A }
+
+struct M
+{
+ M (){}
+};
+
+export struct C
+{
+ M m;
+ // lazy implicit ctor
+};
+
+// { dg-final { scan-lang-dump-not {'::C::__ct '} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module B;
+// { dg-module-cmi B }
+export import A;
+
+export struct D
+{
+ C c;
+
+ // ctor causes C::C to exist, and we need to put it in out CMI
+ inline D (){}
+};
+
+// { dg-final { scan-lang-dump {\[.*\]=decl definition '::C@A:1::__ct '} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+import B;
+
+void fn ()
+{
+ D d; // reads in C::C implicit ctor
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(new\) function_decl:'::C@A:.::__ct '\n} module } }
+// { dg-final { scan-lang-dump {Adding implicit member '::C@A:.::__ct @B:.} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+import B;
+
+void fn ()
+{
+ C c; // creates C::C implicitly (we never read B's version)
+}
+
+// { dg-final { scan-lang-dump-not {Read:-1's named merge key \([a-z]*\) function_decl:'::C@A:.::__ct '\n} module } }
+// { dg-final { scan-lang-dump-not {Adding implicit member '::C@A:.::__ct @B:.} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+import B;
+
+void fn ()
+{
+ C c; // created C::C implicitly
+}
+
+void fn2 ()
+{
+ D d; // merges implicit C::C
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) function_decl:'::C@A:.::__ct '\n} module } }
+// { dg-final { scan-lang-dump-not {Adding implicit member '::C@A:.::__ct @B:.} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+// A more complete imp-member test
+export module A;
+// { dg-module-cmi A }
+
+struct M
+{
+ M (){}
+ M (M const &){}
+ M (M &&){}
+ ~M (){}
+ M &operator=(M const &){ return *this;}
+ M &operator=(M &&){ return *this;}
+};
+
+export struct C
+{
+ M m;
+ // lazy implicit ctors, dtors, assop
+};
+
+// C doesn't contain a lot
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::C'\n \[1\]=decl declaration '::C::C'\n \[2\]=binding '::C'\n} module } }
+
+// particularly not ...
+// { dg-final { scan-lang-dump-not {'::C::__ct '} module } }
+// { dg-final { scan-lang-dump-not {'::C::__dt '} module } }
+// { dg-final { scan-lang-dump-not {'::C::operator= '} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module B;
+// { dg-module-cmi B }
+export import A;
+
+export struct D
+{
+ C c;
+
+ // cause all C's implicit members to exist, and we need to put it in out CMI
+ inline D (){}
+ inline D (D const &v) : c (v.c) {}
+ inline D (D &&v) : c (static_cast<C &&> (v.c)) {}
+ inline ~D () {}
+ inline D &operator= (D const &v) { c = v.c; return *this;}
+ inline D &operator= (D &&v) { c =static_cast<C &&> (v.c); return *this;}
+};
+
+// { dg-final { scan-lang-dump-times {\[0\]=decl definition '::C@A:1::__dt '} 1 module } }
+// { dg-final { scan-lang-dump-times {\[0\]=decl definition '::C@A:1::__ct '} 3 module } }
+// { dg-final { scan-lang-dump-times {\[0\]=decl definition '::C@A:1::operator='} 2 module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+import B;
+
+void fn ()
+{
+ D d; // reads in C::C implicits
+}
+
+// { dg-final { scan-lang-dump-times {Read:-[0-9]*'s named merge key \(new\) function_decl:'::C@A:.::__dt '\n} 1 module } }
+// { dg-final { scan-lang-dump-times {Adding implicit member '::C@A:.::__dt @B:.} 1 module } }
+// { dg-final { scan-lang-dump-times {Read:-[0-9]*'s named merge key \(new\) function_decl:'::C@A:.::__ct '\n} 3 module } }
+// { dg-final { scan-lang-dump-times {Adding implicit member '::C@A:.::__ct @B:.} 3 module } }
+// { dg-final { scan-lang-dump-times {Read:-[0-9]*'s named merge key \(new\) function_decl:'::C@A:.::operator='\n} 2 module } }
+// { dg-final { scan-lang-dump-times {Adding implicit member '::C@A:.::operator=@B:.} 2 module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+class bad_optional_access
+{
+public:
+
+ virtual ~bad_optional_access() noexcept = default; // { dg-bogus "" }
+};
+
+inline void
+__throw_bad_optional_access()
+{
+ throw bad_optional_access ();
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Bar;
+// { dg-module-cmi "Bar" }
+
+export void Quux (int);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Baz;
+// { dg-module-cmi "Baz" }
+
+export void Quux (int, int);
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+// { dg-final { scan-lang-dump "Writing exported import:.->. Baz" "module" } }
+// { dg-final { scan-lang-dump "Writing exported import:.->. Bar" "module" } }
+
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+export import Bar;
+export import Baz;
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Foop;
+// { dg-module-cmi "Foop" }
+
+import Bar;
+
+export int Thing ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import Foo;
+
+int main ()
+{
+ Quux (1); // from Bar
+ Quux (1, 2); // from Baz
+ return 0;
+}
+
+// { dg-final { scan-lang-dump "Found exported import:1 Bar->1" "module" } }
+// { dg-final { scan-lang-dump "Found exported import:2 Baz->2" "module" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module Foop;
+
+int Thing ()
+{
+ Quux (1); // from Bar
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import Foop;
+
+int main ()
+{
+ Thing ();
+ Quux (1); // { dg-error "not declared" }
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// Don't segfault on missing module BMI
+
+// { dg-module-cmi "!bob" }
+// { dg-module-cmi "!bill" }
+
+import bill;
+// { dg-regexp "In module imported at \[^\n]*import-2.C:7:.:\nbill: error: failed to read compiled module: \[^\n]*\n" }
+
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
+
--- /dev/null
+<stdarg.h>
+<stdio.h>
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#ifndef _STDARG_H
+#define _STDARG_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern void frob ();
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options -fmodule-header }
+
+#ifndef _STDIO_H
+#define _STDIO_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ // Yes, inside extern "C" block :(
+ #include "inc-xlate-1_a.H"
+ #ifndef _STDARG_H
+ #error barf
+ #endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+// { dg-final { scan-file inc-xlate-1_b.i {import "[^\n]*inc-xlate-1_a.H" \[\[__translated\]\];\n} } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+extern "C" {
+ #include "inc-xlate-1_a.H"
+}
+
+int main ()
+{
+ frob ();
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=|@g++-mapper-server\\ -t\\ [srcdir]/inc-xlate-1.map" }
+export module bad;
+#include "inc-xlate-1_a.H" // { dg-error "not be include-translated" }
+
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+// indirect references to import. Non-template cases
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo {
+
+ export int frob (int i)
+ {
+ return i;
+ }
+
+
+ export class X
+ {
+ int i;
+
+ public:
+ X (int i) :i(i) { }
+ operator int () const { return i; }
+ };
+
+ export class Y : public virtual X
+ {
+ int j;
+ public:
+ Y (int i, int j) : X(i), j(j){}
+ virtual int frob () const;
+ };
+
+ int Y::frob () const
+ {
+ return *this + j;
+ }
+
+ export enum Plain {A, B, C, D};
+ export enum class Scoped {A, B, C, D};
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int frob (int i = foo::frob (0))
+ {
+ return i;
+ }
+
+ export int quux (int i = foo::X (0) )
+ {
+ return i;
+ }
+
+ export class Z : public foo::Y
+ {
+ public:
+ Z (int i, int j) : X(i), Y(i, j)
+ {
+ }
+ };
+
+ export constexpr auto Plain_One (bool b) { return b ? foo::B : foo::C; }
+ export constexpr auto Scoped_One (bool b) { return b ? foo::Scoped::B
+ : foo::Scoped::C; }
+
+ export extern auto const Plain_Const_Three = foo::D;
+ export extern auto const Scoped_Const_Three = foo::Scoped::D;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::frob'@'foo' section:} module } }
+// { dg-final { scan-lang-dump-not {namespace:-[0-9]* namespace_decl:'::foo'} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* function_decl:'::foo@foo:.::frob@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::X'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* type_decl:'::foo@foo:.::X@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::Y'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* type_decl:'::foo@foo:.::Y@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::B'@'foo' section:} module } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::foo@foo:.::C@foo:.'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::Scoped'@'foo' section:} module } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::foo@foo:.::Scoped@foo:.::[ABCD]'@'foo' section:} module } }
+
+// { dg_final { scan-lang-dump {Wrote named import:-[0-9]* const_decl:'::foo::Plain@\(foo\)::C'@foo} module } }
+// { dg_final { scan-lang-dump {Wrote named import:-[0-9]* const_decl:'::foo::Plain@\(foo\)::B'@foo} module } }
+// { dg_final { scan-lang-dump {Wrote named import:-[0-9]* const_decl:'::foo::Scoped@\(foo\)::C'@foo} module } }
+// { dg_final { scan-lang-dump {Wrote named import:-[0-9]* const_decl:'::foo::Scoped@\(foo\)::B'@foo} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+import bar;
+
+
+int main ()
+{
+ if (bar::frob ())
+ return 1;
+ if (bar::quux ())
+ return 2;
+
+ if (bar::Z (1, 2).frob () != 3)
+ return 3;
+
+ static_assert (bar::Plain_One (true) == 1);
+ static_assert (bar::Plain_One (false) == 2);
+ static_assert (int (bar::Scoped_One (true)) == 1);
+ static_assert (int (bar::Scoped_One (false)) == 2);
+
+ static_assert (bar::Plain_Const_Three == 3);
+ static_assert (int (bar::Scoped_Const_Three) == 3);
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::frob'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[14\] section:4} module } }
+// { dg-final { scan-lang-dump {Named:-[0-9]* namespace_decl:'::foo@foo:1'@foo} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* function_decl:'::foo@foo:.::frob@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::quux'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[1\] section:1} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* type_decl:'::foo@foo:.::X@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Z'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[8\] section:2} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* type_decl:'::foo@foo:.::Y@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump {Read member:-[0-9]* field_decl:'::foo@foo:.::Y@foo:.::_vptr.Y'} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* function_decl:'::foo@foo:.::Y@foo:.::frob@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Plain_One'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[13\] section:3} module } }
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Scoped_One'@'bar' section} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[15\] section:5} module } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::foo@foo:.::[ABC]'@'foo' section:} module } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::foo@foo:.::Scoped@\(foo\)::[ABC]'@'foo' section:} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Plain_Const_Three'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::Scoped_Const_Three'@'bar' section} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+// indirect references to import, simple templates
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo
+{
+ export template<int I> int frob ()
+ {
+ return I;
+ }
+
+ export template<int I> class X
+ {
+ int i = I;
+
+ public:
+ operator int () const { return i; }
+ };
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias-uid" }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int frob (int i = foo::frob<0> ())
+ {
+ return i;
+ }
+
+ export int quux (int i = foo::X<0> ())
+ {
+ return i;
+ }
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::frob'@'foo' section} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template frob@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo@foo:.::frob<0x0>'} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::X'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template X@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::X<0x0>'\n \[1\]=specialization declaration '::foo@foo:.::X<0x0>::__conv_op <0x0>'\n \[2\]=specialization declaration '::foo@foo:.::X<0x0>::X<0x0>'\n( \[.\]=[^\n]* '\n)*} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::X<0x0>'} module } }
+// { dg-final { scan-lang-dump {Depset:. specialization entity:. type_decl:'::foo@foo:.::X<0x0>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::X<0x0>'} module } }
+// { dg-final { scan-lang-dump {Wrote purview:-[0-9]* type_decl:'::foo@foo:.::X<0x0>'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+import bar;
+
+int main ()
+{
+
+ if (bar::frob ())
+ return 1;
+
+ if (bar::quux ())
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::frob'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[4\] section:2} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::template frob@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump-not {Wrote mergeable} module } }
+
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::quux'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[1\] section:1} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::template X@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]* function_decl:'::foo@foo:.::frob<0x0>'} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+// indirect references to import, template member non-template or
+// non-template member of template cases
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo
+{
+ export class X
+ {
+ public:
+ template <int I> int frob () const { return I; }
+ };
+
+ export template<int I> class TPL
+ {
+ public:
+ int frob () const { return I; }
+ };
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-uid-alias" }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int quux (int i = foo::X().frob<0> ())
+ {
+ return i;
+ }
+
+ export int toto (int i = foo::TPL<0>().frob ())
+ {
+ return i;
+ }
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::X'@'foo' section} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::X@foo:.::template frob@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::TPL'@'foo' section} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::TPL<0x0>'\n \[1\]=specialization declaration '::foo@foo:.::TPL<0x0>::TPL<0x0>'\n( \[.\]=[^\n]* '\n)* \[.\]=decl definition '::foo@foo:.::TPL<0x0>::frob<0x0>'\n} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::X@foo:.::frob<0x0>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::TPL<0x0>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo@foo:.::X@foo:.::frob<0x0>'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+import bar;
+
+int main ()
+{
+
+ if (bar::quux ())
+ return 1;
+
+ if (bar::toto ())
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::quux'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[5\] section:2} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::X@foo:.::template frob@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump-not {Instantiation:-[0-9]* function_decl:'::foo::X@foo:.::frob@.()<0x0>'} module } }
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::toto'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[1\] section:1} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } }
+// { dg-final { scan-lang-dump {Reading definition type_decl '::foo@foo:.::TPL@bar:.<0x0>'} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+// indirect references to import, template member of template case
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo
+{
+ export template<int I> class TPL
+ {
+ public:
+ template <int J> int frob () const
+ {
+ return I + J;
+ }
+ };
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias-uid" }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int quux (int i = foo::TPL<1> ().frob<2> ())
+ {
+ return i;
+ }
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::foo@foo:.::TPL'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Wrote import:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::TPL<0x1>'\n \[1\]=specialization declaration '::foo@foo:.::TPL<0x1>::template frob<#unnamed#>'\n \[2\]=specialization declaration '::foo@foo:.::TPL<0x1>::TPL<0x1>'\n( \[.\]=[^\n]* '\n)*} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::foo@foo:.::TPL<0x1>::frob<0x2>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::foo@foo:.::TPL<0x1>'} module } }
+// { dg-final { scan-lang-dump {Wrote purview:-[0-9]* type_decl:'::foo@foo:.::TPL<0x1>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo@foo:.::TPL<0x1>::frob<0x2>'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid-alias" }
+import bar;
+
+int main ()
+{
+ if (bar::quux () != 3)
+ return 1;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar@bar:.::quux'@'bar' section:} module } }
+// { dg-final { scan-lang-dump {>Loading entity foo\[2\] section:1} module } }
+// { dg-final { scan-lang-dump {Imported:-[0-9]* template_decl:'::foo@foo:.::template TPL@foo:.'@foo} module } }
+
+// { dg-final { scan-lang-dump {Reading definition function_decl '::foo@foo:.::TPL@bar:.<0x1>::frob@bar:.<0x2>'} module } }
+// { dg-final { scan-lang-dump {Reading definition type_decl '::foo@foo:.::TPL@bar:.<0x1>'} module } }
--- /dev/null
+// { dg-additional-options "-fmodule-header -isystem [srcdir] -isystem [srcdir]/sys -fdump-lang-module" }
+
+#ifndef _PROTECT
+#define _PROTECT
+
+/* We were found on the system inc path, so have been turned into a
+ system header, so no warning on the following extension. */
+#include_next <inext-1.H>
+
+#endif
+
--- /dev/null
+
+template <typename _Tp>
+struct Base
+{
+ // template constructor
+ template<typename _Del> Base(_Tp *__p, _Del __d);
+};
+
+template <typename _Tp, typename _Dp>
+struct Derived : Base<_Tp>
+{
+ // Inheriting the template constructor
+ using Base<_Tp>::Base;
+};
+
+template <typename _Tp>
+class unique_ptr
+{
+ Derived<_Tp, int> _M_t;
+
+public:
+ // Instantiates Derived<ResultDerived,int>::Derived
+ template<typename _Up> unique_ptr(unique_ptr<_Up>&& __u) noexcept
+ : _M_t ((_Tp *)0, 1) { }
+};
+
+struct ResultBase { };
+struct ResultDerived : ResultBase { };
+
+void Frob (unique_ptr<ResultBase> &&__res) ;
+
+inline void X (unique_ptr<ResultDerived> &parm)
+{
+ Frob (static_cast <unique_ptr<ResultDerived> &&> (parm));
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "inh-tmpl-ctor-1.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "inh-tmpl-ctor-1.h"
+import "inh-tmpl-ctor-1_a.H";
+
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+export module Foo;
+// { dg-module-cmi Foo }
+
+int Frob (int i)
+{
+ return i;
+}
+
+export int j = Frob (5);
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+import Foo;
+
+int frob (int j)
+{
+ return j + 1;
+}
+
+int q = frob (j);
+
+int main ()
+{
+ return !(q == 6);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+export module Foo;
+// { dg-module-cmi Foo }
+
+// { dg-final { scan-assembler {_ZGIW3FooEv:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+export module Bar;
+// { dg-module-cmi Bar }
+
+import Foo;
+
+// { dg-final { scan-assembler {_?_ZGIW3BarEv:} } }
+// { dg-final { scan-assembler {call[ \t]+_?_ZGIW3FooEv} { target i?86-*-* x86_64-*-* } } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-inline" }
+
+import Foo;
+import Bar;
+
+// We know Bar imports Foo, so only call Bar's Global Init
+// { dg-final { scan-assembler {call[ \t]+_?_ZGIW3BarEv} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler-not {call[ \t]+_?_ZGIW3FooEv} { target i?86-*-* x86_64-*-* } } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module foo;
+// { dg-module-cmi foo }
+
+int i_baz (int i)
+{
+ return i;
+}
+
+inline int baz (int i)
+{
+ return i_baz (i);
+}
+
+int f_baz (float f)
+{
+ return int (f);
+}
+
+inline int baz (float f)
+{
+ return f_baz (f);
+}
+
+export template <typename T>
+int foo (T t)
+{
+ return baz (t);
+}
+
+export inline void user ()
+{
+ foo (1);
+ foo (1.0f);
+}
+
+// { dg-final { scan-lang-dump {Depending definition function_decl:'::foo<float>'} module } }
+// { dg-final { scan-lang-dump {Depending definition function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump {\[0\]=specialization definition '::foo<float>'} module } }
+// { dg-final { scan-lang-dump {\[0\]=specialization definition '::foo<int>'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-uid-alias} }
+import foo;
+
+int main ()
+{
+ user ();
+ foo ('a'); // new inst
+ foo (1); // find foo's inst
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading definition function_decl '::foo@foo:.<int>'} module } }
+// { dg-final { scan-lang-dump {Reading definition function_decl '::foo@foo:.<float>'} module } }
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(unique\) function_decl:'::baz'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(unique\) function_decl:'::baz'} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-blocks-uid-alias} }
+
+export module foo;
+// { dg-module-cmi foo }
+
+inline int baz (int i)
+{
+ return i;
+}
+
+export template <typename T>
+inline int foo (T t)
+{
+ return baz (t);
+}
+
+export inline void user ()
+{
+ foo (1);
+}
+
+// { dg-final { scan-lang-dump {\[0\]=specialization definition '::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s named merge key \(decl\) function_decl:'::baz'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) function_decl:'::foo<int>'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-uid-alias} }
+import foo;
+
+int main ()
+{
+ foo (1); // read pending inst
+ user (); //
+ foo (1); // reuse inst
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations} module } }
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s decl spec merge key \(new\) function_decl:'::foo'} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks-alias} }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T> struct TPL
+{
+ T m;
+};
+
+export inline int user (int i)
+{
+ TPL<int> x;
+ x.m = i;
+ return x.m;
+}
+
+// { dg-final { scan-lang-dump {Cluster members:\n( \[.\]=[^\n]*'\n)* \[.\]=specialization definition '::TPL<int>'\n \[.\]=specialization declaration '::TPL<int>::TPL<int>'\n} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s type spec merge key \(specialization\) type_decl:'::TPL<int>'} module } }
+// { dg-final { scan-lang-dump {Depset:. specialization entity:. type_decl:'::TPL<int>'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias-uid} }
+import foo;
+
+int main ()
+{
+ if (user (1) != 1)
+ return 1;
+ TPL<int> x;
+ TPL<float> y;
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s type spec merge key \(new\) type_decl:'::TPL'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s decl spec merge key \(new\) type_decl:'::template TPL@foo:.<T>::TPL'} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks-alias} }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T> struct TPL
+{
+ T m;
+};
+
+export inline int user (int i)
+{
+ TPL<int> x;
+ x.m = i;
+ return x.m;
+}
+
+// { dg-final { scan-lang-dump {Specialization '::TPL<int>' entity:. keyed to foo\[.\] '::template TPL'} module } }
+// { dg-final { scan-lang-dump {Specialization '::TPL<int>::TPL<int>' entity:. keyed to foo\[.\] '::template TPL<T>::template TPL'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias-uid} }
+import foo;
+
+int main ()
+{
+ TPL<int> x;
+ if (user (1) != 1)
+ return 1;
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to foo\[.\] '::template TPL@foo:.'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s type spec merge key \(new\) type_decl:'::TPL'} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template <int I> int fn ()
+{
+ return I;
+}
+
+inline void g ()
+{
+ fn<1> (); // instantiation gets emitted
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+template <int I> int fn ()
+{
+ return I;
+}
+
+void f ()
+{
+ fn<1> ();
+}
+
+import "inst-5_a.H";
+// no longer need to instantate
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob; // { dg-error "failed to write" }
+// { dg-module-cmi !frob }
+
+namespace {
+// We shouldn't be complaining about members of internal linkage
+// entities
+class X // { dg-bogus "internal linkage" "" { xfail *-*-* } }
+{ // { dg-bogus "internal linkage" "" { xfail *-*-* } }
+};
+
+}
+
+static int frob ()
+{
+ return 1;
+}
+
+export int f (int = frob ()); // { dg-error "references internal linkage" }
+int goof (X &); // { dg-error "references internal linkage" }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options {-fmodule-header -fdump-lang-module-blocks} }
+// { dg-module-cmi {} }
+
+static int bob (int x)
+{
+ return x;
+}
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::bob'\n \[1\]=binding '::bob'} module } }
--- /dev/null
+// { dg-additional-options {-fmodule-header} }
+// { dg-module-cmi {} }
+
+static int bob (int x)
+{
+ return x;
+}
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias} }
+
+import "internal-2_a.H";
+import "internal-2_b.H";
+
+int main ()
+{
+ bob (2);
+}
+
+// { dg-final { scan-lang-dump { Read:-1's named merge key \(new\) function_decl:'::bob'} module } }
+// { dg-final { scan-lang-dump { Read:-1's named merge key \(matched\) function_decl:'::bob'} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+extern "C"
+{
+ extern int isalnum (int) __attribute__ ((__nothrow__, __leaf__));
+}
+
+namespace std
+{
+using ::isalnum;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export struct import {};
+export ::import *a;
+export ::import (b);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import bob;
+
+::import (d); // not import
+import (e); // not import
+
+void foo ()
+{
+ void *c = a;
+ void *e = &b;
+}
+
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+export module tom.riddle;
+// { dg-module-cmi tom.riddle }
+
+export inline auto One (int a)
+{
+ return [=] (int b) { return a + b; };
+}
+
+// Look Ma! this isn't inline!
+export auto Two (int a)
+{
+ return [=] (int b) { return a * b; };
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import tom.riddle;
+
+int main ()
+{
+ auto one = One (2);
+
+ if (one (1) != 3)
+ return 1;
+
+ auto two = Two (3);
+ if (two (2) != 6)
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// The lambda is attached to 'all', and should be merged keyed by that.
+inline constexpr auto all = [] () {};
--- /dev/null
+// { dg-additional-options "-fmodule-header -fdump-lang-module-alias" }
+// { dg-module-cmi {} }
+
+#include "lambda-2.h"
+
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s attached merge key \(decl\) type_decl:'::._anon_0'} module } }
+// { dg-final { scan-lang-dump {Written -[0-9]*\[0\] attached decl '::._anon_0'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+// Not an ODR violation!
+#include "lambda-2.h"
+import "lambda-2_a.H";
+
+// { dg-bogus "conflicting" "not an odr violation" }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s attached merge key \(matched\) type_decl:'#null#'} module } }
+// { dg-final { scan-lang-dump {Read -[0-9]*\[0\] matched attached decl '::._anon_0'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+import "lambda-2_a.H";
--- /dev/null
+
+template<int I> inline constexpr auto tmpl = [] {return I;};
+
+inline const auto tpl_1 = tmpl<1>;
+inline const auto tpl_2 = tmpl<2>;
--- /dev/null
+// { dg-additional-options "-fmodule-header -fdump-lang-module-alias" }
+// { dg-module-cmi {} }
+
+#include "lambda-3.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "lambda-3.h"
+import "lambda-3_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump {Read -1\[0\] matched attached decl '::template ._anon_0<#unnamed#>'} module } }
+// { dg-final { scan-lang-dump {Read -1\[0\] matched attached decl '::._anon_2'} module } }
+// { dg-final { scan-lang-dump {Read -1\[0\] matched attached decl '::._anon_1'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+import "lambda-3_a.H";
--- /dev/null
+
+inline void (*all) (int) = [] (auto) {};
--- /dev/null
+// { dg-additional-options "-fmodule-header -fdump-lang-module-alias" }
+// { dg-module-cmi {} }
+
+#include "lambda-4.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "lambda-4.h"
+import "lambda-4_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) template_decl:'::._anon_0::template _FUN'} module } }
+// { dg-final { scan-lang-dump {named merge key \(matched\) template_decl:'::._anon_0::template __conv_op '} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+extern "C"
+{
+ int cfunc ();
+}
+
+extern "C++"
+{
+ int cxxfunc ();
+}
+
+
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+extern "C"
+{
+ import "lang-1_a.H";
+}
+
+extern "C" int cfunc (int); // { dg-error "conflicting declaration" }
+extern "C" int cxxfunc (int);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+extern "C++"
+{
+ import "lang-1_a.H";
+}
+
+extern "C"
+import "lang-1_a.H"; // { dg-error "cannot appear directly" }
+
+extern "C" int cfunc (int); // { dg-error "conflicting declaration" }
+extern "C" int cxxfunc (int);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+extern "C"
+{
+ import foo; // { dg-warning "inside language-linkage" }
+}
+extern "C++"
+{
+ import foo; // { dg-warning "inside language-linkage" }
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename _Iterator>
+struct reverse_iterator
+{
+ _Iterator base() const;
+};
+
+template<typename _Iterator>
+reverse_iterator<_Iterator> __make_reverse_iterator (_Iterator __i);
+
+template<typename _Iterator>
+auto __niter_base(reverse_iterator<_Iterator> __it)
+ -> decltype (__make_reverse_iterator(__niter_base(__it.base())))
+{ return __make_reverse_iterator(__niter_base(__it.base())); }
--- /dev/null
+// { dg-additional-options "-fmodule-header -fdump-lang-module-blocks" }
+// { dg-module-cmi {} }
+
+template<typename T> struct TPL {operator T () const {return 0;}};
+
+template<typename T>
+auto Foo (T *arg)
+ -> TPL<decltype (+*arg)> {return TPL<int> ();}
+
+template<typename T>
+auto Bar (T *arg)
+ -> TPL<decltype (arg)> ;
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::template Foo'\n \[1\]=specialization declaration '::TPL<#null#>'\n \[2\]=binding '::Foo'\n} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T> struct TPL {operator T () const {return 0;}};
+
+template<typename T>
+auto Foo (T *arg)
+ -> TPL<decltype (+*arg)> {return TPL<int> ();}
+
+// Deliberately different to 2_a's Bar
+template<typename T>
+auto Bar (T *arg)
+ -> TPL<decltype (*arg)> ;
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+import "late-ret-2_a.H";
+import "late-ret-2_b.H";
+
+int main ()
+{
+ int *p = 0;
+ int j = Foo (p);
+
+ Bar (p); // { dg-error "ambiguous" }
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::template Foo'\n Deduping '::template Foo@[^\n]*/late-ret-2_a.H:.'\n} module } }
--- /dev/null
+// { dg-additional-options "-fmodule-header -fdump-lang-module-blocks" }
+// { dg-module-cmi {} }
+
+template<typename T> struct TPL_1 { using type = T;};
+
+template<typename U> struct TPL_2 { using type = int;};
+
+template<typename V> using TPL_3 = typename TPL_2<V>::type;
+
+template<typename A>
+auto Foo (const A& arg)
+ -> TPL_3<typename TPL_1<decltype(arg)>::type>
+ {return 3;}
+
+template<typename A>
+auto Bar (const A& arg)
+ -> TPL_3<typename TPL_1<decltype(arg)>::type>
+ {return 3;}
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::template Foo'\n \[1\]=specialization declaration '::TPL_1<#null#>'\n \[2\]=specialization declaration '::TPL_3<::TPL_1<#null#>::type>'\n \[3\]=specialization declaration '::TPL_2<::TPL_1<#null#>::type>'\n \[4\]=binding '::Foo'\n} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T> struct TPL_1 { using type = T;};
+
+template<typename U> struct TPL_2 { using type = int;};
+
+template<typename V> using TPL_3 = typename TPL_2<V>::type;
+
+template<typename A>
+auto Foo (const A& arg)
+ -> TPL_3<typename TPL_1<decltype(arg)>::type>
+ {return 3;}
+
+// Deliberately different to 3_a's Bar
+template<typename A>
+auto Bar (const A& arg)
+ -> TPL_3<typename TPL_1<int>::type>
+ {return 3;}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+import "late-ret-3_a.H";
+import "late-ret-3_b.H";
+
+struct Arg
+{
+ int type;
+};
+
+int main ()
+{
+ Arg arg;
+
+ int j = Foo (arg);
+
+ Bar (arg); // { dg-error "ambiguous" }
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(matched\) template_decl:'::template Foo'\n Deduping '::template Foo@[^\n]*/late-ret-3_a.H:.'\n} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi "foo" }
+
+export int bar ()
+{
+ return 1;
+}
+
+export int baz ()
+{
+ return 2;
+}
+
+export int quux ()
+{
+ return 3;
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+// Check some lazy loading
+
+import foo;
+
+int main ()
+{
+ bar ();
+
+ baz ();
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::bar'@'foo' section} "module" } }
+// { dg-final { scan-lang-dump {Lazily binding '::baz'@'foo' section} "module" } }
+// quux is not referenced, so never loaded
+// { dg-final { scan-lang-dump {Bindings '::quux' section} "module" } }
+// { dg-final { scan-lang-dump-not {Lazily binding '::quux'@'foo' section} "module" } }
+// { dg-final { scan-lang-dump-not {Read -[0-9]* function_decl:'::quux'} "module" } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+int bob (int);
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+int bob (int);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-1_a.H";
+import "leg-merge-1_b.H";
+
+int main ()
+{
+ return bob (0);
+}
--- /dev/null
+int bob (int i)
+{
+ return i;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+class X;
--- /dev/null
+// { dg-module-do link }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+class X;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-2_a.H";
+import "leg-merge-2_b.H";
+
+int main ()
+{
+ X *ptr = 0;
+
+ return ptr != 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+extern int bob;
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+extern int bob;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-3_a.H";
+import "leg-merge-3_b.H";
+
+int main ()
+{
+ return !(bob == 17);
+}
--- /dev/null
+int bob = 17;
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+extern int bob;
+void frob ();
+class X;
+
+extern int ok;
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+extern float bob;
+int frob ();
+union X;
+
+int ok ();
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-4_a.H";
+import "leg-merge-4_b.H";
+
+void foo ()
+{
+ 2[0]; // { dg-error "" }
+ bob = 5;
+ frob ();
+ X *p;
+}
+
+// { dg-regexp "\nIn module \[^\n]*leg-merge-4_b.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_b.H:4:\[0-9]*: error: conflicting global module declaration 'float bob'\nIn module \[^\n]*leg-merge-4_a.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_a.H:4:\[0-9]*: note: existing declaration 'int bob'\n\[^\n]*leg-merge-4_c.C:9:\[0-9]*: note: during load of binding '::bob'$" }
+
+// { dg-regexp "\nIn module \[^\n]*leg-merge-4_b.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_b.H:5:\[0-9]*: error: conflicting global module declaration 'int frob\\(\\)'\nIn module \[^\n]*leg-merge-4_a.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_a.H:5:\[0-9]*: note: existing declaration 'void frob\\(\\)'\n\[^\n]*leg-merge-4_c.C:10:\[0-9]*: note: during load of binding '::frob'$" }
+
+// { dg-regexp "In module \[^\n]*leg-merge-4_b.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_b.H:6:\[0-9]*: error: conflicting global module declaration 'union X'\nIn module \[^\n]*leg-merge-4_a.H, imported at \[^\n]*leg-merge-4_c.C:\[0-9]*:\n\[^\n]*leg-merge-4_a.H:6:\[0-9]*: note: existing declaration 'class X'\n\[^\n]*leg-merge-4_c.C:11:\[0-9]*: note: during load of binding '::X'$" }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+inline int bob (int x)
+{
+ return x;
+}
+
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+inline int bob (int x)
+{
+ return x;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-5_a.H";
+import "leg-merge-5_b.H";
+
+int main ()
+{
+ return bob (0);
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+struct X
+{
+ int m;
+ X (int m) :m(m) {}
+ operator int () const { return m; }
+};
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+struct X
+{
+ int m;
+ X (int m) :m(m) {}
+ operator int () const { return m; }
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-6_a.H";
+import "leg-merge-6_b.H";
+
+int main ()
+{
+ X x (75);
+
+ return !(int (x) == 75);
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template<int I> int foo (int i)
+{
+ return I == i;
+}
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template<int I> int foo (int i)
+{
+ return I == i;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-7_a.H";
+import "leg-merge-7_b.H";
+
+int main ()
+{
+ return !foo<2> (2);
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template<int I> struct Tpl
+{
+ int i;
+ Tpl () : i (I){}
+ operator int () const
+ {
+ return i;
+ }
+};
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template<int I> struct Tpl
+{
+ int i;
+ Tpl () : i (I){}
+ operator int () const
+ {
+ return i;
+ }
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "leg-merge-8_a.H";
+import "leg-merge-8_b.H";
+
+int main ()
+{
+ Tpl<1> one;
+
+ return !(one == 1);
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef int X;
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef int X;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import "leg-merge-9_a.H";
+import "leg-merge-9_b.H";
+
+X an_int;
+
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef HEADER_H
+#define HEADER_H
+
+int frob (int);
+
+#endif
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+int frob (int a)
+{
+ return a + 2;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "legacy-1_a.H";
+
+int main ()
+{
+ return !(frob (-2) == 0);
+}
--- /dev/null
+#define FROB frob
--- /dev/null
+"legacy-2_a.H"
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+// this is a legacy header
+
+int frob (int);
+
--- /dev/null
+// { dg-additional-options "-fmodule-header -fmodule-mapper=|@g++-mapper-server\\ -mt\\ $srcdir/g++.dg/modules/legacy-2.map" }
+// { dg-module-cmi {} }
+
+#define frob FROB
+
+// this should be diverted, if it isn't the above #define will break us
+#include "legacy-2_a.H"
+int move (int X = __LINE__); // Capture __LINE__ in a non-definition
+
+// this should not be diverted
+#include "legacy-2.h"
+
+
--- /dev/null
+int frob (int a)
+{
+ return a * 2;
+}
+int move (int a)
+{
+ return a;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import "legacy-2_b.H";
+
+int main ()
+{
+ if (frob (2) != 4)
+ return 1;
+ /* Check line number is not disturbed. */
+ if (move () != 8)
+ return 2;
+ return 0;
+}
--- /dev/null
+#define FROB frob
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+// this is a legacy header
+
+int frob (int);
+
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options -fmodule-header }
+
+#define frob FROB
+
+// Enough blank lines to force a line sync before the legacy import
+
+// this should be diverted, if it isn't the above #define will break us
+#include "legacy-3_a.H"
+int move (int X = __LINE__); // Capture __LINE__ in a non-definition
+
+// this should not be diverted
+#include "legacy-3.h"
+
+// { dg-final { scan-file legacy-3_b.i {\n# 9 "[^\n]*legacy-3_b.H"\nimport "[^\n]*legacy-3_a.H" \[\[__translated\]\];\nint move \(int X = 10\);\n} } }
+
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options -fmodule-header }
+
+#define frob FROB
+
+// this should be translated, if it isn't the above #define will break
+// us
+MARK1 __LINE__
+#include "legacy-3_a.H"
+MARK2 __LINE__
+int move (int X = __LINE__); // Capture __LINE__ in a non-definition
+// this should also be translated, but elided too
+MARK2 __LINE__
+#include "legacy-3_a.H"
+MARK3 __LINE__
+
+// this should not be translated
+#include "legacy-3.h"
+
+// { dg-final { scan-file legacy-3_c.i {MARK1 8\nimport "[^\n]*legacy-3_a.H" \[\[__translated\]\];\nMARK2 10\n} } }
+// We should have stopped.
+// { dg-final { scan-file legacy-3_c.i {move} } }
+// { dg-final { scan-file legacy-3_c.i {MARK2 13\n\nMARK3 15\n} } }
+// { dg-final { scan-file-not legacy-3_c.i {# [^\n]*legacy-3_a.H} } }
+// { dg-final { scan-file legacy-3_c.i {# [^\n]*legacy-3.h} } }
--- /dev/null
+./legacy-6_a.H
+./legacy-6_b.H
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+// this is a legacy user header
+
+int frob (int);
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+// this is a legacy user header
+
+int frob (float);
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=|@g++-mapper-server\\ -mt\\ [srcdir]/legacy-6.map" }
+
+#include "legacy-6_a.H"
+#include "legacy-6_b.H"
+int i;
+
+// { dg-final { scan-file legacy-6_c.i {import "[^\n]*legacy-6_a.H" \[\[__translated\]\];\nimport "[^\n]*legacy-6_b.H" \[\[__translated\]\];\nint i;} } }
--- /dev/null
+// { dg-do preprocess }
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=|@g++-mapper-server\\ -mt\\ [srcdir]/legacy-6.map" }
+
+#include "legacy-6_a.H"
+int i;
+#include "legacy-6_b.H"
+
+// { dg-final { scan-file legacy-6_d.i {import "[^\n]*legacy-6_a.H" \[\[__translated\]\];\nint i;} } }
+// { dg-final { scan-file legacy-6_d.i {int i;\nimport "[^\n]*legacy-6_b.H" \[\[__translated\]\];\n} } }
--- /dev/null
+// { dg-additional-options "-fmodule-mapper=|@mapper-server\\ -f\\ [srcdir]/legacy-6.map" }
+
+#include "legacy-6_a.H"
+#include "legacy-6_b.H"
+int i;
--- /dev/null
+// { dg-additional-options "-fmodule-mapper=|@mapper-server\\ -f\\ [srcdir]/legacy-6.map" }
+
+#include "legacy-6_a.H"
+int i;
+#include "legacy-6_b.H"
+
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+
+#define throw(...) /* { dg-warning "-:not exporting" } */ \
+ noexcept(__VA_OPT__(false))
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+
+import "legacy-7_a.H";
+
+#ifdef throw
+#error barf
+#endif
+
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+int sqr (int);
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+float sqr (float);
--- /dev/null
+#include "legacy-8_a.H"
+#include "legacy-8_a.H"
+
+int sqr (int a)
+{
+ return a * a;
+}
+
+
+float sqr (float a)
+{
+ return a * a;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+import "legacy-8_a.H";
+import "legacy-8_b.H";
+
+export inline int Sqr (int a)
+{
+ return sqr (a);
+}
+
+export inline float Sqr (float a)
+{
+ return sqr (a);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+int main ()
+{
+ int (*ifp) (int) = Sqr;
+ float (*ffp) (float) = Sqr;
+
+ if (ifp (2) != 4)
+ return 1;
+
+ // Comparing these two floats is ok
+ if (ffp (2.0f) != 4.0f)
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+// Make sure we're not confused by an imported declaration of a
+// library fn
+export module foo;
+// { dg-module-cmi foo }
+
+export inline void thrower ()
+{
+ try
+ {
+ throw 1;
+ }
+ catch (...)
+ {
+ }
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import foo;
+
+void bar ()
+{
+ thrower ();
+}
+
+void baz ()
+{
+ try
+ {
+ throw 1;
+ }
+ catch (...)
+ {
+ }
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -Wno-pedantic -Wno-psabi" }
+
+// Make sure e can serialize various literals. */
+
+export module real2reel;
+// { dg-module-cmi real2reel }
+
+export inline float assassing ()
+{
+ return 2.0f;
+}
+
+export inline double market (float square, double heroes)
+{
+ return 4.0 * square * heroes;
+}
+
+using cplx_i = __complex__ int;
+using cplx_f = __complex__ float;
+using cplx_d = __complex__ double;
+
+export inline cplx_i cinderella_search ()
+{
+ return (cplx_i) {1, 2};
+}
+export inline cplx_f emerald_lies ()
+{
+ return (cplx_f) {3, 4};
+}
+export inline cplx_d forgotten_sons ()
+{
+ return (cplx_d) {5, 6};
+}
+
+export inline int garden_party (unsigned ix)
+{
+ return "invites call the debs to play"[ix];
+}
+
+using vec = int __attribute__((vector_size (sizeof (int) * 4)));
+
+export inline vec incubus ()
+{
+ return (vec){1,7,3,9}; // Not an arithmetic series
+}
+
+export inline vec charting_the_single ()
+{
+ return (vec){1,2,3,4}; // An arithmetic series
+}
--- /dev/null
+// { dg-additional-options {-fmodules-ts -Wno-psabi} }
+
+import real2reel;
+
+int main ()
+{
+ if (assassing () != 2.0f)
+ return 1;
+
+ if (market (/*square=*/2.0f, /*heroes=*/7.0) != 56.0)
+ return 2;
+
+ auto c_i = cinderella_search ();
+ if (__real__ (c_i) != 1 || __imag__ (c_i) != 2)
+ return 3;
+
+ auto c_f = emerald_lies ();
+ if (__real__ (c_f) != 3.0f || __imag__ (c_f) != 4.0f)
+ return 4;
+
+ auto c_d = forgotten_sons ();
+ if (__real__ (c_d) != 5.0 || __imag__ (c_d) != 6.0)
+ return 5;
+
+
+ if (garden_party (7) != ' ')
+ return 6;
+
+ auto v = incubus ();
+ if (v[0] != 1 || v[1] != 7 || v[2] != 3 || v[3] != 9)
+ return 7;
+
+ v = charting_the_single ();
+ if (v[0] != 1 || v[1] != 2 || v[2] != 3 || v[3] != 4)
+ return 8;
+
+ return 0;
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export int frob (int *); // line 5
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module stuart;
+// { dg-module-cmi stuart }
+
+
+export int frob (float *); // line 6
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import bob;
+import stuart;
+
+void kevin ()
+{
+ frob (nullptr); // { dg-error "call of overload" }
+}
+
+// { dg-regexp "In module stuart, imported at \[^\n]*loc-1_c.C:4:\n\[^\n]*loc-1_b.C:7:12: note:.*" }
+// { dg-regexp "In module bob, imported at \[^\n]*loc-1_c.C:3:\n\[^\n]*loc-1_a.C:6:12: note:.*" }
+
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export int frob (int *);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module stuart;
+// { dg-module-cmi stuart }
+
+export import bob;
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module kevin;
+// { dg-module-cmi kevin }
+
+export import stuart;
+export import bob; // Bob should be reseated in the export map
+export import stuart;
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import stuart;
+
+void foo ()
+{
+ frob (2); /* { dg-error "invalid conversion" } */
+}
+
+// { dg-regexp "In module bob, imported at \[^\n]*loc-2_b.C:6,\nof module stuart, imported at \[^\n]*loc-2_d.C:3:\n\[^\n]*loc-2_a.C:6:18: note:.*" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import stuart;
+import bob;
+import stuart;
+
+void foo ()
+{
+ frob (2); // { dg-error "invalid conversion" }
+}
+
+// { dg-regexp "In module bob, imported at \[^\n]*loc-2_e.C:4:\n\[^\n]*loc-2_a.C:6:18: note:.*" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import kevin;
+
+void foo ()
+{
+ frob (2); // { dg-error "invalid conversion" }
+}
+
+// { dg-regexp "In module bob, imported at \[^\n]*loc-2_c.C:7,\nof module kevin, imported at \[^\n]*loc-2_f.C:3:\n\[^\n]*loc-2_a.C:6:18: note:.*" }
--- /dev/null
+template<typename _Tp>
+struct __is_integer
+{
+ enum { __value = 0 };
+};
+
+template<typename _Tp>
+struct __is_integer_nonstrict
+
+{
+ using __is_integer<_Tp>::__value;
+
+ enum { __width = __value ? sizeof(_Tp) * 8 : 0 };
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+#include "loc-wrapper-1.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+// ICEd comparing VIEW_CONVERT_EXPR location wrappers with null types
+#include "loc-wrapper-1.h"
+import "loc-wrapper-1_a.H";
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module the.shop;
+// { dg-module-cmi the.shop }
+
+export int for_local_people ()
+{
+ struct X {int a;};
+ X m;
+ m.a = 5;
+ return m.a;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import the.shop;
+
+int main ()
+{
+ if (for_local_people () != 5)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+module;
+# 4 __FILE__ 1
+inline void frob ()
+{
+ extern int bob; // OK
+}
+
+# 11 "" 2
+export module bob;
+// { dg-module-cmi !bob }
+
+inline void dob ()
+{
+ extern int bob; // { dg-error "block-scope extern" }
+}
+
+
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+
+inline int *wcstok(int *__wcstok_ws1)
+{
+ extern int *__iso_wcstok(int * bob);
+
+ return __iso_wcstok(__wcstok_ws1);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export inline int __inline_signbitf (float __x)
+{
+ union x { float __f; unsigned int __u; } __u;
+
+ __u.__f = __x;
+
+ return int (__u.__u >> 31);
+}
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fno-module-lazy} }
+
+import foo;
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module agnes;
+// { dg-module-cmi agnes }
+
+int a;
+
+#define BOB(X) int X ()
+#define KEVIN(X) int X ()
+
+export BOB(me);
+export KEVIN(you);
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module edith;
+// { dg-module-cmi edith }
+
+#define STUART(X) X
+
+import STUART(agnes);
+
+export void STUART(gru) ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+module edith;
+
+void gru ()
+{
+ me (1);
+ you (1);
+}
+
+// { dg-regexp "\[^\n]*macloc-1_c.C:7:8: error: too many arguments to function 'int me@agnes\\(\\)'\nIn module agnes, imported at \[^\n]*macloc-1_b.C:8,\nof module edith, imported at \[^\n]*macloc-1_c.C:3:\n\[^\n]*macloc-1_a.C:11:12: note: declared here\n\[^\n]*macloc-1_a.C:8:20: note: in definition of macro 'BOB'\n" }
+
+// { dg-regexp "\[^\n]*macloc-1_c.C:8:9: error: too many arguments to function 'int you@agnes\\(\\)'\nIn module agnes, imported at \[^\n]*macloc-1_b.C:8,\nof module edith, imported at \[^\n]*macloc-1_c.C:3:\n\[^\n]*macloc-1_a.C:12:14: note: declared here\n\[^\n]*macloc-1_a.C:9:22: note: in definition of macro 'KEVIN'\n" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import edith;
+import agnes;
+
+void margo ()
+{
+ me (1);
+ gru (2);
+}
+
+// { dg-regexp "\[^\n]*macloc-1_d.C:8:8: error: too many arguments to function 'int me@agnes\\(\\)'\nIn module agnes, imported at \[^\n]*macloc-1_d.C:4:\n\[^\n]*macloc-1_a.C:11:12: note: declared here\n\[^\n]*macloc-1_a.C:8:20: note: in definition of macro 'BOB'\n" }
+// { dg-regexp "\[^\n]*macloc-1_d.C:9:9: error: too many arguments to function 'void gru@edith\\(\\)'\nIn module edith, imported at \[^\n]*macloc-1_d.C:3:\n\[^\n]*macloc-1_b.C:10:20: note: declared here\n\[^\n]*macloc-1_b.C:6:19: note: in definition of macro 'STUART'\n" }
--- /dev/null
+// { dg-additional-options {-fmodule-header -nostdinc} }
+// { dg-module-cmi {} }
+
+#define MACRO(X) X
+
+inline int frob (int x)
+{
+ return x + 2;
+}
--- /dev/null
+// { dg-additional-options {-fmodules-ts -nostdinc} }
+module;
+
+import "macloc-2_a.H";
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export inline int MACRO (fn) (int i)
+{
+ return frob (i);
+}
+
+export int (MACRO) (int i);
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_1_H
+#define MACRO_1_H
+#define foo bar baz
+#define kevin(X) stuart (X)
+#define stuart(X) bob ("banana", X) // Yes we have X bananas
+#define bob(...) {__VA_ARGS__}
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import "macro-1_a.H";
+
+#define baz = + 1
+int foo;
+struct X
+{
+ const char *s;
+ int v;
+}
+;
+X x kevin (5);
+
+int main ()
+{
+ if (foo != 1)
+ return 1;
+ if (x.v != 5)
+ return 2;
+ const char *banana = "banana";
+ for (unsigned ix = 0; banana[ix]; ix++)
+ if (banana[ix] != x.s[ix])
+ return 3;
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_2a_H
+#define MACRO_2a_H
+
+#define FOO_OK foo
+#define BAR_OK(BAZ) BINKY(2)
+
+#define FOO_BAD foo
+#define BAR_BAD(BAZ) BINKY(2)
+
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+
+
+
+// Make line numbers distinct from macro-2_a.H
+
+
+
+
+
+
+#ifndef MACRO_2b_H
+#define MACRO_2b_H
+
+#define FOO_OK foo
+#define BAR_OK(BAZ) BINKY(2)
+
+#define FOO_BAD foot
+#define BAR_BAD(BAZ) BINKY(3)
+
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodule-header -fdump-lang-module" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_2c_H
+#define MACRO_2c_H
+import "macro-2_a.H";
+
+#endif
+
+// { dg-final { scan-lang-dump-not {Read new macro #define MACRO_2a_H at} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+#define BINKY(X) X
+
+import "macro-2_a.H";
+import "macro-2_b.H";
+
+int FOO_OK = BAR_OK(1);
+
+int BAR_BAD;
+// { dg-regexp {[^\n]*macro-2_d.C:10:5: error: inconsistent imported macro definition 'BAR_BAD'\nIn module [^\n]*macro-2_a.H, imported at [^\n]*macro-2_d.C:5:\n[^\n]*macro-2_a.H:11: note: '#define BAR_BAD\(BAZ\) BINKY\(2\)'\nIn module [^\n]*macro-2_b.H, imported at [^\n]*macro-2_d.C:6:\n[^\n]*macro-2_b.H:21: note: '#define BAR_BAD\(BAZ\) BINKY\(3\)'\n} }
+
+int FOO_BAD;
+// { dg-regexp {[^\n]*macro-2_d.C:13:5: error: inconsistent imported macro definition 'FOO_BAD'\nIn module [^\n]*macro-2_a.H, imported at [^\n]*macro-2_d.C:5:\n[^\n]*macro-2_a.H:10: note: '#define FOO_BAD foo'\nIn module [^\n]*macro-2_b.H, imported at [^\n]*macro-2_d.C:6:\n[^\n]*macro-2_b.H:20: note: '#define FOO_BAD foot'\n} }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header -fdump-lang-module-vops" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_3a_H
+#define MACRO_3a_H
+
+#undef nothing
+#define bob x
+#undef bob
+#define foo 1
+#define bar 2
+
+#endif
+
+// { dg-final { scan-lang-dump {Writing macro #define foo at} module } }
+// { dg-final { scan-lang-dump {Writing macro #define bar at} module } }
+// { dg-final { scan-lang-dump-not {Writing macro #define bob at} module } }
+// { dg-final { scan-lang-dump-not {Writing macro #undef nothing at} module } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodule-header -fdump-lang-module-vops" }
+// { dg-module-cmi {} }
+
+import "macro-3_a.H";
+
+// Not the controlling macro, because of above tokens
+#ifndef MACRO_3b_H
+#define MACRO_3b_H
+
+#define bob 1
+#undef foo
+#undef bar
+#define bar 3
+
+#endif
+
+// { dg-final { scan-lang-dump {Read new macro #define foo at} module } }
+// { dg-final { scan-lang-dump {Read new macro #define bar at} module } }
+// { dg-final { scan-lang-dump-not {Read [^ ]* macro #define bob at} module } }
+
+// { dg-final { scan-lang-dump {Writing macro #define bob at} module } }
+// { dg-final { scan-lang-dump {Writing macro #undef & #define bar at} module } }
+// { dg-final { scan-lang-dump {Writing macro #undef foo at} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-vops" }
+
+import "macro-3_b.H";
+import "macro-3_a.H";
+
+int main ()
+{
+#ifdef foo
+ return 1;
+#endif
+ if (bar != 3)
+ return 2;
+#define foo 2
+ if (foo != 2)
+ return 3;
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Read new macro #define foo at} module } }
+// { dg-final { scan-lang-dump {Read new macro #define bar at} module } }
+
+// { dg-final { scan-lang-dump {Read add macro #undef foo} module } }
+// { dg-final { scan-lang-dump {Read new macro #define bob} module } }
+// { dg-final { scan-lang-dump {Read add macro #undef & #define bar} module } }
--- /dev/null
+// { dg-additional-options "-fmodule-header -Winvalid-imported-macros" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_4_a
+#define MACRO_4_a
+
+#define ONE 1
+#define TWO 2
+#define THREE 3
+#define FOUR 4
+#define FIVE 5
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodule-header -Winvalid-imported-macros" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_4_b
+#define MACRO_4_b
+
+#define ONE 1
+#define TWO 2a
+#undef THREE // no effect
+#define THREE 3b
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodule-header -Winvalid-imported-macros" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_4_c
+#define MACRO_4_c
+
+#undef FIVE // no effect
+import "macro-4_a.H";
+int a;
+#undef THREE
+#undef FOUR
+#define FOUR 4c
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Winvalid-imported-macros" }
+
+import "macro-4_b.H";
+import "macro-4_a.H";
+
+// { dg-regexp {[^\n]*macro-4_d.C: warning: inconsistent imported macro definition 'TWO' \[-Winvalid-imported-macros\]\nIn module [^\n]*macro-4_b.H, imported at [^\n]*macro-4_d.C:[0-9]*:\n[^\n]*macro-4_b.H:[0-9]*: note: .#define TWO 2a.\nIn module [^\n]*macro-4_a.H, imported at [^\n]*macro-4_d.C:[0-9]*:\n[^\n]*macro-4_a.H:[0-9]*: note: .#define TWO 2.\n} }
+
+// { dg-regexp {[^\n]*macro-4_d.C: warning: inconsistent imported macro definition 'THREE' \[-Winvalid-imported-macros\]\nIn module [^\n]*macro-4_b.H, imported at [^\n]*macro-4_d.C:[0-9]*:\n[^\n]*macro-4_b.H:[0-9]*: note: .#define THREE 3b.\nIn module [^\n]*macro-4_a.H, imported at [^\n]*macro-4_d.C:[0-9]*:\n[^\n]*macro-4_a.H:[0-9]*: note: .#define THREE 3.\n} }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Winvalid-imported-macros" }
+
+import "macro-4_b.H";
+import "macro-4_a.H";
+import "macro-4_c.H";
+
+int stop;
+
+#ifndef FIVE
+#error bah!
+#endif
+
+// { dg-regexp {[^\n]*macro-4_e.C: warning: inconsistent imported macro definition 'TWO' \[-Winvalid-imported-macros\]\nIn module [^\n]*macro-4_b.H, imported at [^\n]*macro-4_e.C:[0-9]*:\n[^\n]*macro-4_b.H:[0-9]*: note: .#define TWO 2a.\nIn module [^\n]*macro-4_a.H, imported at [^\n]*macro-4_e.C:[0-9]*:\n[^\n]*macro-4_a.H:[0-9]*: note: .#define TWO 2.\n} }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+export import "macro-4_b.H";
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Winvalid-imported-macros" }
+
+import bob;
+import "macro-4_a.H";
--- /dev/null
+// { dg-additional-options "-fmodule-header -Dfoo=bar -Dbaz=1 -fdump-lang-module-vops" }
+// command line macros are not exported
+// { dg-module-cmi {} }
+
+// { dg-final { scan-lang-dump-not {Writing macro #define [_a-zA-Z0-9]* at [0-9]*} module } }
--- /dev/null
+// { dg-additional-options "-fmodule-header -Dfoo=bar -Dbaz=2 -fdump-lang-module-vops" }
+// { dg-module-cmi {} }
+
+#undef baz // not exported
+#define baz 3 // exported
+
+
+// { dg-final { scan-lang-dump {Writing macro #define baz at [0-9]*} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Winvalid-imported-macros" }
+
+import "macro-5_a.H";
+import "macro-5_b.H";
+
+#if baz != 3
+#error
+#endif
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#ifndef MACRO_6_H
+#define MACRO_6_H
+#define foo bar baz
+
+#endif
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+export module macro;
+// { dg-module-cmi {macro} }
+import "macro-6_a.H";
+
+#ifndef foo
+#error bad
+#endif
+
+// { dg-final { scan-lang-dump {Reading macro table [^\n]*macro-6_a.H} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+// Macro tables are only loaded when transitively reachable from top
+// level
+
+import macro;
+
+#ifdef foo
+#error bad
+#endif
+
+// { dg-final { scan-lang-dump-not {>Reading macro table "macro-6_a.H"} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+#define MACRO(X) X
+
+export template<int I> int Factory ()
+{
+ // this macro expansion location ends up in the instantiation
+ // emitted by an importer
+ return MACRO(I);
+}
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+export inline int One ()
+{
+ return Factory<1> ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import bar;
+
+int main ()
+{
+ return !(One () == 1);
+}
--- /dev/null
+$root .
+frob map-1_a.nms
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/map-1.map" }
+
+// Ick! no cross-host testing for you!
+// { dg-additional-files map-1.map }
+
+export module frob;
+// { dg-module-cmi "=map-1_a.nms" }
+
+export int frob (int i)
+{
+ return -i;
+}
--- /dev/null
+// Ick!
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/map-1_b.map?MAP" }
+// { dg-additional-files map-1.map }
+
+import frob;
+
+int main ()
+{
+ if (frob (-2) != 2)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+MAP $root .
+MAP frob map-1_a.nms
+I can't see you
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fmodule-mapper=[srcdir]/map-2.map" }
+
+
+// Ick! no cross-host testing for you!
+// { dg-additional-files map-2.map }
+
+export module foo;
+// { dg-error "Interface: no such module" "" { target *-*-* } .-1 }
+// { dg-error "failed reading mapper" "" { target *-*-* } 0 }
+
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo:part1;
+// { dg-module-cmi {foo:part1} }
+struct frob
+{
+ struct inner;
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+
+export module foo:part2;
+// { dg-module-cmi {foo:part2} }
+
+import :part1;
+
+struct frob::inner
+{
+ int i;
+};
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::frob@foo:part1:1::inner'\n \[1\]=decl declaration '::frob@foo:part1:1::inner::inner'\n} module } }
+// { dg-final { scan-lang-dump {Member '::frob@foo:part1:1::inner' entity:0 keyed to foo:part1\[0\] '::frob@foo:part1:1'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :part2;
+export import :part1;
+
+export auto foo ()
+{
+ return frob::inner ();
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending members keyed to foo:part1\[0\] '::frob@foo:part1:1'} module } }
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::frob@foo:part1:1'\n \[1\]=decl definition '::frob@foo:part1:1::inner@foo:part1:1'\n \[2\]=decl declaration '::frob@foo:part1:1::inner@foo:part1:1::__dt '\n( \[.\]=decl declaration '::frob@foo:part1:1::inner@foo:part1:1::__ct '\n)* \[6\]=decl declaration '::frob@foo:part1:1::inner@foo:part1:1::inner@foo:part2:2'\n \[7\]=decl declaration '::frob@foo:part1:1::frob@foo:part1:1'\n \[8\]=decl declaration '::frob@foo:part1:1::__as_base @foo:part1:1'\n \[9\]=binding '::frob'\n} module } }
+// { dg-final { scan-lang-dump {Pendings 0} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module foo;
+
+void f ()
+{
+ frob::inner x;
+ x.i = 17;
+}
+
+// { dg-final { scan-lang-dump {Loaded 1 clusters} module } }
--- /dev/null
+// { dg-module-do link }
+// { dg-additional-options -fmodules-ts }
+
+export module foo:part1;
+// { dg-module-cmi {foo:part1} }
+
+export struct frob
+{
+ void member ();
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+
+export module foo:part2;
+// { dg-module-cmi {foo:part2} }
+
+import :part1;
+
+inline void frob::member ()
+{
+}
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::frob@foo:part1:1::member'\n} module } }
+// { dg-final { scan-lang-dump {Pendings 1} module } }
+// { dg-final { scan-lang-dump {Bindings 0} module } }
+
+// { dg-final { scan-assembler-not {_ZN4frob6memberEv:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks-alias" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :part2;
+export import :part1;
+
+
+// { dg-final { scan-lang-dump { Cluster members:\n \[0\]=decl definition '::frob@foo:part1:1'\n \[1\]=decl declaration '::frob@foo:part1:1::frob@foo:part1:1'\n \[2\]=decl definition '::frob@foo:part1:1::member@foo:part1:1'\n \[3\]=decl declaration '::frob@foo:part1:1::__as_base @foo:part1:1'\n \[4\]=binding '::frob'\n} module } }
+// { dg-final { scan-lang-dump {Bindings 1} module } }
+// { dg-final { scan-lang-dump {Pendings 0} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key .matched. function_decl:'::frob@foo:part1:1::member'} module } }
+
+// { dg-final { scan-assembler-not {_ZN4frob6memberEv:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import foo;
+
+int main ()
+{
+ frob x;
+ x.member ();
+}
+
+// { dg-final { scan-lang-dump {Reading function definition '::frob@foo:1::member@foo:1'} module } }
+
+// { dg-final { scan-assembler {_ZN4frob6memberEv:} } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module Foo;
+// { dg-module-cmi Foo }
+
+export class Bit
+{
+private:
+ unsigned _M_msb:1;
+};
+
+Bit Make () noexcept;
+
+export class Container
+{
+public:
+ void Frob ()
+ {
+ _M_rep = Make ();
+ }
+
+private:
+ Bit _M_rep;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import Foo;
+
+void X ()
+{
+ Container c;
+ c.Frob ();
+}
--- /dev/null
+
+struct timex
+{
+ unsigned modes;
+ int :32;
+ int :32;
+};
+
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-10.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-10.h"
+import "merge-10_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+
+
+
+template<typename _From, bool>
+struct __is_nt_convertible_helper;
+
+template<typename _From>
+class __is_nt_convertible_helper<_From, false>
+{
+ template<typename> static int __test (int);
+ template<typename> static void __test(...);
+
+public:
+ using type = decltype(__test<_From>(0));
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-11.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-11.h"
+import "merge-11_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+
+template<typename _Functor, typename _ArgTypes>
+struct invoke_result;
+
+template<typename _Fn, typename _ArgTypes>
+struct is_invocable;
+
+template<typename _Fn, typename... _Args>
+concept invocable = is_invocable<_Fn, _Args...>::value;
+
+template<typename _Fn, typename _Is>
+requires invocable<_Fn, _Is>
+ using indirect_result_t = typename invoke_result<_Fn, _Is>::type;
+
+template<typename _Tp>
+struct remove_cv;
+
+template<typename _Iter, typename _Proj>
+struct projected
+{
+ using value_type = remove_cv<indirect_result_t<_Proj&, _Iter>>;
+};
+
--- /dev/null
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "merge-12.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-12.h"
+import "merge-12_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+template<typename T> class Base;
+
+template<typename U> class Derived : Base<U>
+{
+ using Base_ = Base<U>;
+ using typename Base_::base_member;
+
+public:
+ base_member Func ();
+};
--- /dev/null
+// { dg-additional-options "-fmodule-header -fconcepts" }
+// { dg-module-cmi {} }
+
+#include "merge-13.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fconcepts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-13.h"
+import "merge-13_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+template<typename T>
+struct TPL
+{
+ T val = 0;
+};
+
+inline TPL<int> x;
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-14.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-14.h"
+import "merge-14_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+struct optional
+{
+ int &get () &;
+ int &&get () &&;
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-15.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-15.h"
+import "merge-15_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{
+};
+
+typedef integral_constant<bool, true> true_type;
+
+void __throw_with_nested_impl (true_type);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+void frob ()
+{
+ __throw_with_nested_impl (integral_constant<bool, true> ());
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename _CharT> class istreambuf_iterator;
+
+void move(char __t);
+void move(istreambuf_iterator<char> &__u);
+
+template<typename _Tp> struct allocator {};
+
+template<typename _Alloc> struct __alloc_traits
+{
+ static void _S_on_swap(_Alloc& __b)
+ {
+ move (__b);
+ }
+
+ typedef allocator<char> other;
+};
+
+template<typename _CharT> class basic_string
+{
+ typedef __alloc_traits<char>::other _Char_alloc_type;
+};
+
+template<typename _CharT> class istreambuf_iterator
+{
+ void frob (const basic_string<char>& __s);
+};
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fno-module-lazy} }
+import "merge-2_a.H";
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module_cmi {} }
+
+struct bob
+{
+ int i;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+struct bob;
+import "merge-3_a.H";
+
+bob b = {1};
+
+void frob ()
+{
+ b.i = 7;
+}
--- /dev/null
+template<typename T> struct Bob
+{
+ struct M
+ {
+ int m;
+ };
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-4.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-4.h"
+import "merge-4_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::template Bob'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::template Bob<T>::template M'} module } }
--- /dev/null
+
+template<bool> struct __truth_type;
+
+template<typename T> struct __traitor
+{
+ enum X { __value = true };
+ typedef typename __truth_type<__value>::__type __type;
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-5.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-5.h"
+import "merge-5_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) const_decl:'::template __traitor<T>::template X<T>::__value'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+
+template<bool>
+struct __truth_type;
+
+template<typename T>
+struct __traitor
+{
+ enum { __value = true }; // Oh, an anonymous templatey thing!
+ typedef typename __truth_type<__value>::__type __type;
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-6.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-6.h"
+import "merge-6_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s field merge key \(matched\) template_decl:'::template __traitor<T>::template #null#'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+template<typename _Tp2, typename _Up2>
+struct __promote_2
+{
+ typedef __typeof__(_Tp2() + _Up2()) __type;
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-7.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-7.h"
+import "merge-7_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::template __promote_2<_Tp2,_Up2>::template __type'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+
+struct __do_is_destructible_impl
+{
+ template<typename _Tp, typename = decltype(_Tp().~_Tp())>
+ static bool __test(int);
+
+ template<typename>
+ static float __test(...);
+};
+
+template<typename _Tp>
+struct __is_destructible_impl
+ : public __do_is_destructible_impl
+{
+ // Requires BINFO merging
+ typedef decltype(__test<_Tp>(0)) type;
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-8.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-8.h"
+import "merge-8_a.H";
+
+// { dg-final { scan-lang-dump {Deduping binfo '::__do_is_destructible_impl'\[0\]} module } }
+// { dg-final { scan-lang-dump {Deduping binfo '::template __is_destructible_impl<_Tp>'\[0\]} module } }
+// { dg-final { scan-lang-dump {Deduping binfo '::template __is_destructible_impl<_Tp>'\[1\]} module } }
--- /dev/null
+using size_t = __SIZE_TYPE__;
+
+namespace std
+{
+// This is a builtin, but should not be a global tree
+ enum class align_val_t: size_t {};
+ // as is this
+ class type_info;
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "merge-9.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "merge-9.h"
+import "merge-9_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[10-9]*'s named merge key \(matched\) type_decl:'::std::align_val_t'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Baz;
+// { dg-module-cmi "Baz" }
+
+void Quux (void);
+
+export void Bar (void);
+
+void Foo (void);
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 "gmf" 1
+void Frob (void);
+# 6 "" 2
+
+module Baz;
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+// { dg-final { scan-lang-dump "Starting module Foo" "module" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module Foo;
+// { dg-final { scan-lang-dump "Starting module Foo" "module" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+export module Baz;
+// { dg-module-cmi "Baz" }
+
+import Foo;
+
+// { dg-final { scan-lang-dump "Starting module Foo" "module" } }
+// { dg-final { scan-lang-dump "Starting module Baz" "module" } }
+// { dg-final { scan-lang-dump "Writing import:1->1 Foo" "module" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module Baz;
+
+// { dg-final { scan-lang-dump "Starting module Baz" "module" } }
+// { dg-final { scan-lang-dump "Found import:1 Foo->1" "module" } }
+// { dg-final { scan-lang-dump "Starting module Foo" "module" } }
--- /dev/null
+// { dg-module-do "run" }
+// { dg-additional-options "-fmodules-ts" }
+
+export module baz;
+// { dg-module-cmi "baz" }
+
+export int Square (int);
+
+float Square (int, int);
+export int Square (int, int, int);
+
+int Prod (int, int);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module baz;
+
+int Square (int a)
+{
+ return Prod (a, a);
+}
+
+float Square (int a, int b)
+{
+ return a * b * 1.5f;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module baz;
+
+int Prod (int a, int b)
+{
+ return a * b;
+}
+
+int Square (int a, int b, int c)
+{
+ return Prod (Square (a, b), c);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import baz;
+
+int Prod (int a, int b)
+{
+ return -a * b; // What kind of crazy math is this?
+}
+
+int Square (float a)
+{
+ return Prod (int (a), int (a));
+}
+
+int main ()
+{
+ if (Square (2) != 4)
+ return 1;
+
+ if (Square (2.0f) != -4)
+ return 1;
+
+ if (Square (2, 3, 4) != 9 * 4)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-do run }
+
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+export int bob (int);
+export float bob (float);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module Bar;
+// { dg-module-cmi "Bar" }
+
+import Foo;
+
+export int frob (int, float);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module Foo;
+
+int bob (int a)
+{
+ return a * 2;
+}
+
+float bob (float b)
+{
+ return b * 1.5f;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module Bar;
+
+int frob (int a, float b)
+{
+ return bob (a) * bob (b);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import Bar;
+
+int main ()
+{
+ return frob (2, 4) != 4 * 6;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module Foo;
+// { dg-module-cmi "Foo" }
+
+export int bob ();
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module Bar;
+// { dg-module-cmi "Bar" }
+
+import Foo;
+
+export int bill ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module Foo;
+
+export int bob (int);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import Bar;
+// { dg-error "CRC mismatch" "" { target *-*-* } 0 }
+// { dg-regexp "Foo: error: failed to read compiled module: Bad file data\n" }
+// { dg-regexp "Bar: error: failed to read compiled module: Bad import dependency\n" }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
+
+int bill ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module linkage;
+// { dg-module-cmi "linkage" }
+
+inline void Foo () {}
+
+export inline void Baz () __attribute__((used));
+
+inline void Bink () {}
+
+export inline void Baz () { Foo (); Bink (); }
+
+extern "C" inline void cfunc (void) __attribute__((used));
+extern "C" inline void cfunc (void) {}
+
+namespace Inner
+{
+ inline void Foo2 () {}
+
+ export inline void Baz2 () __attribute__((used));
+
+ inline void Bink2 () {}
+
+ export inline void Baz2 () { Foo2 (); Bink2 (); }
+}
+
+// These fail until namespace hack is removed
+// { dg-final { scan-assembler "_ZW7linkageE3Foov:" } }
+// { dg-final { scan-assembler "_ZW7linkageE4Binkv:" } }
+// { dg-final { scan-assembler "_ZW7linkageEN5Inner4Foo2Ev:" } }
+// { dg-final { scan-assembler "_ZW7linkageEN5Inner5Bink2Ev:" } }
+// { dg-final { scan-assembler "_Z3Bazv:" } }
+// { dg-final { scan-assembler "_ZN5Inner4Baz2Ev:" } }
+// { dg-final { scan-assembler "cfunc:" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 "header" 1
+inline void Foo () {}
+# 6 "" 2
+export module okely.dokely;
+// { dg-module-cmi "okely.dokely" }
+
+namespace One {
+ namespace Two {
+ inline namespace Three
+ {
+ inline void Foo2 () {}
+
+ export inline void Baz2 () __attribute__((used));
+ export inline void Baz2 () { Foo (); Foo2 (); }
+ }
+ }
+}
+
+// { dg-final { scan-assembler "_Z3Foov:" } }
+// { dg-final { scan-assembler "_ZW5okely6dokelyEN3One3Two5Three4Foo2Ev:" } }
+// { dg-final { scan-assembler "_ZN3One3Two5Three4Baz2Ev:" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module bob;
+// { dg-module-cmi "bob" }
+
+namespace X
+{
+ inline void Foo () __attribute__((used));
+ export inline void Baz () __attribute__((used));
+
+ namespace Y
+ {
+ inline void Quux () __attribute__((used));
+ export inline void Bar () __attribute__((used));
+ }
+
+ inline void Y::Quux () {}
+ inline void Y::Bar () {}
+}
+
+inline void X::Foo () {}
+inline void X::Baz () {}
+
+// { dg-final { scan-assembler "_ZW3bobEN1X3FooEv:" } }
+// { dg-final { scan-assembler "_ZN1X3BazEv:" } }
+// { dg-final { scan-assembler "_ZW3bobEN1X1Y4QuuxEv:" } }
+// { dg-final { scan-assembler "_ZN1X1Y3BarEv:" } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module Frob;
+// { dg-module-cmi "Frob" }
+
+export template <typename T>
+T twice (T x)
+{
+ return x * 2;
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+import Frob;
+
+int main ()
+{
+ return twice (2) != 4;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob;
+// { dg-module-cmi "frob" }
+
+export template <typename T>
+class X
+{
+ T m;
+
+public:
+ void frob (T v) { m = v; }
+
+ T frobber (T v) { return v + m; }
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import frob;
+
+int main ()
+{
+ X<int> x;
+
+ x.frob (3);
+
+ return ! (x.frobber (-3) == 0);
+}
--- /dev/null
+class exception_ptr;
+
+
+void rethrow_exception(exception_ptr);
+
+
+class exception_ptr
+{
+ friend void rethrow_exception(exception_ptr);
+};
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Frob;
+// { dg-module-cmi Frob }
+
+namespace impl
+{
+ export int doit (int);
+}
+
+namespace ompl
+{
+ export int doneit (int);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module Frink;
+// { dg-module-cmi Frink }
+
+import Frob;
+
+export int frab (int x)
+{
+ return impl::doit (x) + ompl::doneit (x);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// The indirect import of frob, with namespaces impl and ompl doesn't
+// affect us.
+static int impl;
+import Frink;
+
+static int ompl;
+
+void corge (int x)
+{
+ impl = x;
+ ompl = frab (x);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -Wno-pedantic" }
+
+module;
+# 5 "gmf" 1
+namespace not_exported
+{
+ // not in purview
+}
+# 10 "" 2
+export module foo;
+// { dg-module-cmi foo }
+
+namespace explicit_export
+{
+}
+
+namespace implicit_export
+{
+ export int bob ();
+}
+
+namespace also_not_exported
+{
+ int bob ();
+}
+
+export namespace explicit_export
+{
+ namespace also_exported
+ {
+ }
+}
+
+// { dg-final { scan-lang-dump-not {Writable bindings at '::not_exported'} "module" } }
+// { dg-final { scan-lang-dump {Writing namespace:[0-9] '::implicit_export', export, public} "module" } }
+// { dg-final { scan-lang-dump {Writing namespace:[0-9] '::explicit_export', export, public} "module" } }
+// { dg-final { scan-lang-dump {Writing namespace:[0-9] '::also_not_exported', public} "module" } }
+// { dg-final { scan-lang-dump {Writing namespace:[0-9] '::explicit_export::also_exported', export, public} "module" } }
+// { dg-final { scan-lang-dump-not {Writing namespace:[0-9] '::not_exported'} "module" } }
+// { dg-final { scan-lang-dump-not {Writing namespace:[0-9] '::std'} "module" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+static int also_not_exported; // ok
+
+void X ()
+{
+ implicit_export::bob ();
+}
+
+static int implicit_export; // { dg-error "different kind" }
+
+void Y ()
+{
+ also_not_exported = 1;
+}
--- /dev/null
+// Check namespace needed only by internal reference is not made visible
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob;
+// { dg-module-cmi frob }
+
+namespace silent
+{
+ namespace inner
+ {
+ static int X ()
+ {
+ return 1;
+ }
+ }
+}
+
+export int f (int y)
+{
+ return y + silent::inner::X ();
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import frob;
+
+int x = silent; // { dg-error "not declared" }
+
+static int silent;
+
+int user ()
+{
+ return f (silent);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob;
+// { dg-module-cmi frob }
+
+namespace
+{
+ int nope;
+}
+
+export int f (int)
+{
+ return nope;
+}
+
+int g (int *a);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+module frob;
+
+namespace
+{
+void *nope; // ok, different nope
+}
+
+void *q (int)
+{
+ f (bool (nope));
+ g (static_cast <int *> (nope));
+ return nope; // Ok sees above nope
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import frob;
+
+namespace
+{
+ float *nope;
+}
+
+float *q ()
+{
+ f (int (*nope));
+ return nope;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+namespace foo {
+
+ export int frob (int i)
+ {
+ return i;
+ }
+
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module bar;
+// { dg-module-cmi bar }
+
+import foo;
+
+namespace bar
+{
+ export int frob (int i)
+ {
+ return i;
+ }
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts --param lazy-modules=1" }
+import bar;
+
+int main ()
+{
+ return bar::frob (0);
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module blinky;
+// { dg-module-cmi blinky }
+
+export struct X
+{
+ struct Inner
+ {
+ int m;
+ Inner (int);
+ int getter () const
+ {
+ return m;
+ }
+ };
+};
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+module blinky;
+
+X::Inner::Inner (int m_)
+ :m (m_)
+{
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import blinky;
+
+int main ()
+{
+ X::Inner i (7);
+
+ if (i.getter () != 7)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+export struct X
+{
+ typedef X *iter;
+
+ int m;
+ X() :m(-1)
+ {
+ }
+
+ void set (int m_)
+ {
+ m = m_;
+ }
+ operator int () const
+ {
+ return m;
+ }
+};
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+import bob;
+
+int main ()
+{
+ X ary[10];
+ X::iter iter;
+ unsigned ix;
+
+ for (ix = 10, iter = ary; ix--; iter++)
+ iter->set (ix);
+
+ for (ix = 10; ix--;)
+ if (ary[ix] + ix != 9)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+
+template<typename T>
+struct traits
+{
+ template<typename U>
+ struct nested
+ { using type = void; };
+
+ template<typename U> requires requires { typename U::type; }
+ struct nested<U>
+ { using type = typename U::type; };
+};
+
+using V = traits<char>::nested<int>::type;
+
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+#include "nested-constr-1.h"
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "nested-constr-1.h"
+import "nested-constr-1_a.H";
+
+struct X
+{
+ using type = int;
+};
+
+traits<char>::nested<X>::type b;
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodules-ts" }
+export module foo;
+// { dg-module-cmi foo }
+
+export template<typename T>
+struct traits
+{
+ template<typename U>
+ struct nested
+ { using type = void; };
+
+ template<typename U> requires requires { typename U::type; }
+ struct nested<U>
+ { using type = typename U::type; };
+};
+
+export using V = traits<char>::nested<int>::type;
+
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodules-ts" }
+export module bar;
+// { dg-module-cmi bar }
+import foo;
+
+struct X
+{
+ using type = int;
+};
+
+export traits<char>::nested<X>::type b;
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodules-ts" }
+
+import bar;
+
+decltype(b) c;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+// { dg-module-do run }
+
+export module node;
+// { dg-module-cmi node }
+
+export template <typename T> void assert (T t)
+{
+ static_assert (sizeof (T) == sizeof (int), "whoops");
+}
+
+export class other
+{
+public:
+ other () :f (5) {}
+ void o () { }
+ int f;
+};
+
+export template<typename T> class baselink : T, other
+{
+public:
+ int Frob ()
+ {
+ o ();
+ return this->T::frob ();
+ }
+};
+
+export template <typename T> bool trait ()
+{
+ return __has_nothrow_assign(T);
+}
+
+export inline bool ptrmemdata (other const &obj)
+{
+ int other::*ptr = &other::f;
+
+ return (obj.*ptr) == 5;
+}
+
+export template<typename T> int ptrmemfn (T const &obj)
+{
+ int (T::*ptr) () const = &T::frob;
+ return (obj.*ptr) ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import node;
+
+struct b
+{
+ int frob () const
+ {
+ return 0;
+ }
+};
+
+int main ()
+{
+ assert (0);
+ baselink<b> thing;
+ thing.Frob ();
+ if (!trait<b> ())
+ return 1;
+
+ if (!ptrmemdata (other ()))
+ return 2;
+
+ if (ptrmemfn (b ()))
+ return 2;
+
+ return 0;
+}
--- /dev/null
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{
+ static constexpr _Tp value = __v;
+ typedef _Tp value_type;
+ typedef integral_constant<_Tp, __v> type;
+};
+
+template<typename _Tp, _Tp __v>
+constexpr _Tp integral_constant<_Tp, __v>::value;
+
+typedef integral_constant<bool, false> false_type;
+
+
+template<typename _T1>
+struct Alien
+{
+};
+
+template<typename _T1>
+bool operator==(const Alien<_T1>& __x, const Alien<_T1>& __y);
+
+template<typename _Rep>
+struct duration;
+
+template<bool _DenIsOne>
+struct __duration_cast_impl
+{
+};
+
+template<typename _ToDur, typename _Rep>
+long Frob (const duration<_Rep>& __d)
+{
+ typedef __duration_cast_impl<// finds ::operator==
+ _ToDur::num == 1> __dc;
+
+ return 0;
+}
+
+template<typename _Rep>
+struct duration
+{
+public:
+ constexpr duration() = default;
+
+ duration (const duration& __d)
+ {
+ Frob <duration> (__d);
+ }
+};
+
+template<typename _Tp>
+struct __atomic_semaphore
+{
+ template<typename _Rep>
+ bool _M_try_acquire_for (const duration<_Rep>& __rtime) noexcept;
+
+ void _M_release() noexcept;
+};
+
+template<long __least_max_value>
+class counting_semaphore
+{
+ __atomic_semaphore<unsigned> _M_sem;
+
+public:
+ explicit counting_semaphore() noexcept;
+
+ void release() noexcept (noexcept (_M_sem._M_release ()));
+};
+
+class stop_token
+{
+public:
+ counting_semaphore<1> _M_done;
+};
+
+bool operator==(const stop_token& __a, const stop_token& __b);
--- /dev/null
+// { dg-additional-options {-std=c++20 -fmodule-header} }
+// { dg-module-cmi {} }
+
+#include "noexcept-1.h"
--- /dev/null
+// { dg-additional-options {-std=c++20 -fmodules-ts -fno-module-lazy} }
+
+#include "noexcept-1.h"
+import "noexcept-1_a.H";
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export namespace detail {
+ using bob = int;
+}
+
+namespace elsewhere {
+export namespace det = ::detail;
+namespace ail = ::detail;
+
+void frob (det::bob);
+
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+module foo;
+
+elsewhere::det::bob j;
+elsewhere::ail::bob k;
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+elsewhere::det::bob j;
+elsewhere::ail::bob k; // { dg-error "does not name a type" }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+namespace detail {
+int i;
+}
+
+namespace elsewhere {
+
+export inline void frob ()
+{
+ using namespace detail;
+ i = 5;
+}
+
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+void foo ()
+{
+ elsewhere::frob ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export namespace std
+{
+}
--- /dev/null
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+
+module;
+# 5 __FILE__ 1
+namespace std {}
+# 7 "" 2
+export module bob;
+// { dg-module-cmi bob }
+
+import foo;
+namespace std {}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module Foo;
+// { dg-module-cmi {Foo} }
+
+namespace Bob
+{
+export int Random ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module Bar;
+// { dg-module-cmi {Bar} }
+
+export import Foo;
+
+namespace Bob
+{
+export int Quux ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export import Foo;
+export import Bar;
+
+namespace Bob
+{
+void Widget ()
+{
+ Random ();
+ Quux ();
+}
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module Foo:A;
+// { dg-module-cmi {Foo:A} }
+
+namespace Bob
+{
+export int Random ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module Foo:B;
+// { dg-module-cmi {Foo:B} }
+
+export import :A;
+
+namespace Bob
+{
+export int Quux ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module Foo;
+// { dg-module-cmi {Foo} }
+
+export import :A;
+export import :B;
+
+namespace Bob
+{
+export void Widget ()
+{
+ Random ();
+ Quux ();
+}
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module nsdmi;
+// { dg-module-cmi nsdmi }
+
+export struct Bob
+{
+ int m = 42;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import nsdmi;
+
+int main ()
+{
+ Bob b;
+
+ return b.m != 42;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module foo;
+// { dg-module-cmi foo }
+
+
+export enum class file_type : signed char { none = 0 };
+
+export class directory_entry
+{
+public:
+ directory_entry(int);
+
+ int _M_path;
+
+ // ICE from deferred_parse NSDMI in as_base class
+ file_type _M_type = file_type::none;
+};
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::directory_entry'\n \[1\]=decl definition '::directory_entry::__as_base '\n \[2\]=decl declaration '::directory_entry::__ct '\n} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fopenmp" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export inline void frob (unsigned (&ary)[64])
+{
+ int sum = 0;
+
+#pragma omp for
+ for (unsigned ix = 0; ix < 64; ix++)
+ sum += ary[ix];
+
+#pragma omp simd safelen(16) aligned (ary : 16)
+ for (unsigned ix = 0; ix < 64; ix++)
+ ary[ix] *= 2;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fopenmp" }
+
+import foo;
+
+unsigned ary[64];
+
+int main ()
+{
+ frob (ary);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+// { dg-regexp "In module imported at \[^\n]*omp-1_c.C:3:1:\nfoo: error: module contains OpenMP, use '-fopenmp' to enable\n" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fopenmp" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+// The OpenMPness doesn't escape to the interface.
+export void frob (unsigned (&ary)[64])
+{
+ int sum = 0;
+
+#pragma omp for
+ for (unsigned ix = 0; ix < 64; ix++)
+ sum += ary[ix];
+
+#pragma omp simd safelen(16) aligned (ary : 16)
+ for (unsigned ix = 0; ix < 64; ix++)
+ ary[ix] *= 2;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import foo;
+
+unsigned ary[64];
+
+int main ()
+{
+ frob (ary);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fmodule-only" }
+
+export module bob;
+// { dg-module-cmi bob }
--- /dev/null
+// { dg-additional-options "-fmodule-only" }
+
+
+int i;
+// { dg-warning "for non-interface" "" { target *-*-* } 0 }
--- /dev/null
+// { dg-options "-fmodule-only" }
+
+
+int i;
+// { dg-warning "for non-interface" "" { target *-*-* } 0 }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+
+module;
+# 5 __FILE__ 1
+
+struct Type {};
+bool operator==(Type const &, Type const &);
+
+# 10 "" 2
+export module Foo;
+// { dg-module-cmi Foo }
+
+export template<typename T>
+bool equal (T const &x, T const &y)
+{
+ return x == y;
+}
+
--- /dev/null
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+
+struct Type {};
+
+import Foo;
+
+bool foo (Type const &t)
+{
+ return equal (t, t);
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+module;
+module; // { dg-error "expected" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+int j;
+module; // { dg-error "not permitted" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+int k;
+module frob; // { dg-error "not permitted" }
+// { dg-prune-output "failed to read" }
+// { dg-prune-output "fatal error:" }
+// { dg-prune-output "compilation terminated" }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi foo:baz }
+
+export module foo:baz;
+
+export int baz ()
+{
+ return -1;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :baz;
+
+export int foo (int a)
+{
+ return a;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+int main ()
+{
+ if (baz () != -1)
+ return 1;
+
+ if (foo (42) != 42)
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo:inter;
+// { dg-module-cmi foo:inter }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo:imp;
+// { dg-module-cmi foo:imp }
+
+import :inter; // ok
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo:inter2;
+// { dg-module-cmi foo:inter2 }
+
+import :imp; // ok
+
+import :inter; // ok at this point
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi !foo }
+
+import :imp; // ok
+
+export import :inter2; // ok
+
+// { dg-regexp "In module imported at \[^\n]*part-2_b.C:6:.,\nof module foo:imp, imported at \[^\n]*part-2_d.C:6:\nfoo:inter: error: interface partition is not exported\n" }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+import :imp; // ok
+
+export import :inter2; // ok
+
+export import :inter; // ok now
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module foo:bar;
+// { dg-module-cmi foo:bar }
+
+int foo (int x)
+{
+ return -x;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo:baz;
+// { dg-module-cmi foo:baz }
+
+int foo (int);
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :bar;
+export import :baz;
+
+export inline int frob (int x)
+{
+ return foo (x);
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]'s named merge key \(new\) function_decl:'::foo'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]'s named merge key \(matched\) function_decl:'::foo'} module } }
+// { dg-final { scan-lang-dump {Cluster sections are \[1,3\)} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+import foo;
+
+int main ()
+{
+ int r = frob (75);
+ return !(r == -75);
+}
+
+// { dg-final { scan-lang-dump { Read:-[0-9]'s named merge key \(unique\) function_decl:'::frob'} module } }
+// { dg-final { scan-lang-dump {> Read:-[0-9]'s named merge key \(unique\) function_decl:'::foo'} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo:part1;
+// { dg-module-cmi {foo:part1} }
+
+struct frob {
+ struct inner {};
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+// detecting an ICE in dumping machinery
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :part1;
+
+export frob foo ()
+{
+ return frob ();
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import foo;
+
+void f ()
+{
+ auto f = foo ();
+
+ decltype (f)::inner x;
+}
--- /dev/null
+// { dg-module-do link }
+// { dg-additional-options -fmodules-ts }
+
+export module foo:exp;
+// { dg-module-cmi foo:exp }
+
+export class Foo
+{
+ Foo ();
+
+public:
+ void Func ();
+
+ static Foo *Factory ();
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export import :exp;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module foo:bits;
+import :exp;
+
+void Foo::Func ()
+{
+}
+
+inline Foo::Foo ()
+{
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module foo;
+import :bits;
+
+Foo *Foo::Factory ()
+{
+ return new Foo ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+int main ()
+{
+ Foo::Factory ()->Func ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo:bill;
+// { dg-module-cmi foo:bill }
+
+export class frob;
+
+export template<int I> class FROB;
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-blocks} }
+
+module foo:bob;
+// { dg-module-cmi foo:bob }
+
+class frob
+{
+public:
+ int field;
+};
+
+template<int J>
+class FROB
+{
+public:
+ static constexpr int val = J;
+};
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::frob'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template FROB'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-blocks} }
+
+export module foo;
+// { dg-module-cmi foo }
+import :bob;
+export import :bill;
+
+int foo (frob *p)
+{
+ return p->field;
+}
+
+int foo (FROB<2> *p)
+{
+ return p->val;
+}
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::frob@foo:bob:1'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template FROB@foo:bob:1'} module } }
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+// { dg-module-cmi {mod:impl} }
+
+module;
+# 6 "inner" 1
+import "part-hdr-1_a.H";
+# 8 "" 2
+module mod:impl;
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi {mod} }
+
+export module mod;
+import mod:impl;
--- /dev/null
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#define FOO(X) int X
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+// { dg-module-cmi {mod:impl} }
+
+module;
+# 6 "inner" 1
+import "part-mac-1_a.H";
+# 8 "" 2
+module mod:impl;
+
+FOO(k);
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi {mod} }
+
+export module mod;
+import mod:impl;
--- /dev/null
+
+template<typename _Tp>
+class allocator {};
+
+template<typename _Alloc> struct allocator_traits;
+
+template<typename _Tp>
+struct allocator_traits <allocator<_Tp>>
+{
+ using pointer = _Tp*;
+};
+
+struct mutex {};
+
+template<typename _Tp, typename _Alloc>
+class Inplace
+{
+public:
+ virtual void _M_dispose() noexcept
+ {
+ // bogus error ambiguous partial specializations
+ typename allocator_traits<_Alloc>::pointer v;
+ }
+};
+
+inline void *
+allocate_shared()
+{
+ return new Inplace<mutex, allocator<mutex>> ();
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "partial-1.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "partial-1.h"
+import "partial-1_a.H";
--- /dev/null
+
+struct X
+{
+ int mfn ();
+};
+
+inline void bob (X &)
+{
+ int (X::*pmf) () = &X::mfn;
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "pmf-1.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "pmf-1.h"
+import "pmf-1_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// The function-scope var is unique
+// { dg-final { scan-lang-dump-times {merge key \(unique\)} 1 module } }
--- /dev/null
+template<typename _Tp>
+struct remove_reference
+{ typedef _Tp FOO; };
+
+template<typename _Tp>
+void forward (typename remove_reference<_Tp>::FOO const& __t)
+{
+}
+
+template<typename _Callable>
+void __invoke(_Callable const & __fn)
+{
+ forward<_Callable const>(__fn);
+}
+
+class _State_baseV2
+{
+public:
+ void _M_set_result()
+ {
+ __invoke (&_State_baseV2::_M_do_set);
+ }
+
+ void _M_do_set();
+};
+
--- /dev/null
+// { dg-additional-options {-fmodule-header -fdump-lang-module-uid} }
+// { dg-module-cmi {} }
+
+#include "pmf-2.h"
+
+// { dg-final { scan-lang-dump-times {Written:-[0-9]* ptrmem type} 1 module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-uid" }
+
+#include "pmf-2.h"
+import "pmf-2_a.H";
+
+// { dg-final { scan-lang-dump {Cloned:-[0-9]* typedef template_type_parm:'::template remove_reference<_Tp>::template FOO<_Tp>'} module } }
+// { dg-final { scan-lang-dump {Created:-[0-9]* ptrmem type} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+int k;
+
+module :private; // { dg-message "sorry, unimplemented: private module fragment" }
+int i;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module bob;
+int k;
+
+module :private; // { dg-error "private module fragment" }
+int i;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+module :private; // { dg-message "sorry, unimplemented: private module fragment" }
+int i;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+int k;
+
+module :private; // { dg-error "private module fragment" }
+int i;
--- /dev/null
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+int i;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+#pragma GCC visibility push (default)
+#pragma GCC visibility pop
+
+import "pragma-1_a.H";
--- /dev/null
+// { dg-additional-options "-fmodules-ts -nostdinc -include [srcdir]/predef-1.h" }
+// { dg-additional-files predef-1.C }
+
+// test macro expansion inside forced header
+
+export module bob;
--- /dev/null
+
+// expands a macro (inside #if conditional) inside forced header.
+// modelled on glibc's stdc_predef.h
+
+#define GCC_IEC_559 1
+
+# if GCC_IEC_559 > 0
+# define STDC_IEC_559__ 1
+# endif
+
--- /dev/null
+
+// expands a macro (inside #if conditional) inside forced header.
+// modelled on glibc's stdc_predef.h
+
+// some builtin macro
+# if __GNUC__ > 0
+# endif
--- /dev/null
+// { dg-additional-options "-fmodules-ts -nostdinc -include [srcdir]/predef-2.h" }
+// { dg-additional-files predef-2.h }
+
+// test macro expansion inside forced header
+
+export module bob:part;
+// { dg-module-cmi bob:part }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -nostdinc -include [srcdir]/predef-2.h" }
+// { dg-additional-files predef-2.h }
+
+// test macro expansion inside forced header
+
+export module bob;
+// { dg-module-cmi bob }
+
+export import :part;
--- /dev/null
+# 0 "preproc-1.C"
+// { dg-additional-options "-fmodule-header -fpreprocessed" }
+// { dg-module-cmi {=gcm.cache/,/preproc-1.C.gcm} }
--- /dev/null
+# 0 "preproc-2_a.H"
+# 0 "<built-in>"
+#define __STDC__ 1
+# 0 "<command-line>"
+#define NAME bob
+# 1 "preproc-2_a.H"
+# 8 "preproc-2_a.H"
+void NAME ();
+
+// { dg-additional-options "-fmodules-ts -fpreprocessed -fdirectives-only" }
+// { dg-module-cmi {,/preproc-2_a.H} }
--- /dev/null
+# 0 "preproc-2_b.C"
+# 0 "<built-in>"
+#define __STDC__ 1
+# 0 "<command-line>"
+# 1 "preproc-2_b.C"
+# 7 "preproc-2_b.C"
+import "./preproc-2_a.H";
+
+#define NAME bill
+
+int NAME = 4;
+
+int bob; // error with header
+
+float NAME; // error with self
+
+// { dg-additional-options "-fmodules-ts -fpreprocessed -fdirectives-only" }
+
+// { dg-regexp {preproc-2_b.C:13:5: error: 'int bob' redeclared as different kind of entity\nIn module ./preproc-2_a.H, imported at preproc-2_b.C:7:\n<command-line>: note: previous declaration 'void bob\(\)'\npreproc-2_a.H:8:6: note: in expansion of macro 'NAME'} }
+
+// { dg-regexp {preproc-2_b.C:9:14: error: conflicting declaration 'float bill'\npreproc-2_b.C:15:7: note: in expansion of macro 'NAME'\npreproc-2_b.C:9:14: note: previous declaration as 'int bill'\npreproc-2_b.C:11:5: note: in expansion of macro 'NAME'} }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+extern "C"
+{
+ // this matches an anticipated fn
+ extern int printf (const char *__restrict, ...);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import "printf-1_a.H";
+
+int main ()
+{
+ printf ("hello world!\n");
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi foo }
+
+
+export module foo;
+export void v ();
--- /dev/null
+// { dg-additional-options {-fmodules-ts -Wno-pedantic} }
+// { dg-module-cmi bar }
+
+
+module;
+# 7 "gmf1" 1
+# 8 "gmf2" 1
+# 9 "gmf3" 1
+import foo;
+# 11 "" 2
+# 12 "" 2
+# 13 "" 2
+export module bar;
+export import foo;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import bar;
+
+int main ()
+{
+ v (0); // { dg-error "too many arguments" }
+}
+
+// { dg -regexp {In module foo, imported at [^\n]*/reparent-1_b.C:14,\nof module bar, imported at [^\n]*/reparent-1_c.C:2:\n[^\n]*/reparent-1_a.C:6:13: note: declared here\n} }
--- /dev/null
+// Check SCC regions are atomic
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export int bar (int);
+export int baz (int = bar (1));
+export int bar (int = baz (1));
+
+// The ordering depends on hash table iteration, which is address-dependent
+
+// { dg-final { scan-lang-dump { Writing named:-[0-9]* function_decl:'::bar'} "module" } }
+// { dg-final { scan-lang-dump { Writing named:-[0-9]* function_decl:'::baz'} "module" } }
+// { dg-final { scan-lang-dump { \.[0-9]*\. Wrote backref:-[0-9]* function_decl:'::ba[rz]'} "module" } }
+// { dg-final { scan-lang-dump { Wrote backref:-[0-9]* function_decl:'::ba[rz]'} "module" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module frob;
+// { dg-module-cmi frob }
+
+export enum X
+{
+ One, Two, Three
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module shadow;
+// { dg-module-cmi shadow }
+
+export struct stat
+{
+};
+
+export void stat ();
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import shadow;
+
+// unfortunately not the exact same diagnostic in both cases :(
+
+void stat (); // { dg-error "conflicts with import" }
+
+struct stat {}; // { dg-error "in a different module" }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename _CharT>
+static inline __attribute__((__always_inline__)) constexpr void
+__constant_char_array_p ()
+{
+}
+
+inline void foo ()
+{
+ __constant_char_array_p<char> ();
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+
+module;
+# 5 "gmf" 1
+static void Bar () {}
+# 7 "" 2
+export module Foo;
+// { dg-module-cmi Foo }
+
+static void Baz () {}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+module Foo;
+
+void Frob ()
+{
+ Bar (); // { dg-error "not declared" }
+ Baz (); // { dg-error "not declared" }
+}
+
+static void Baz () {}
+static void Bar () {}
+
+void Quux ()
+{
+ Bar ();
+ Baz ();
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import Foo;
+
+void Frob ()
+{
+ Bar (); // { dg-error "not declared" }
+ Baz (); // { dg-error "not declared" }
+}
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+
+namespace std
+{
+int bob;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+int *i = &std::bob;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module std;
+// { dg-module-cmi std }
+
+namespace std
+{
+export int frob ()
+{
+ return 1;
+}
+
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import std;
+
+int main ()
+{
+ return !std::frob ();
+}
--- /dev/null
+template<bool __v>
+struct integral_constant {};
+
+typedef integral_constant<true> true_type;
+typedef integral_constant<false> false_type;
+
+template<typename>
+struct __is_not_void_helper
+ : public true_type { };
+
+template<> struct __is_not_void_helper<void>
+ : public false_type { };
+
+template<typename _Tp, typename _Up>
+struct is_same
+ : public integral_constant<__is_same_as(_Tp, _Up)> {};
+
+template<typename _Iterator>
+struct iterator_traits;
+
+template<typename _Tp> requires __is_not_void_helper<_Tp>::value
+struct iterator_traits<_Tp*>;
+
+template<typename _Tp>
+struct iterator {};
+
+template<typename _Iterator>
+class reverse_iterator
+ : public iterator<typename iterator_traits<_Iterator>::value_type>
+{
+};
+
+template<typename _Tp> struct _Deque_iterator;
+
+template<typename _Tp> void __copy_move_a1(_Deque_iterator<_Tp>);
+
+template<typename _Iterator>
+decltype (NOPE (_Iterator{})) __niter_base (reverse_iterator<_Iterator> __it);
+
+
+template<typename _II>
+inline void __copy_move_a (_II __first)
+{
+ __copy_move_a1 (__niter_base (__first));
+}
+
+template<typename _CharT>
+struct __gnu_char_traits
+{
+ static void move (const char* __s2)
+ {
+ __copy_move_a (__s2);
+ }
+};
+
+class string_view
+{
+ using t = __gnu_char_traits<char>;
+
+public:
+ string_view (const char* __str) noexcept;
+};
+
+template<typename _Ret>
+void __stoa ()
+{
+ struct _Range_chk {
+ static bool _S_chk (false_type) { return false; }
+ static bool _S_chk (true_type) { return true; }
+ };
+
+ _Range_chk::_S_chk (is_same<_Ret, long>{});
+}
+
+inline void stoi () { __stoa<long> (); }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -std=c++2a} }
+module;
+#include "sv-1.h"
+export module Hello;
+// { dg-module-cmi Hello }
+
+export void SayHello (string_view const &name);
--- /dev/null
+// { dg-additional-options {-std=c++2a -fmodules-ts -fno-module-lazy} }
+#include "sv-1.h"
+import Hello;
+
+#if 0
+int main ()
+{
+ SayHello ("World");
+}
+#endif
+
+void foo ()
+{
+ is_same<long, int> q;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module bob.stuart.kevin;
+// { dg-module-cmi bob.stuart.kevin }
+
+class mytype
+{
+};
+
+void frob (mytype &)
+{
+}
+
+// { dg-final { scan-assembler {_ZW3bob6stuart5kevinE4frobRW_2E6mytype:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob.stuart;
+// { dg-module-cmi bob.stuart }
+
+template <typename T> void inner (T &)
+{
+}
+
+export template <typename T> void foo (T &x)
+{
+ inner (x);
+}
+
+// { dg-final { scan-assembler-not {all must have scan-assembler} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module bob.kevin;
+// { dg-module-cmi bob.kevin }
+
+import bob.stuart;
+
+class mytype
+{
+};
+
+void bar (mytype &m)
+{
+ foo (m);
+}
+
+// { dg-final { scan-assembler {_ZW3bob5kevinE3barRW_1E6mytype:} } }
+// { dg-final { scan-assembler {_ZW3bob6stuartE5innerIW_05kevinE6mytypeEvRT_:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++17" }
+export module t.s;
+// { dg-module-cmi t.s }
+
+struct s;
+
+export s *S;
+
+// { dg-final { scan-assembler {.globa?l[ \t]*_?S\n} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -std=c++17" }
+export module t;
+// { dg-module-cmi t }
+import t.s;
+struct t;
+export void f (t*, decltype (S)){}
+// { dg-final { scan-assembler {_Z1fPW1tE1tPW_01sE1s:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun;
+// We're in cologne!
+// { dg-module-cmi zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun }
+
+class mytype
+{
+};
+
+void frob (mytype &)
+{
+}
+
+// { dg-final { scan-assembler {_ZW4zero4eins4zwei4drei4vier4funf5sechs6sieben4acht4neunE4frobRW_9E6mytype:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun.zehn;
+// We're in cologne!
+// { dg-module-cmi zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun.zehn }
+
+class mytype
+{
+};
+
+void frob (mytype &)
+{
+}
+
+// { dg-final { scan-assembler {_ZW4zero4eins4zwei4drei4vier4funf5sechs6sieben4acht4neun4zehnE4frobRWW0_E6mytype:} } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+export module zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun.zehn.elf;
+// We're in cologne!
+// { dg-module-cmi zero.eins.zwei.drei.vier.funf.sechs.sieben.acht.neun.zehn.elf }
+
+class mytype
+{
+};
+
+void frob (mytype &)
+{
+}
+
+// { dg-final { scan-assembler {_ZW4zero4eins4zwei4drei4vier4funf5sechs6sieben4acht4neun4zehn3elfE4frobRWW1_E6mytype:} } }
--- /dev/null
+// { dg-additional-options "-fmodule-header -isystem [srcdir]/sys" }
+// { dg-module-cmi {} }
+
+#ifndef ALIAS_2_A_SYS
+#define ALIAS_2_A_SYS
+
+int frob (int);
+
+#endif
--- /dev/null
+#define NEXT bob
+int foo ();
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module tdef;
+// { dg-module-cmi tdef }
+
+export struct A
+{
+ typedef int I;
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import tdef;
+
+A::I main ()
+{
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module tdef;
+// { dg-module-cmi tdef }
+
+export typedef int I;
+typedef int J;
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+module tdef;
+
+I yup;
+J yupper;
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import tdef;
+
+I main ()
+{
+ return 0;
+}
+
+J nope; // { dg-error "does not name a type" }
+
+typedef char J;
+
+static J ok;
--- /dev/null
+// { dg-module-do run }
+
+// { dg-additional-options -fmodules-ts }
+export module frob;
+// { dg-module-cmi frob }
+
+export typedef struct { int m; } frob;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module quux;
+// { dg-module-cmi quux }
+import frob;
+
+export int foo (frob *p)
+{
+ return p->m;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import frob;
+import quux;
+
+int main ()
+{
+ frob f {2};
+
+ return !(foo (&f) == 2);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct pthread_attr_t
+// guess where this came from?
+{
+ int m;
+};
+typedef struct pthread_attr_t pthread_attr_t;
+
+struct bob
+{
+};
+export typedef struct bob bob;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+pthread_attr_t obj1;
+struct pthread_attr_t obj2;
+
+bob obj3;
+struct bob obj4; // OK -- we see the implicit typedef
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+struct pthread_attr_t obj2;
+pthread_attr_t obj1; // OK -- we see the implicit typedef
+
+bob obj4;
+// the structure tag is not exported. We find the typedef-name, which
+// is ill-formed
+struct bob obj5; // { dg-error "using typedef-name" }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+typedef float _IO_lock_t;
+
+_IO_lock_t _lock;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+_IO_lock_t bob ()
+{
+ return _lock;
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef struct x
+{
+ int __count;
+} X;
+
+typedef struct
+{
+ int __count;
+} __mbstate_t;
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-alias" }
+
+typedef struct
+{
+ int __count;
+} __mbstate_t;
+
+typedef struct x
+{
+ int __count;
+} X;
+
+import "tdef-6_a.H";
+
+X y;
+__mbstate_t x;
+
+// { dg-final { scan-lang-dump {Read:-[0-9]'s named merge key \(matched\) type_decl:'::__mbstate_t'} module } }
--- /dev/null
+
+constexpr void duration_cast ()
+{
+ // the constexpr's body's clone merely duplicates the TYPE_DECL, it
+ // doesn't create a kosher typedef
+ typedef int __to_rep;
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "tdef-7.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias-uid" }
+
+#include "tdef-7.h"
+import "tdef-7_a.H";
+
+// { dg-final { scan-lang-dump-times {merge key \(matched\) function_decl:'::duration_cast} 1 module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-times {merge key \(unique\) type_decl:'#null#'} 2 module } }
+// { dg-final { scan-lang-dump-times {Cloned:-[0-9]* typedef integer_type:'::duration_cast::__to_rep'} 1 module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+// from tr1/type_traits
+export struct __sfinae_types
+{
+ // anon struct with tdef name
+ typedef struct { int i; } __two;
+};
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+int frob (__sfinae_types::__two *p)
+{
+ return p->i;
+}
--- /dev/null
+
+template <typename T>
+class basic_string;
+
+typedef basic_string<char> string;
+
+template <typename T>
+class basic_string
+{
+ public:
+ string Frob ();
+
+ basic_string (int);
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+// The instantiation of the *definition* of basic_string is used in
+// importers, *after* they have instantiated a declaration of it *and*
+// created type variants.
+
+module;
+
+#include "tdef-inst-1.h"
+
+export module foo;
+// { dg-module-cmi foo }
+
+export inline int greeter (string const &bob)
+{
+ return sizeof (bob); // instantiates string
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+#include "tdef-inst-1.h"
+import foo;
+
+string Quux ()
+{
+ return 1; // failed to find converting ctor of string
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct Base
+{
+ virtual ~Base () {}
+ int m;
+};
+
+// Force the creation of implicit members, because we get that wrong
+// in the importer and think its imported (as of 2018-11-27 this
+// causes an ICE, previously it happened to work in this particular
+// testcase.
+Base x;
+
+export struct Derived : virtual Base
+{
+ ~Derived () {}
+};
+
+Derived y;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module baz;
+// { dg-module-cmi baz }
+
+import foo;
+
+export struct Container : virtual Derived
+{
+ Container () {}
+ ~Container () {}
+};
+
+
+
--- /dev/null
+
+template<typename _Iterator, typename>
+struct Trait;
+
+template<typename _Iterator>
+struct Trait<_Iterator, void> {};
+
+template<typename _Iterator>
+requires true
+struct Trait<_Iterator, void>
+{
+ template<typename _Iter> struct __diff {};
+
+ template<typename _Iter> requires true struct __diff<_Iter> {};
+};
--- /dev/null
+// { dg-additional-options "-fmodule-header -std=c++2a" }
+// { dg-module-cmi {} }
+#include "tmpl-part-req-1.h"
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "tmpl-part-req-1.h"
+import "tmpl-part-req-1_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+
+template<typename _Iterator, typename>
+struct Trait;
+
+template<typename _Iterator>
+struct Trait<_Iterator, void> {};
+
+template<typename _Iterator>
+requires true && true
+struct Trait<_Iterator, void>
+{
+ template<typename _Iter> struct __cat {};
+
+ template<typename _Iter> requires true struct __cat<_Iter> {};
+};
+
+template<typename _Iterator>
+requires true
+struct Trait<_Iterator, void>
+{
+ template<typename _Iter> struct __diff {};
+
+ template<typename _Iter> requires true struct __diff<_Iter> {};
+};
--- /dev/null
+// { dg-additional-options "-fmodule-header -std=c++2a" }
+// { dg-module-cmi {} }
+#include "tmpl-part-req-2.h"
--- /dev/null
+// { dg-additional-options "-std=c++2a -fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "tmpl-part-req-2.h"
+import "tmpl-part-req-2_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+# 3 __FILE__ 1
+module ; // { dg-error "cannot be in included file" }
+export module bob; // { dg-error "cannot be in included file" }
+# 6 "" 2
+// { dg-module-cmi !bob }
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+# 1 "other_name"
+module ;
+export module bob;
+// { dg-module-cmi bob }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+#define SEMI ; // this is ok since p1857
+import bob SEMI
+#define IMPORT import // { dg-error "does not name a type" }
+IMPORT bob ;
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+# 3 __FILE__ 1
+export module bob; // { dg-error "in included file" }
+# 6 "" 2
+// { dg-module-cmi !bob }
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+#define MODULE module // { dg-error "does not name a type" }
+export MODULE bob; // { dg-error "may only occur after" }
+// { dg-module-cmi !bob }
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module;
+
+class X; // { dg-error "global module fragment contents" }
+
+class Y;
+
+export module frob;
+// { dg-module-cmi !frob }
+// { dg-prune-output "not writing module" }
--- /dev/null
+template<typename _Ptr> struct pointer_traits;
+
+template<typename _Tp>
+struct pointer_traits<_Tp*>
+{
+ template<typename _Up> using rebind = _Up*;
+};
+
+template<typename _Ptr, typename _Tp>
+using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
+
+template<typename _Tp>
+struct allocator
+{
+ typedef _Tp value_type;
+ typedef _Tp* pointer;
+};
+
+template<typename _Alloc> struct allocator_traits;
+
+template<typename _Tp>
+struct allocator_traits<allocator<_Tp>>
+{
+ using pointer = _Tp*;
+ template<typename _Up>
+ using rebind_alloc = allocator<_Up>;
+};
+
+template<typename _Alloc, typename = typename _Alloc::value_type>
+struct __alloc_traits
+ : allocator_traits<_Alloc>
+{
+ typedef _Alloc allocator_type;
+ typedef allocator_traits<_Alloc> _Base_type;
+ template<typename _Tp>
+ struct rebind
+ {
+ typedef typename _Base_type::template rebind_alloc<_Tp> other;
+ };
+};
+
+template<typename _Ref, typename _Ptr>
+struct _Deque_iterator
+{
+ template<typename _CvTp>
+ using __iter = _Deque_iterator<_CvTp&, __ptr_rebind<_Ptr, _CvTp>>;
+
+ typedef __ptr_rebind<_Ptr, long> _Elt_pointer;
+ typedef __ptr_rebind<_Ptr, _Elt_pointer> _Map_pointer;
+};
+
+template<typename _Alloc>
+struct _Deque_base
+{
+ typedef typename __alloc_traits<_Alloc>::template rebind<long>::other _Tp_alloc_type;
+
+ typedef __alloc_traits<_Tp_alloc_type> _Alloc_traits;
+
+ typedef typename _Alloc_traits::pointer _Ptr;
+
+ typedef _Deque_iterator<long&, _Ptr> iterator;
+
+ typedef typename iterator::_Map_pointer _Map_pointer;
+};
+
+
+inline void stack ()
+{
+ _Deque_base<allocator<long>> c;
+}
--- /dev/null
+// { dg-additional-options "-fmodule-header -fdump-lang-module-alias-uid" }
+// { dg-module-cmi {} }
+
+#include "tpl-alias-1.h"
+
+// { dg-final { scan-lang-dump {Writing named:-[0-9]* template_decl:'::allocator_traits<::allocator<long int>>::template rebind_alloc<_Up>'} module } }
+// { dg-final { scan-lang-dump {Writing decl spec:-[0-9]* type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
+// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
+// { dg-final { scan-lang-dump {Wrote\(-[0-9]*\) alias template type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-uid-alias" }
+
+#include "tpl-alias-1.h"
+import "tpl-alias-1_a.H";
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::allocator_traits<::allocator<long int>>::template rebind_alloc'} module } }
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s decl spec merge key \(matched\) type_decl:'::allocator_traits<::allocator<_Tp>>::rebind_alloc'} module } }
+// { dg-final { scan-lang-dump {Read alias template type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
--- /dev/null
+
+int ary[4];
+extern int unb[];
+typedef int z[0];
+
+
+template<typename _Tp>
+struct __aligned_membuf
+{
+ unsigned char _M_storage[sizeof(_Tp)];
+ _Tp bob[5];
+
+ typedef _Tp ary[5];
+ typedef const ary c_ary;
+};
--- /dev/null
+// { dg-additional-options "-fmodule-header -Wno-pedantic" }
+// { dg-module-cmi {} }
+
+#include "tpl-ary-1.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "tpl-ary-1.h"
+import "tpl-ary-1_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-not {merge key \(unique\)} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T>
+inline void Foo ()
+{
+ {
+ void Frob ();
+ }
+ {
+ void Frob ();
+ }
+ {
+ void Frob ();
+ }
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-extern-fn-1_a.H";
+
+int main ()
+{
+ Foo<int> ();
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename T>
+inline void Foo ()
+{
+ {
+ extern int EXTERN_;
+ EXTERN_++;
+ }
+ {
+ extern int EXTERN_;
+ EXTERN_++;
+ }
+ {
+ extern int EXTERN_;
+ EXTERN_++;
+ }
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-extern-var-1_a.H";
+
+int main ()
+{
+ Foo<int> ();
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-graph-blocks" }
+// declarations followed by friend injection
+
+export module foo;
+// { dg-module-cmi foo }
+
+void foo (int, void *);
+void foo (float, void *);
+
+template <typename T> class TPL
+{
+ friend void foo (T, void *); // { dg-warning "non-template function" }
+
+ T member;
+};
+
+template class TPL<float>; // instantiate
+
+// binding->465500
+// FUNCTION_DECL->465500
+// DECL_TEMPLATE_INFO->NULL
+// DECL_USE_TEMPLATE->0
+
+// specialization 465500
+// tmpl->333580 template_decl
+// the friend decl implicit template
+
+// args->46b640 tree_vec
+// length:1
+// elt:0 real_type
+
+// do not add this (non-)specialization to the depset table
+// the ::foo fns and TPL should be in different depsets
+// the friend decl should be streamed as part of TPL's definition
+
+// { dg-final { scan-lang-dump-not {Connecting declaration decl template_decl:'::foo'} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::foo'\n \[1\]=decl declaration '::foo'\n \[2\]=binding '::foo'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template TPL'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::TPL'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::TPL<float>'} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+void foo (int x, void *p)
+{
+ auto *obj = reinterpret_cast<TPL<int> *> (p);
+
+ obj->member = x;
+}
+
+void foo (float x, void *p)
+{
+ auto *obj = reinterpret_cast<TPL<float> *> (p);
+
+ obj->member = x;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-graph-blocks" }
+// injection followed by declaration
+
+export module foo;
+// { dg-module-cmi foo }
+
+template <typename T> class TPL
+{
+ friend void foo (T, void *); // { dg-warning "non-template function" }
+
+ T member;
+};
+
+template class TPL<int>; // instantiate
+
+void foo (int, void *);
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl definition '::template TPL'\n( \[.\]=[^\n]*'\n)* \[.\]=decl declaration '::template foo'\n( \[.\]=[^\n]*'\n)* \[.\]=binding '::TPL'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::foo<int>'\n \[.\]=binding '::foo'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization definition '::TPL<int>'} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+void foo (int x, void *p)
+{
+ auto *obj = reinterpret_cast<TPL<int> *> (p);
+
+ obj->member = x;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// declarations followed by friend definition injection
+
+export module foo;
+// { dg-module-cmi foo }
+
+void foo (int, void *);
+void foo (float, void *);
+
+template <typename T> class TPL
+{
+ friend void foo (T x, void *p)
+ {
+ auto *obj = reinterpret_cast<TPL<T> *> (p);
+
+ obj->member = x;
+ }
+
+ T member;
+};
+
+template class TPL<float>; // instantiate
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+template class TPL<int>;
+// (instantiated in interface) template class TPL<float>;
+
+void m ()
+{
+ // friend definitions instantiated on-demand here
+ foo (1, 0);
+ foo (1.0f, 0);
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+// friend injection then definition injection
+
+export module foo;
+// { dg-module-cmi foo }
+
+template <typename T> class TPL
+{
+ friend void foo (T, void *); // { dg-warning "non-template function" }
+
+ T member;
+};
+
+template <typename U> class DEF
+{
+ friend void foo (U x, void *p)
+ {
+ auto *obj = reinterpret_cast<TPL<U> *> (p);
+
+ obj->member = x;
+ }
+};
+
+template class TPL<float>; // instantiate
+template class DEF<float>; // instantiate
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+template class TPL<int>;
+template class DEF<int>;
+
+void m ()
+{
+ // ADL to find hidden functions
+ foo (1, (TPL<int> *)0);
+ foo (1.0f, (TPL<int> *)0);
+
+ // no ADL, no find
+ {
+ foo (1, 0); // { dg-error "not declared" }
+ }
+ {
+ foo (1.0f, 0); // { dg-error "not declared" }
+ }
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _CharT> class basic_ios;
+
+template<typename _CharT>
+class basic_streambuf
+{
+ friend class basic_ios<_CharT>;
+
+ _CharT member;
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+module foo;
+
+template class basic_streambuf<char>;
+
+template<typename _CharT> class basic_ios
+{
+public:
+ static void frob (basic_streambuf<_CharT> *p, _CharT val)
+ {
+ p->member = val;
+ }
+};
+
+void bill (basic_streambuf<char> *p)
+{
+ basic_ios<char>::frob (p, 5);
+}
+
+// { dg-final { scan-lang-dump {Lazily binding '::basic_streambuf'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Loading entity foo\[0\] section:1} module } }
+// { dg-final { scan-lang-dump {Loading entity foo\[1\] section:2} module } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+// befriending a specialization
+
+export module foo;
+// { dg-module-cmi foo }
+
+namespace not_std {
+
+template<typename T>
+class basic_streambuf;
+
+template<typename T>
+void __copy_streambufs_eof(basic_streambuf<T>*);
+
+template<typename T>
+class basic_streambuf
+{
+ friend void __copy_streambufs_eof<>(basic_streambuf*);
+
+ T member;
+};
+
+template<>
+void
+__copy_streambufs_eof(basic_streambuf<char>* __sbin);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+namespace not_std {
+
+template<>
+void
+__copy_streambufs_eof(basic_streambuf<char>* __sbin)
+{
+ __sbin->member = 0;
+}
+
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _Tp>
+class new_allocator
+{
+ template<typename _Up>
+ friend bool
+ operator!=(const new_allocator&, const new_allocator<_Up>&)
+ noexcept
+ { return false; }
+};
+
+new_allocator<char> x;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+new_allocator<char> y;
--- /dev/null
+void __istream_extract (int)
+{
+ (void)basic_streambuf<char>::field;
+ (void)basic_streambuf<int>::field;
+ (void)basic_streambuf<long>::field;
+}
--- /dev/null
+
+template<typename T>
+class basic_streambuf
+{
+ friend void __istream_extract (int);
+
+ // something private
+ static constexpr int field = 5;
+};
--- /dev/null
+// { dg-additional-options {-fmodule-header -W} }
+
+// { dg-module-cmi {} }
+
+#include "tpl-friend-merge-1.h"
+extern template class basic_streambuf<char>;
--- /dev/null
+// { dg-additional-options {-fmodule-header -W} }
+
+// { dg-module-cmi {} }
+
+#include "tpl-friend-merge-1.h"
+extern template class basic_streambuf<int>;
--- /dev/null
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+
+void __istream_extract (int);
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+import "tpl-friend-merge-1_a.H";
+import "tpl-friend-merge-1_b.H";
+import "tpl-friend-merge-1_c.H";
+
+#include "tpl-friend-merge-1.cc"
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fno-module-lazy -fdump-lang-module-alias} }
+
+import "tpl-friend-merge-1_a.H";
+import "tpl-friend-merge-1_c.H";
+import "tpl-friend-merge-1_b.H";
+
+#include "tpl-friend-merge-1.cc"
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fno-module-lazy -fdump-lang-module-alias} }
+
+import "tpl-friend-merge-1_c.H";
+import "tpl-friend-merge-1_a.H";
+import "tpl-friend-merge-1_b.H";
+
+#include "tpl-friend-merge-1.cc"
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export template <typename T> int foo (T x)
+{
+ return int (x);
+}
+
+// Body is emitted in module-unit itself
+template <> int foo<int> (int y)
+{
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Dependencies of specialization function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump-not {Depending definition function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization declaration '::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::foo<int>' entity:[0-9]* keyed to TPL\[0\] '::template foo'} module } }
+
+// { dg-final { scan-assembler {_Z3fooIiEiT_:} } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+
+import TPL;
+
+int main ()
+{
+ if (foo (1.0f) != 1)
+ return 1;
+
+ if (foo (1) != 0)
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump-not {Reading definition function_decl '::foo@TPL:.<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization keyed to TPL\[0\] entity:1} module } }
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template foo@TPL:1'} module } }
+
+// { dg-final { scan-assembler-not {_Z3fooIiEiT_:} } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export template <typename T> int foo (T x)
+{
+ return int (x);
+}
+
+// { dg-final { scan-assembler-not {^[a-zA-Z0-9_]*:} } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module SPEC;
+
+export import TPL;
+
+// Body is emitted in module-unit itself
+template <> int foo<int> (int y)
+{
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Dependencies of specialization function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump-not {Depending definition function_decl:'::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization declaration '::foo<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::foo<int>' entity:[0-9]* keyed to TPL\[.\] '::template foo@TPL:.'} module } }
+
+// { dg-final { scan-assembler {_Z3fooIiEiT_:} } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+
+import SPEC;
+
+int main ()
+{
+ if (foo (1.0f) != 1)
+ return 1;
+
+ if (foo (1) != 0)
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template foo@TPL:.'} module } }
+// { dg-final { scan-lang-dump-not {Reading definition function_decl '::foo@TPL:.<int>'} module } }
+
+// { dg-final { scan-assembler-not {_Z3fooIiEiT_:} } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+
+import TPL;
+
+int one ()
+{
+ if (foo (1.0f) != 1)
+ return 1;
+ return 0;
+}
+
+
+import SPEC;
+
+int two ()
+{
+ if (foo (1) != 0)
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template foo@TPL:.'} module } }
+// { dg-final { scan-lang-dump-not {Reading definition function_decl '::foo@TPL:.<int>'} module } }
+
+// { dg-final { scan-assembler-not {_Z3fooIiEiT_:} } }
+// { dg-final { scan-assembler {_Z3fooIfEiT_:} } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export struct frob
+{
+ int i;
+
+ template<typename T> void store (T i_)
+ {
+ i = int (i_);
+ }
+};
+
+// Not inline!
+template <> void frob::store (int i_)
+{
+ i = -i_;
+}
+
+// { dg-final { scan-lang-dump {Dependencies of specialization function_decl:'::frob::store<int>'} module } }
+// { dg-final { scan-lang-dump-not {Depending definition function_decl:'::frob::store<int>'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=specialization declaration '::frob::store<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::frob::store<int>' entity:[0-9]* keyed to TPL\[1\] '::frob::template store'} module } }
+
+// { dg-final { scan-assembler {_ZN4frob5storeIiEEvT_:} } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module} }
+
+import TPL;
+
+int main ()
+{
+ frob f;
+
+ f.store (1);
+ if (f.i != -1)
+ return 1;
+
+ f.store (1.0f);
+ if (f.i != 1)
+ return 2;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[1\] '::frob@TPL:.::template store@TPL:.'} module } }
+// { dg-final { scan-lang-dump-not {Reading definition function_decl '::frob@TPL:.::store@TPL:.<int>'} module } }
+
+// { dg-final { scan-assembler-not {_ZN4frob5storeIiEEvT_:} } }
+
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export template <typename T>
+struct X
+{
+ T f;
+};
+
+template<> struct X<int>
+{
+ int m;
+};
+
+// { dg-final { scan-lang-dump {Dependencies of specialization type_decl:'::X<int>'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n( \[.\]=[^\n]*'\n)* \[.\]=specialization definition '::X<int>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::X<int>' entity:[0-9]* keyed to TPL\[0\] '::template X'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+import TPL;
+
+int main ()
+{
+ X<int> q;
+
+ q.m = 5;
+
+ X<float> p;
+ p.f = 4.0f;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template X@TPL:.'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-graph-blocks} }
+
+export module TPL;
+// { dg-module-cmi TPL }
+
+export template <typename T, int I>
+struct X
+{
+ T ary[I];
+};
+
+template<typename T> struct X<T,1>
+{
+ T scalar;
+};
+
+// { dg-final { scan-lang-dump {Dependency on partial template_decl:'::template X<T,0x1>' found} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n( \[.\][^\n]*'\n)* \[.\]=partial definition '::template X<T,0x1>'} module } }
+// { dg-final { scan-lang-dump {Specialization '::template X<T,0x1>' entity:[0-9]* keyed to TPL\[0\] '::template X'} module } }
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias} }
+
+import TPL;
+
+int main ()
+{
+ X<int,2> q;
+
+ q.ary[0] = 5;
+
+ X<float,1> p;
+ p.scalar = 4.0f;
+
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Reading 1 pending specializations keyed to TPL\[0\] '::template X@TPL:.'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename _Tp, _Tp __v>
+struct integral_constant;
+
+template<typename _From, typename _To, bool>
+struct __is_nt_convertible_helper;
+
+template<typename _From, typename _To>
+class __is_nt_convertible_helper<_From, _To, false>
+{
+ template<typename _To1>
+ static void __test_aux(_To1) noexcept;
+
+ template<typename _From1, typename _To1>
+ static
+ integral_constant<bool, noexcept(__test_aux<_To1> (_From1 ()))>
+ __test(int);
+};
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+module foo;
+
+__is_nt_convertible_helper<int, int, false> ok;
+__is_nt_convertible_helper<int, int, true> not_ok; // { dg-error "incomplete" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+typedef unsigned long size_t;
+
+template<typename _Tp, bool _IsInt, bool _IsEnum>
+class __make_unsigned_selector;
+
+class __make_unsigned_selector_base
+{
+protected:
+ template<typename...> struct _List { };
+
+ template<typename _Tp, typename... _Up>
+ struct _List<_Tp, _Up...> : _List<_Up...>
+ { static constexpr size_t __size = sizeof(_Tp); };
+
+ template<size_t _Sz, typename _Tp, bool = (_Sz <= _Tp::__size)>
+ struct __select;
+};
+
+template<typename _Tp>
+class __make_unsigned_selector<_Tp, false, true>
+ : __make_unsigned_selector_base
+{
+ using _UInts = _List<unsigned char, unsigned short, unsigned int,
+ unsigned long, unsigned long long>;
+
+ using __unsigned_type = typename __select<sizeof(_Tp), _UInts>::__type;
+};
+
+
+
+
+
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template <typename T> class TPL
+{
+ template <typename U> friend void foo (U);
+};
+
+template class TPL<char>;
+
+template <typename V> void foo (V x)
+{
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+void m ()
+{
+ foo ('a');
+ foo (0);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template <typename T>
+class outer
+{
+public:
+ template <typename U>
+ struct inner
+ {
+ typedef outer<U> other;
+ };
+
+ using type = T;
+};
+
+template class outer<int>;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+static_assert (sizeof (outer<int>::inner<char>::other::type) == 1);
+static_assert (sizeof (outer<char>::inner<int>::other::type) == sizeof (int));
--- /dev/null
+typedef long unsigned int size_t;
+
+template<typename _Tp, typename _Up>
+struct Replace;
+
+template<template<typename> class _Template>
+struct Replace<_Template<char>, char>
+{
+ using type = _Template<char>;
+};
+
+template<typename _Tp>
+struct TPL;
+
+template<typename _Alloc>
+struct Traits
+{
+ template<typename _Tp>
+ using Rebind = typename Replace<_Alloc, _Tp>::type;
+};
+
+using tdef = Traits<TPL<char>>::template Rebind<char>;
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "tpl-tpl-merge-1.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "tpl-tpl-merge-1.h"
+import "tpl-tpl-merge-1_a.H";
--- /dev/null
+typedef long unsigned int size_t;
+
+template<typename> class allocator;
+
+template<typename _Tp, typename _Up>
+struct __replace_first_arg
+{ };
+
+template<template<typename, typename...> class _Template, typename _Up,
+ typename _Tp, typename... _Types>
+struct __replace_first_arg<_Template<_Tp, _Types...>, _Up>
+{
+ using type = _Template<_Up, _Types...>;
+};
+
+template<typename _Tp, typename _Up>
+using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type;
+
+template<typename _Tp>
+class new_allocator
+{
+public:
+ typedef _Tp value_type;
+};
+
+template<typename _Tp>
+using __allocator_base = new_allocator<_Tp>;
+
+template<typename _Tp>
+class allocator : public __allocator_base<_Tp>
+{
+public:
+};
+
+struct __allocator_traits_base
+{
+ template<typename _Tp, typename _Up, typename = void>
+ struct __rebind : __replace_first_arg<_Tp, _Up> { };
+};
+
+template<typename _Alloc, typename _Up>
+using __alloc_rebind
+= typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
+
+template<typename _Alloc>
+struct allocator_traits : __allocator_traits_base
+{
+public:
+ template<typename _Tp>
+ using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
+};
+
+template<typename _Alloc, typename = typename _Alloc::value_type>
+struct __alloc_traits
+
+{
+ template<typename _Tp>
+ struct rebind
+ {
+ typedef typename allocator_traits<_Alloc>::template rebind_alloc<_Tp> other;
+ };
+};
+
+typedef typename __alloc_traits<allocator<char>>::template
+rebind<char>::other _Char_alloc_type;
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "tpl-tpl-merge-2.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "tpl-tpl-merge-2.h"
+import "tpl-tpl-merge-2_a.H";
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<template<typename> class _TQual>
+struct basic_common_reference;
+
+template<typename _Tp>
+struct __xref;
+
+template<typename _Tp1>
+using __basic_common_ref
+= typename basic_common_reference<__xref<_Tp1>::template __type>::type;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "tpl-tpl-parm-1_a.H";
+
+template<> struct __xref<int>
+{
+ template <typename T> struct __type;
+};
+
+template<> struct basic_common_reference<__xref<int>::__type>
+{
+ typedef int type;
+};
+
+__basic_common_ref<int> main ()
+{
+ return 0;
+}
--- /dev/null
+
+
+
+template<typename _Alloc>
+struct allocator_traits
+{
+ template<template<typename> class _Func>
+ struct _Ptr {};
+
+ using rebind_alloc = int;
+};
+
+inline void frob ()
+{
+ allocator_traits<int> _M_unpooled;
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "tpl-tpl-parm-2.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "tpl-tpl-parm-2.h"
+import "tpl-tpl-parm-2_a.H";
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module frob;
+// { dg-module-cmi "frob" }
+
+export struct A
+{
+ A ()
+ {
+ }
+
+ template<typename T> operator T () const
+ {
+ return T(99);
+ }
+};
+
+export template<typename T> struct B
+{
+ T m;
+
+ B(T t) : m(t)
+ {
+ }
+
+ template<typename S> operator S () const
+ {
+ return S (m);
+ }
+};
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import frob;
+
+int main ()
+{
+ A a;
+
+ if (int (a) != 99)
+ return 1;
+ if (float (a) != 99)
+ return 2;
+ if (static_cast <void *> (a) != (void *)99)
+ return 3;
+
+ B<int> bi(1);
+ B<float> bf(1.25f);
+ if (int (bi) != 1)
+ return 4;
+ if (int (bf) != 1)
+ return 5;
+
+ // 1.25 is exactly representable
+ if (float (bf) != 1.25f)
+ return 6;
+
+ return 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module billy.bob.thornton;
+// { dg-module-cmi "billy.bob.thornton" }
+
+export template<unsigned I> struct Outer
+{
+ template<unsigned J> struct Inner
+ {
+ static unsigned m ()
+ {
+ return I * J;
+ }
+ };
+};
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import billy.bob.thornton;
+
+int main ()
+{
+ Outer<4>::Inner<16> v;
+
+ if (v.m () != 64)
+ return 1;
+ return 0;
+}
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module bob;
+
+export template<template<typename> class TPL, typename T>
+struct Wrapper
+{
+ using type = TPL<T>;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import bob;
+
+template<typename T> struct X
+{
+ using type = T;
+};
+
+template<typename X, typename Y> struct same;
+template<typename X> struct same<X, X> {};
+
+void frob ()
+{
+ using type = Wrapper<X, int>::type::type;
+
+ same<type, int> v;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<template<typename...> class Arg1>
+struct TPL1;
+
+template<template<typename...> class Arg2>
+struct TPL2;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module foo;
+
+template <template<typename ...> class Arg4>
+struct TPL1
+{
+};
+
+template <template<typename ...> class Arg4>
+struct TPL2
+{
+};
+
+template <typename> class Arg;
+
+
+template struct TPL1<Arg>;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+template<typename Arg1, template<typename> typename Arg2>
+struct TPL
+{
+ using type = char;
+};
+
+/// Implementation of the detection idiom (positive case).
+template<template<typename> typename Op>
+struct TPL <Op<int>, Op>
+{
+ using type = int;
+};
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module foo;
+
+
+template <typename> class Y;
+
+static_assert (sizeof (TPL<Y<char>, Y>::type) == 1);
+static_assert (sizeof (TPL<Y<int>, Y>::type) != 1, "where's my specialization?");
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export template <typename T>
+struct TPL
+{
+ typename T::type m;
+ using type = typename T::type;
+ const type cm;
+};
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+struct X
+{
+ using type = int;
+};
+
+int main ()
+{
+ TPL<X> x {0,1};
+
+ return 0;
+}
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+export module PiL;
+// { dg-module-cmi PiL }
+
+int counter = 0;
+
+export inline int get ()
+{
+ return counter++;
+}
+
+export inline int hwm ()
+{
+ return counter;
+}
+
+// { dg-final { scan-lang-dump {Bindings '::counter' section:1} module } }
+// { dg-final { scan-lang-dump-not {horcrux} module } }
+// { dg-final { scan-lang-dump-not {Unnamed . '::counter'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+
+import PiL;
+
+// Until the linkage is promoted, this won't link.
+
+int main ()
+{
+ int i = get ();
+ if (i)
+ return 1;
+ int h = hwm ();
+ if (h != 1)
+ return 2;
+ return 0;
+}
+
+// { dg-final { scan-lang-dump {Bindings '::counter'} module } }
+// { dg-final { scan-lang-dump {>Loading entity PiL\[0\] section:1} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+export module PiL;
+// { dg-module-cmi PiL }
+
+static int counter = 0;
+
+// These are not inlined, so their bodies don't get into the BMI
+export int get ()
+{
+ return counter++;
+}
+
+export int hwm ()
+{
+ return counter;
+}
+
+// { dg-final { scan-lang-dump-not {Bindings '::counter' section:} module } }
+// { dg-final { scan-lang-dump-not {Unnamed . '::counter'} module } }
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+inline int frob (int x)
+{
+ return x;
+}
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+import "used-1_a.H";
+
+inline int wrapper (int x)
+{
+ return frob (x);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import "used-1_b.H";
+
+int main ()
+{
+ return wrapper (0);
+}
+
+// { dg-final { scan-assembler {_Z4frobi:} } }
--- /dev/null
+// { dg-module-do link }
+// { dg-additional-options "-fmodules-ts" }
+export module frob;
+// { dg-module-cmi frob }
+
+namespace details
+{
+void foo ()
+{
+}
+}
+
+using details::foo;
+void footle ();
+export void bink ()
+{
+ foo ();
+ footle ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+module frob;
+
+void footle ()
+{
+ foo ();
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import frob;
+
+int main ()
+{
+ bink ();
+ return 0;
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+namespace N {
+export int foo (int a)
+{
+ return -a;
+}
+int bar (int a)
+{
+ return -a;
+}
+}
+
+export using N::foo;
+using N::bar;
+
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+module bob;
+
+int a = foo (1);
+int b = bar (2);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import bob;
+
+int a = foo (1);
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+export module bad;
+// { dg-module-cmi !bad }
+
+namespace N
+{
+static int foo ();
+int bar ();
+}
+
+using N::foo;
+using N::bar;
+
+export using N::foo; // { dg-error "does not have external linkage" }
+export using N::bar; // { dg-error "does not have external linkage" }
+
+// { dg-prune-output "not writing module" }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+export module bob;
+// { dg-module-cmi bob }
+
+namespace N {
+export int foo ();
+}
+
+// Only one using decl exported!
+using N::foo;
+export using N::foo;
+
+// { dg-final { scan-lang-dump {Writing section:2 2 depsets} module } }
+// { dg-final { scan-lang-dump {Depset:0 using overload:'::N::foo'} module } }
+// { dg-final { scan-lang-dump {Depset:1 binding namespace_decl:'::foo'} module } }
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+import bob;
+
+int a = foo ();
+
+// { dg-final { scan-lang-dump {Binding of '::foo'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+export module foo;
+// { dg-module-cmi foo }
+
+namespace One {
+class X;
+}
+
+namespace Two {
+using One::X;
+}
+
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::One::X'\n \[1\]=binding '::One::X'} module } }
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=using declaration '::One::X'\n \[1\]=binding '::Two::X'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+module foo;
+
+Two::X *p;
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+export module bob;
+// { dg-module-cmi bob }
+
+namespace A
+{
+export void swap (int &, int &);
+void copy (int &);
+}
+
+export template <typename T>
+void Foo (T & a, T &b)
+{
+ using A::swap;
+ swap (a, b);
+
+ using A::copy;
+ copy (b);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import bob;
+
+int main ()
+{
+ int a = 0, b = 1;
+ Foo (a, b);
+
+ return 0;
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-blocks" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export namespace __gnu_cxx
+{
+enum _Lock_policy { _S_single};
+}
+
+export namespace std
+{
+ using __gnu_cxx::_S_single;
+}
+
+// { dg-final { scan-lang-dump {Writing section:1 4 depsets\n Cluster members:\n \[0\]=decl definition '::__gnu_cxx::_Lock_policy'\n \[1\]=using declaration '::__gnu_cxx::_Lock_policy::_S_single'\n \[2\]=binding '::__gnu_cxx::_[A-Za-z_]*'\n \[3\]=binding '::__gnu_cxx::_[A-Za-z_]*'\n} module } }
+// { dg-final { scan-lang-dump {Writing section:2 2 depsets\n Cluster members:\n \[0\]=using declaration '::__gnu_cxx::_Lock_policy::_S_single'\n \[1\]=binding '::std::_S_single'\n} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -Wno-pedantic" }
+module;
+# 4 __FILE__ 1
+namespace A
+{
+void swap (int &, int &);
+void copy (int &);
+}
+# 10 "" 2
+export module bob;
+// { dg-module-cmi bob }
+
+export template <typename T>
+void Foo (T & a, T &b)
+{
+ using A::swap;
+ swap (a, b);
+
+ using A::copy;
+ copy (b);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+import bob;
+
+int main ()
+{
+ int a = 0, b = 1;
+ Foo (a, b);
+
+ return 0;
+}
+
--- /dev/null
+// { dg-additional-options {-fmodule-header -std=c++2a} }
+// { dg-module-cmi {} }
+
+enum class E {a, b, c};
+struct C
+{
+ using enum E;
+};
+
+struct D: C
+{
+ int foo ()
+ {
+ return int (a);
+ }
+};
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fno-module-lazy -std=c++2a } }
+
+#include "using-enum-1_a.H"
+import "using-enum-1_a.H";
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module Var;
+// { dg-module-cmi Var }
+
+export int counter = 2;
+export extern const int limit = 5;
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import Var;
+
+int main ()
+{
+ if (counter != 2)
+ return 1;
+ if (limit != 5)
+ return 2;
+ static_assert (limit == 5, "huh?");
+ return 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+
+export module frob;
+// { dg-module-cmi frob }
+
+export template<typename T> T sum (T a)
+{
+ return a;
+}
+
+export template<typename T, typename... R>
+inline T sum (T a, R... b)
+{
+ return a + static_cast<T> (sum (b...));
+}
+
+export inline int add (int a, int b, int c)
+{
+ return sum (a, b, c);
+}
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import frob;
+
+int main ()
+{
+ if (6 != add (1, 2, 3))
+ return 1;
+
+ if (10 != sum (1, unsigned (2), 3.0f, 4.0))
+ return 2;
+
+ return 0;
+}
--- /dev/null
+
+template<class _CharT> struct char_traits;
+
+template<typename _CharT, typename _Traits = char_traits<_CharT>>
+class basic_string;
+
+typedef basic_string<char> string;
+
+template<typename> struct iterator_traits;
+
+template<bool _Cond> struct conditional;
+
+template<typename _Iter>
+inline constexpr bool disable_sized_sentinel_for = false;
+
+template<typename _Iter>
+concept sized_sentinel_for = !disable_sized_sentinel_for<_Iter>;
+
+template<typename _Iterator>
+class __normal_iterator
+{
+ typedef iterator_traits<_Iterator> __traits_type;
+};
+
+template<typename _Iterator>
+class reverse_iterator
+{
+public:
+ using iterator_concept
+ = typename conditional<sized_sentinel_for<_Iterator>>::type;
+};
+
+
+template<typename _Iterator>
+requires (!sized_sentinel_for<_Iterator>)
+bool disable_sized_sentinel_for<reverse_iterator<_Iterator>> = true;
+
+
+template<typename _Iterator>
+bool operator==(const reverse_iterator<_Iterator>& __x,
+ const reverse_iterator<_Iterator>& __y);
+template<typename _Iterator>
+bool operator==(const __normal_iterator<_Iterator>& __lhs,
+ const __normal_iterator<_Iterator>& __rhs);
+
+template<typename _It >
+class common_iterator
+{
+public:
+ friend bool operator==(const common_iterator& __x,
+ const common_iterator& __y)
+ {
+ return __x._M_it == __y._M_it;
+ }
+
+private:
+ _It _M_it;
+};
+
+template<typename _It>
+struct iterator_traits<common_iterator<_It>>
+{
+};
+
+template<typename _CharT>
+struct char_traits
+{
+ static bool eq(const _CharT& __c1, const _CharT& __c2)
+ { return __c1 == __c2; }
+};
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fconcepts} }
+module;
+#include "var-tpl-concept-1.h"
+
+export module foo:part1;
+// { dg-module-cmi {foo:part1} }
+
+export void bar (string &);
--- /dev/null
+// { dg-additional-options {-fmodules-ts -fconcepts} }
+module;
+#include "var-tpl-concept-1.h"
+
+export module foo;
+// { dg-module-cmi {foo} }
+
+export import :part1;
+
+export void baz (string &);
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export struct Visitor
+{
+ virtual int Visit ();
+};
+
+// Key function explicitly not in line (regardless of p1779's state)
+// We emit vtables & rtti only in this TU
+int Visitor::Visit ()
+{
+ return 0;
+}
+
+export int Visit (Visitor *v)
+{
+ return v->Visit ();
+}
+
+// { dg-final { scan-assembler {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler {_ZTS7Visitor:} } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+struct Mine : Visitor
+{
+ int Visit () override
+ {
+ return 1;
+ }
+};
+
+int main ()
+{
+ Mine me;
+
+ return !(Visit (&me) == 1);
+}
+
+// We do not emit Visitor vtable or rtti here
+// { dg-final { scan-assembler-not {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler-not {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler-not {_ZTS7Visitor:} } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options -fmodules-ts }
+export module foo;
+// { dg-module-cmi foo }
+
+export struct Visitor
+{
+ virtual int Visit ();
+};
+
+// Key function explicitly inline (regardless of p1779's state)
+// We emit vtables & rtti only in this TU
+inline // Yoink!
+ int Visitor::Visit ()
+{
+ return 0;
+}
+
+export int Visit (Visitor *v)
+{
+ return v->Visit ();
+}
+
+// Emit here
+// { dg-final { scan-assembler {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler {_ZTS7Visitor:} } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+struct Mine : Visitor
+{
+ int Visit () override
+ {
+ return 1;
+ }
+};
+
+extern int Foo ();
+
+int main ()
+{
+ Mine me;
+
+ if (auto b = Foo ())
+ return b;
+ return !(Visit (&me) == 1);
+}
+
+// We do not emit Visitor vtable
+// but we do emit rtti here
+// { dg-final { scan-assembler-not {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler {_ZTS7Visitor:} } }
--- /dev/null
+// { dg-additional-options -fmodules-ts }
+
+import foo;
+
+int Foo ()
+{
+ Visitor v;
+
+ return !(Visit (&v) == 0);
+}
+
+// We do emit Visitor vtable
+// andl also we do emit rtti here
+// { dg-final { scan-assembler {_ZTV7Visitor:} } }
+// { dg-final { scan-assembler {_ZTI7Visitor:} } }
+// { dg-final { scan-assembler {_ZTS7Visitor:} } }
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+export module tom.riddle;
+// { dg-module-cmi tom.riddle }
+
+export inline auto One (int a)
+{
+ struct X {
+ int x;
+ // p1779 makes these things not-inline, which is a surprise.
+ // Asking CWG
+ inline X(int a) :x(a){}
+ inline operator int () const {return x;}
+ };
+
+ return X(a);
+}
+
+// Look Ma! this isn't inline!
+export auto Two (int a)
+{
+ struct Y {
+ int x;
+ // In this case we do manage to emit these fns (if not marked as
+ // inline), but we give them internal linkage, so they are not
+ // nameable from elsewhere. Workaround for now.
+ inline Y(int a) :x(a){}
+ inline operator int () const {return x;}
+ };
+
+ return Y(a);
+}
+
--- /dev/null
+// { dg-additional-options "-fmodules-ts" }
+
+import tom.riddle;
+
+int main ()
+{
+ auto one = One (2);
+
+ if (int (one) != 2)
+ return 1;
+
+ int two = Two (3);
+ if (two != 3)
+ return 2;
+
+ return 0;
+}
--- /dev/null
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-graph-blocks" }
+
+export module voldy;
+// { dg-module-cmi voldy }
+
+export auto frobber (int i)
+{
+ return [=] (int j) { return i + j; };
+}
+
+// { dg-final { scan-lang-dump {Connecting definition decl type_decl:'::frobber::._anon_0'} module } }
+// { dg-final { scan-lang-dump {Entities 5} module } }
+
+// { dg-final { scan-lang-dump {Cluster members:\n \[0\]=decl declaration '::frobber'\n \[1\]=decl definition '::frobber::._anon_0'\n( \[.\]=decl [^\n]*'\n)* \[.\]=binding '::frobber'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-graph-blocks" }
+
+export module malfoy;
+// { dg-module-cmi malfoy }
+
+import voldy;
+
+void interpose ()
+{
+ // Force renumber of anon vars
+ auto lambda = [] () {};
+}
+
+export auto conduit (int i)
+{
+ return frobber (i);
+}
+
+// { dg-final { scan-lang-dump-not {Cluster import } module } }
+// { dg-final { scan-lang-dump-not {onnecting definition decl type_decl:'::frobber@voldy:.::._anon_1@voldy:.'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+
+import malfoy;
+
+void interpose ()
+{
+ // Force renumber of anon vars
+ auto lambda0 = [] () {};
+ auto lambda1 = [] () {};
+ auto lambda2 = [] () {};
+}
+
+int main ()
+{
+ auto widget = conduit (2);
+
+ return !(widget (8) == 10);
+}
+
+// { dg-final { scan-lang-dump {Loading entity voldy\[1\] section:1} module } }
+// { dg-final { scan-lang-dump {Indirect:-[0-9]* decl's type record_type:'::frobber@voldy:.::._anon_3@voldy:.'} module } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -O2 -fno-inline" }
+
+export module foo;
+// { dg-module-cmi foo }
+
+export struct base
+{
+ base () {}
+ virtual ~base ();
+ int m;
+};
+
+base::~base ()
+{
+}
+
+export struct derived : virtual base
+{
+ derived () {}
+ virtual ~derived ();
+ int m2;
+};
+
+derived::~derived ()
+{
+}
+
+export void make_foo ()
+{
+ base b;
+ derived d;
+}
+
+// { dg-final {scan-assembler "_ZTV4base:" } }
+// { dg-final {scan-assembler "_ZTV7derived:" } }
+// { dg-final {scan-assembler "_ZTT7derived:" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -O2 -fno-inline" }
+
+export module bar;
+// { dg-module-cmi bar }
+
+export import foo;
+
+export struct mine : derived
+{
+ mine () {}
+ ~mine ();
+ int mm;
+};
+
+mine::~mine ()
+{
+}
+
+export inline void make_bar ()
+{
+ mine m;
+}
+
+// { dg-final {scan-assembler-not "_ZTV4base:" } }
+// { dg-final {scan-assembler-not "_ZTV7derived:" } }
+// { dg-final {scan-assembler-not "_ZTT7derived:" } }
+// { dg-final {scan-assembler "_ZTV4mine:" } }
+// { dg-final {scan-assembler "_ZTT4mine:" } }
--- /dev/null
+// { dg-additional-options "-fmodules-ts -O2 -fno-inline" }
+
+import bar;
+
+int main ()
+{
+ make_foo ();
+ make_bar ();
+
+ mine m0;
+
+ return 0;
+}
+
+// { dg-final {scan-assembler-not "_ZTV4base:" } }
+// { dg-final {scan-assembler-not "_ZTV7derived:" } }
+// { dg-final {scan-assembler-not "_ZTT7derived:" } }
+// { dg-final {scan-assembler-not "_ZTV4mine:" } }
+// { dg-final {scan-assembler-not "_ZTT4mine:" } }
--- /dev/null
+
+class basic_ios
+{
+public:
+ virtual ~basic_ios();
+ basic_ios();
+};
+
+class basic_ostream : virtual public basic_ios
+{
+public:
+ basic_ostream();
+ virtual ~basic_ostream();
+};
--- /dev/null
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "vtt-2.h"
--- /dev/null
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+
+#include "vtt-2.h"
+import "vtt-2_a.H";
+
+// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
+// { dg-final { scan-lang-dump-times {merge key \(unique\)} 2 module } }