// RUN: rm -rf %t // RUN: mkdir -p %t // RUN: split-file %s %t // RUN: %clang_cc1 -std=c++20 -emit-module-interface -o %t/format.pcm %t/format.cppm // RUN: %clang_cc1 -std=c++20 -emit-module-interface -o %t/includes_in_gmf.pcm %t/includes_in_gmf.cppm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/test.cpp -verify -fsyntax-only // RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -o %t/format.pcm %t/format.cppm // RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -o %t/includes_in_gmf.pcm %t/includes_in_gmf.cppm // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/test.cpp -verify -fsyntax-only //--- format.h #pragma once namespace test { template struct type_identity { typedef _Tp type; }; template using type_identity_t = typename type_identity<_Tp>::type; template struct formatter { formatter() = delete; }; template <> struct formatter {}; template struct basic_format_string { static inline const int __handles_{ [] { formatter f; (void)f; return 0; }() }; consteval basic_format_string(const _CharT*) { (void)__handles_; } }; template using wformat_string = basic_format_string...>; template using format_string = basic_format_string...>; template void format(format_string<_Args...> __fmt, _Args&&... __args) {} template void format(wformat_string<_Args...> __fmt, _Args&&... __args) {} } //--- format.cppm module; #include "format.h" export module format; export namespace test { using test::format; using test::formatter; using test::format_string; } auto something() -> void { auto a = 'a'; test::format("{}", a); } //--- includes_in_gmf.cppm module; #include "format.h" export module includes_in_gmf; namespace test { using test::format; using test::formatter; using test::format_string; } //--- test.cpp // expected-no-diagnostics import format; import includes_in_gmf; auto what() -> void { auto a = 'a'; test::format("{}", a); constexpr auto fs = "{}"; // test::format_string{ "{}" }; // <- same result even passing exact param type test::format(fs, 'r'); }