diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -843,6 +843,21 @@ if (!CI.InitializeSourceManager(Input)) return false; + if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() && + Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) { + // We have an input filename like foo.iih, but we want to find the right + // module name (and original file, to build the map entry). + // Check if the first line specifies the original source file name with a + // linemarker. + std::string PresumedInputFile = std::string(getCurrentFileOrBufferName()); + ReadOriginalFileName(CI, PresumedInputFile); + // Unless the user overrides this, the module name is the name by which the + // original file was known. + if (CI.getLangOpts().ModuleName.empty()) + CI.getLangOpts().ModuleName = std::string(PresumedInputFile); + CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName; + } + // For module map files, we first parse the module map and synthesize a // "" buffer before more conventional processing. if (Input.getKind().getFormat() == InputKind::ModuleMap) { diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -109,10 +109,18 @@ const_cast(getLangOpts()).CurrentModule = HUName.str(); } - auto &Map = PP.getHeaderSearchInfo().getModuleMap(); // TODO: Make the C++20 header lookup independent. - Module::Header H{getLangOpts().CurrentModule, getLangOpts().CurrentModule, - SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())}; + // When the input is pre-processed source, we need a file ref to the original + // file for the header map. + auto F = SourceMgr.getFileManager().getFile(HUName); + // For the sake of error recovery (if someone has moved the original header + // after creating the pre-processed output) fall back to obtaining the file + // ref for the input file, which must be present. + if (!F) + F = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); + assert(F && "failed to find the header unit source?"); + Module::Header H{HUName.str(), HUName.str(), *F}; + auto &Map = PP.getHeaderSearchInfo().getModuleMap(); Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H); assert(Mod && "module creation should not fail"); ModuleScopes.push_back({}); // No GMF diff --git a/clang/test/Modules/cxx20-hu-05.cpp b/clang/test/Modules/cxx20-hu-05.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Modules/cxx20-hu-05.cpp @@ -0,0 +1,32 @@ +// Test macro preservation in C++20 Header Units. + +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// RUN: cd %t + +// Produce a pre-processed file. +// RUN: %clang_cc1 -std=c++20 -E -xc++-user-header hu-01.h -o hu-01.iih + +// consume that to produce the heder unit. +// RUN: %clang_cc1 -std=c++20 -emit-header-unit \ +// RUN: -xc++-header-unit-header-cpp-output hu-01.iih -o hu-01.pcm + +// check that the header unit is named for the original file, not the .iih. +// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \ +// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t + +//--- hu-01.h +#ifndef __GUARD +#define __GUARD + +int baz(int); +#define FORTYTWO 42 + +#define SHOULD_NOT_BE_DEFINED -1 +#undef SHOULD_NOT_BE_DEFINED + +#endif // __GUARD + +// CHECK-HU: ====== C++20 Module structure ====== +// CHECK-HU-NEXT: Header Unit './hu-01.h' is the Primary Module at index #1