[C++20] [Modules] Remove unmaintained Header Module

Currently there is a -emit-header-module mode, which can combine several
headers together as a module interface. However, this breaks our
assumption (for standard c++ modules) about module interface. The module
interface should come from a module interface unit. And if it is a
header, it should be a header unit. And currently we have no ideas to
combine several headers together.

So I think this mode is an experimental one and it is not maintained and
it is not used. So it will be better to remove them.

Reviewed By: Bigcheese, dblaikie, bruno

Differential Revision: https://reviews.llvm.org/D137609
This commit is contained in:
Chuanqi Xu
2022-11-18 10:13:40 +08:00
parent cab9c02bd9
commit 4a7be42d92
21 changed files with 9 additions and 361 deletions

View File

@@ -436,26 +436,6 @@ public:
}
};
class HeaderModulePrecompileJobAction : public PrecompileJobAction {
void anchor() override;
const char *ModuleName;
public:
HeaderModulePrecompileJobAction(Action *Input, types::ID OutputType,
const char *ModuleName);
static bool classof(const Action *A) {
return A->getKind() == HeaderModulePrecompileJobClass;
}
void addModuleHeaderInput(Action *Input) {
getInputs().push_back(Input);
}
const char *getModuleName() const { return ModuleName; }
};
class ExtractAPIJobAction : public JobAction {
void anchor() override;

View File

@@ -5934,8 +5934,6 @@ def emit_module : Flag<["-"], "emit-module">,
HelpText<"Generate pre-compiled module file from a module map">;
def emit_module_interface : Flag<["-"], "emit-module-interface">,
HelpText<"Generate pre-compiled module file from a C++ module interface">;
def emit_header_module : Flag<["-"], "emit-header-module">,
HelpText<"Generate pre-compiled module file from a set of header files">;
def emit_header_unit : Flag<["-"], "emit-header-unit">,
HelpText<"Generate C++20 header units from header files">;
def emit_pch : Flag<["-"], "emit-pch">,

View File

@@ -155,19 +155,6 @@ private:
CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
};
class GenerateHeaderModuleAction : public GenerateModuleAction {
/// The synthesized module input buffer for the current compilation.
std::unique_ptr<llvm::MemoryBuffer> Buffer;
std::vector<std::string> ModuleHeaders;
private:
bool PrepareToExecuteAction(CompilerInstance &CI) override;
bool BeginSourceFileAction(CompilerInstance &CI) override;
std::unique_ptr<raw_pwrite_stream>
CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
};
class GenerateHeaderUnitAction : public GenerateModuleAction {
private:

View File

@@ -87,9 +87,6 @@ enum ActionKind {
/// Generate pre-compiled module from a C++ module interface file.
GenerateModuleInterface,
/// Generate pre-compiled module from a set of header files.
GenerateHeaderModule,
/// Generate a C++20 header unit module from a header file.
GenerateHeaderUnit,

View File

@@ -566,9 +566,6 @@ public:
/// \returns The newly-created module.
Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name);
/// Create a header module from the specified list of headers.
Module *createHeaderModule(StringRef Name, ArrayRef<Module::Header> Headers);
/// Create a C++20 header unit.
Module *createHeaderUnit(SourceLocation Loc, StringRef Name,
Module::Header H);

View File

@@ -25,7 +25,6 @@ const char *Action::getClassName(ActionClass AC) {
return "offload";
case PreprocessJobClass: return "preprocessor";
case PrecompileJobClass: return "precompiler";
case HeaderModulePrecompileJobClass: return "header-module-precompiler";
case ExtractAPIJobClass:
return "api-extractor";
case AnalyzeJobClass: return "analyzer";
@@ -352,13 +351,6 @@ PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
}
void HeaderModulePrecompileJobAction::anchor() {}
HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
Action *Input, types::ID OutputType, const char *ModuleName)
: PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType),
ModuleName(ModuleName) {}
void ExtractAPIJobAction::anchor() {}
ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType)

View File

@@ -3957,7 +3957,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
: nullptr;
// Construct the actions to perform.
HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr;
ExtractAPIJobAction *ExtractAPIAction = nullptr;
ActionList LinkerInputs;
ActionList MergerInputs;
@@ -4012,16 +4011,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
break;
}
// Each precompiled header file after a module file action is a module
// header of that same module file, rather than being compiled to a
// separate PCH.
if (Phase == phases::Precompile && HeaderModuleAction &&
getPrecompiledType(InputType) == types::TY_PCH) {
HeaderModuleAction->addModuleHeaderInput(Current);
Current = nullptr;
break;
}
if (Phase == phases::Precompile && ExtractAPIAction) {
ExtractAPIAction->addHeaderInput(Current);
Current = nullptr;
@@ -4038,9 +4027,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
if (NewCurrent == Current)
continue;
if (auto *HMA = dyn_cast<HeaderModulePrecompileJobAction>(NewCurrent))
HeaderModuleAction = HMA;
else if (auto *EAA = dyn_cast<ExtractAPIJobAction>(NewCurrent))
if (auto *EAA = dyn_cast<ExtractAPIJobAction>(NewCurrent))
ExtractAPIAction = EAA;
Current = NewCurrent;
@@ -4524,9 +4511,6 @@ Action *Driver::ConstructPhaseAction(
OutputTy = types::TY_Nothing;
}
if (ModName)
return C.MakeAction<HeaderModulePrecompileJobAction>(Input, OutputTy,
ModName);
return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
}
case phases::Compile: {
@@ -5303,10 +5287,6 @@ InputInfoList Driver::BuildJobsForActionNoCache(
if (JA->getType() == types::TY_dSYM)
BaseInput = InputInfos[0].getFilename();
// ... and in header module compilations, which use the module name.
if (auto *ModuleJA = dyn_cast<HeaderModulePrecompileJobAction>(JA))
BaseInput = ModuleJA->getModuleName();
// Append outputs of offload device jobs to the input list
if (!OffloadDependencesInputInfo.empty())
InputInfos.append(OffloadDependencesInputInfo.begin(),

View File

@@ -4539,7 +4539,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsHIPDevice = JA.isDeviceOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
bool IsExtractAPI = isa<ExtractAPIJobAction>(JA);
bool IsDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_Host));
@@ -4554,28 +4553,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction);
auto LTOMode = D.getLTOMode(IsDeviceOffloadAction);
// A header module compilation doesn't have a main input file, so invent a
// fake one as a placeholder.
const char *ModuleName = [&] {
auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ);
return ModuleNameArg ? ModuleNameArg->getValue() : "";
}();
InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName);
// Extract API doesn't have a main input file, so invent a fake one as a
// placeholder.
InputInfo ExtractAPIPlaceholderInput(Inputs[0].getType(), "extract-api",
"extract-api");
const InputInfo &Input = [&]() -> const InputInfo & {
if (IsHeaderModulePrecompile)
return HeaderModuleInput;
if (IsExtractAPI)
return ExtractAPIPlaceholderInput;
return Inputs[0];
}();
InputInfoList ModuleHeaderInputs;
InputInfoList ExtractAPIInputs;
InputInfoList HostOffloadingInputs;
const InputInfo *CudaDeviceInput = nullptr;
@@ -4583,15 +4571,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
for (const InputInfo &I : Inputs) {
if (&I == &Input || I.getType() == types::TY_Nothing) {
// This is the primary input or contains nothing.
} else if (IsHeaderModulePrecompile &&
types::getPrecompiledType(I.getType()) == types::TY_PCH) {
types::ID Expected = HeaderModuleInput.getType();
if (I.getType() != Expected) {
D.Diag(diag::err_drv_module_header_wrong_kind)
<< I.getFilename() << types::getTypeName(I.getType())
<< types::getTypeName(Expected);
}
ModuleHeaderInputs.push_back(I);
} else if (IsExtractAPI) {
auto ExpectedInputType = ExtractAPIPlaceholderInput.getType();
if (I.getType() != ExpectedInputType) {
@@ -4779,9 +4758,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (JA.getType() == types::TY_Nothing)
CmdArgs.push_back("-fsyntax-only");
else if (JA.getType() == types::TY_ModuleFile)
CmdArgs.push_back(IsHeaderModulePrecompile
? "-emit-header-module"
: "-emit-module-interface");
CmdArgs.push_back("-emit-module-interface");
else if (JA.getType() == types::TY_HeaderUnit)
CmdArgs.push_back("-emit-header-unit");
else
@@ -7376,9 +7353,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
addDashXForInput(Args, Input, CmdArgs);
ArrayRef<InputInfo> FrontendInputs = Input;
if (IsHeaderModulePrecompile)
FrontendInputs = ModuleHeaderInputs;
else if (IsExtractAPI)
if (IsExtractAPI)
FrontendInputs = ExtractAPIInputs;
else if (Input.isNothing())
FrontendInputs = {};

View File

@@ -2469,7 +2469,6 @@ static const auto &getFrontendActionTable() {
{frontend::GenerateModule, OPT_emit_module},
{frontend::GenerateModuleInterface, OPT_emit_module_interface},
{frontend::GenerateHeaderModule, OPT_emit_header_module},
{frontend::GenerateHeaderUnit, OPT_emit_header_unit},
{frontend::GeneratePCH, OPT_emit_pch},
{frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
@@ -4129,7 +4128,6 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
case frontend::FixIt:
case frontend::GenerateModule:
case frontend::GenerateModuleInterface:
case frontend::GenerateHeaderModule:
case frontend::GenerateHeaderUnit:
case frontend::GeneratePCH:
case frontend::GenerateInterfaceStubs:

View File

@@ -265,77 +265,6 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
}
bool GenerateHeaderModuleAction::PrepareToExecuteAction(
CompilerInstance &CI) {
if (!CI.getLangOpts().Modules) {
CI.getDiagnostics().Report(diag::err_header_module_requires_modules);
return false;
}
auto &Inputs = CI.getFrontendOpts().Inputs;
if (Inputs.empty())
return GenerateModuleAction::BeginInvocation(CI);
auto Kind = Inputs[0].getKind();
// Convert the header file inputs into a single module input buffer.
SmallString<256> HeaderContents;
ModuleHeaders.reserve(Inputs.size());
for (const FrontendInputFile &FIF : Inputs) {
// FIXME: We should support re-compiling from an AST file.
if (FIF.getKind().getFormat() != InputKind::Source || !FIF.isFile()) {
CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
<< (FIF.isFile() ? FIF.getFile()
: FIF.getBuffer().getBufferIdentifier());
return true;
}
HeaderContents += "#include \"";
HeaderContents += FIF.getFile();
HeaderContents += "\"\n";
ModuleHeaders.push_back(std::string(FIF.getFile()));
}
Buffer = llvm::MemoryBuffer::getMemBufferCopy(
HeaderContents, Module::getModuleInputBufferName());
// Set that buffer up as our "real" input.
Inputs.clear();
Inputs.push_back(
FrontendInputFile(Buffer->getMemBufferRef(), Kind, /*IsSystem*/ false));
return GenerateModuleAction::PrepareToExecuteAction(CI);
}
bool GenerateHeaderModuleAction::BeginSourceFileAction(
CompilerInstance &CI) {
CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderModule);
// Synthesize a Module object for the given headers.
auto &HS = CI.getPreprocessor().getHeaderSearchInfo();
SmallVector<Module::Header, 16> Headers;
for (StringRef Name : ModuleHeaders) {
Optional<FileEntryRef> FE = HS.LookupFile(
Name, SourceLocation(), /*Angled*/ false, nullptr, nullptr, None,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
if (!FE) {
CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
<< Name;
continue;
}
Headers.push_back(
{std::string(Name), std::string(Name), &FE->getFileEntry()});
}
HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers);
return GenerateModuleAction::BeginSourceFileAction(CI);
}
std::unique_ptr<raw_pwrite_stream>
GenerateHeaderModuleAction::CreateOutputFile(CompilerInstance &CI,
StringRef InFile) {
return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
}
bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {
if (!CI.getLangOpts().CPlusPlusModules) {
CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);

View File

@@ -65,8 +65,6 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
return std::make_unique<GenerateModuleFromModuleMapAction>();
case GenerateModuleInterface:
return std::make_unique<GenerateModuleInterfaceAction>();
case GenerateHeaderModule:
return std::make_unique<GenerateHeaderModuleAction>();
case GenerateHeaderUnit:
return std::make_unique<GenerateHeaderUnitAction>();
case GeneratePCH: return std::make_unique<GeneratePCHAction>();

View File

@@ -899,29 +899,6 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
return Result;
}
Module *ModuleMap::createHeaderModule(StringRef Name,
ArrayRef<Module::Header> Headers) {
assert(LangOpts.CurrentModule == Name && "module name mismatch");
assert(!Modules[Name] && "redefining existing module");
auto *Result =
new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
/*IsExplicit*/ false, NumCreatedModules++);
Result->Kind = Module::ModuleInterfaceUnit;
Modules[Name] = SourceModule = Result;
for (const Module::Header &H : Headers) {
auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
/*IsFramework*/ false,
/*IsExplicit*/ true, NumCreatedModules++);
// Header modules are implicitly 'export *'.
M->Exports.push_back(Module::ExportDecl(nullptr, true));
addHeader(M, H, NormalHeader);
}
return Result;
}
Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
Module::Header H) {
assert(LangOpts.CurrentModule == Name && "module name mismatch");

View File

@@ -1 +0,0 @@
#define ATTRS [[ ]]

View File

@@ -1,18 +0,0 @@
// RUN: %clang_cc1 -std=c++2a -emit-header-module -fmodule-name=attrs -x c++-header %S/Inputs/empty.h %S/Inputs/attrs.h -o %t.pcm
// RUN: %clang_cc1 -std=c++2a %s -fmodule-file=%t.pcm -E -verify -I%S/Inputs | FileCheck %s
#define SEMI ;
// expected-error@+1 {{semicolon terminating header import declaration cannot be produced by a macro}}
import "empty.h" SEMI // CHECK: import attrs.{{.*}};
#define IMPORT import "empty.h"
IMPORT; // CHECK: import attrs.{{.*}};
#define IMPORT_ANGLED import <empty.h>
IMPORT_ANGLED; // CHECK: import attrs.{{.*}};
// Ensure that macros only become visible at the semicolon.
// CHECK: import attrs.{{.*}} ATTRS ;
import "attrs.h" ATTRS ;
// CHECK: {{\[\[}} ]] int n;
ATTRS int n;

View File

@@ -1,32 +0,0 @@
// RUN: %clang_cc1 -std=c++2a -emit-header-module -fmodule-name=attrs -x c++-header %S/Inputs/empty.h %S/Inputs/attrs.h -o %t.pcm
// RUN: %clang_cc1 -std=c++2a %s -fmodule-file=%t.pcm -fsyntax-only -verify -I%S/Inputs
template<int> struct import; // expected-note 2{{previous}}
constexpr struct { int h; } empty = {0};
struct A;
struct B;
struct C;
template<> struct import<0> {
static A a;
static B b;
static C c;
};
// OK, not an import-declaration.
struct A {}
::import
<empty.h>::a;
// This is invalid: the tokens after 'import' are a header-name, so cannot be
// parsed as a template-argument-list.
struct B {}
import // expected-error {{redefinition of 'import'}} expected-error {{expected ';'}}
<empty.h>::b; // (error recovery skips these tokens)
// Likewise, this is ill-formed after the tokens are reconstituted into a
// header-name token.
struct C {}
import // expected-error {{redefinition of 'import'}} expected-error {{expected ';'}}
<
empty.h // (error recovery skips these tokens)
>::c;

View File

@@ -1,11 +1,11 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: %clang_cc1 -std=c++2a -x c++-header %S/Inputs/header.h -emit-header-module -fmodule-name=FIXME -o %t/h.pcm
// RUN: %clang_cc1 -std=c++2a %s -DX_INTERFACE -emit-module-interface -o %t/x.pcm
// RUN: %clang_cc1 -std=c++2a %s -DY_INTERFACE -emit-module-interface -o %t/y.pcm
// RUN: %clang_cc1 -std=c++2a %s -DINTERFACE -fmodule-file=%t/x.pcm -fmodule-file=%t/y.pcm -emit-module-interface -o %t/m.pcm
// RUN: %clang_cc1 -std=c++2a %s -DIMPLEMENTATION -I%S/Inputs -fmodule-file=%t/h.pcm -fmodule-file=%t/m.pcm -verify
// RUN: %clang_cc1 -std=c++2a %s -DUSER -I%S/Inputs -fmodule-file=%t/h.pcm -fmodule-file=%t/m.pcm -verify
// RUN: %clang_cc1 -std=c++20 -x c++-header %S/Inputs/header.h -emit-header-unit -o %t/h.pcm
// RUN: %clang_cc1 -std=c++20 %s -DX_INTERFACE -emit-module-interface -o %t/x.pcm
// RUN: %clang_cc1 -std=c++20 %s -DY_INTERFACE -emit-module-interface -o %t/y.pcm
// RUN: %clang_cc1 -std=c++20 %s -DINTERFACE -fmodule-file=%t/x.pcm -fmodule-file=%t/y.pcm -emit-module-interface -o %t/m.pcm
// RUN: %clang_cc1 -std=c++20 %s -DIMPLEMENTATION -I%S/Inputs -fmodule-file=%t/h.pcm -fmodule-file=%t/m.pcm -verify
// RUN: %clang_cc1 -std=c++20 %s -DUSER -I%S/Inputs -fmodule-file=%t/h.pcm -fmodule-file=%t/m.pcm -verify
#if defined(X_INTERFACE)
export module X;

View File

@@ -1,24 +0,0 @@
// Check compiling a header module to a .pcm file.
//
// RUN: %clang -fmodules-ts -fmodule-name=foobar -x c++-header --precompile %S/Inputs/header1.h %S/Inputs/header2.h %S/Inputs/header3.h -o %t.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
//
// CHECK-PRECOMPILE: -cc1 {{.*}} -emit-header-module
// CHECK-PRECOMPILE-SAME: -fmodules-ts
// CHECK-PRECOMPILE-SAME: -fno-implicit-modules
// CHECK-PRECOMPILE-SAME: -fmodule-name=foobar
// CHECK-PRECOMPILE-SAME: -o {{.*}}.pcm
// CHECK-PRECOMPILE-SAME: -x c++-header
// CHECK-PRECOMPILE-SAME: header1.h
// CHECK-PRECOMPILE-SAME: header2.h
// CHECK-PRECOMPILE-SAME: header3.h
//
// RUN: %clang -fmodules-ts -fmodule-name=foobar -x c++-header -fsyntax-only %S/Inputs/header1.h %S/Inputs/header2.h %S/Inputs/header3.h -v 2>&1 | FileCheck %s --check-prefix=CHECK-SYNTAX-ONLY
// CHECK-SYNTAX-ONLY: -cc1 {{.*}} -fsyntax-only
// CHECK-SYNTAX-ONLY-SAME: -fmodules-ts
// CHECK-SYNTAX-ONLY-SAME: -fno-implicit-modules
// CHECK-SYNTAX-ONLY-SAME: -fmodule-name=foobar
// CHECK-SYNTAX-ONLY-NOT: -o{{ }}
// CHECK-SYNTAX-ONLY-SAME: -x c++-header
// CHECK-SYNTAX-ONLY-SAME: header1.h
// CHECK-SYNTAX-ONLY-SAME: header2.h
// CHECK-SYNTAX-ONLY-SAME: header3.h

View File

@@ -39,37 +39,4 @@
// RUN: cp %s %t/module.cppm
// RUN: %clang -std=c++2a --precompile %t/module.cppm -o %t/module.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
// Check compiling a header unit to a .pcm file.
//
// RUN: echo '#define FOO BAR' > %t/foo.h
// RUN: %clang -std=c++2a --precompile -x c++-header %t/foo.h -fmodule-name=header -o %t/foo.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-HEADER-UNIT
//
// CHECK-HEADER-UNIT: -cc1
// CHECK-HEADER-UNIT-SAME: -emit-header-module
// CHECK-HEADER-UNIT-SAME: -fmodule-name=header
// CHECK-HEADER-UNIT-SAME: -o {{.*}}foo.pcm
// CHECK-HEADER-UNIT-SAME: -x c++-header
// CHECK-HEADER-UNIT-SAME: foo.h
// Check use of header unit.
//
// RUN: %clang -std=c++2a -fmodule-file=%t/module.pcm -fmodule-file=%t/foo.pcm -I%t -DIMPORT -Dexport= %s -E -o - -v 2>&1 | FileCheck %s --check-prefix=CHECK-HEADER-UNIT-USE
//
// CHECK-HEADER-UNIT-USE: -cc1
// CHECK-HEADER-UNIT-USE: -E
// CHECK-HEADER-UNIT-USE: -fmodule-file={{.*}}module.pcm
// CHECK-HEADER-UNIT-USE: -fmodule-file={{.*}}foo.pcm
// Note, we use -Dexport= to make this a module implementation unit when building the implementation.
export module foo;
#ifdef IMPORT
// CHECK-HEADER-UNIT-USE: FOO;
FOO;
// CHECK-HEADER-UNIT-USE: import header.{{.*}}foo.h{{.*}};
import "foo.h";
// CHECK-HEADER-UNIT-USE: BAR;
FOO;
#endif

View File

@@ -1,4 +0,0 @@
// RUN: rm -rf %t && mkdir %t
// RUN: not %clang_cc1 -emit-header-module %s -o %t/out.pcm -serialize-diagnostic-file %t/diag 2>&1 | FileCheck %s
// CHECK: error: header module compilation requires '-fmodules', '-std=c++20', or '-fmodules-ts'

View File

@@ -1,48 +0,0 @@
// RUN: %clang_cc1 -fmodules-ts -fmodule-name=ab -x c++-header %S/Inputs/no-module-map/a.h %S/Inputs/no-module-map/b.h -emit-header-module -o %t.pcm
// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify
// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DA
// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DB
// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DA -DB
// RUN: %clang_cc1 -E %t.pcm -o - | FileCheck %s
// RUN: %clang_cc1 -frewrite-imports -E %t.pcm -o - | FileCheck %s
// CHECK: # {{.*}}a.h
// CHECK: # {{.*}}b.h
#ifdef B
// expected-no-diagnostics
#endif
#ifdef A
#include "a.h"
#endif
#ifdef B
#include "b.h"
#endif
#if defined(A) || defined(B)
#ifndef A_H
#error A_H should be defined
#endif
#else
#ifdef A_H
#error A_H should not be defined
#endif
// expected-error@+3 {{must be imported from}}
// expected-note@* {{declaration}}
#endif
void use_a() { a(); }
#if defined(B)
#ifndef B_H
#error B_H should be defined
#endif
#else
#ifdef B_H
#error B_H should not be defined
#endif
// expected-error@+3 {{must be imported from}}
// expected-note@* {{declaration}}
#endif
void use_b() { b(); }