Skip to content

Commit a3221d4

Browse files
committed
[clang] Delay normalization of -fmodules-cache-path
1 parent 5cf9fd0 commit a3221d4

File tree

5 files changed

+55
-70
lines changed

5 files changed

+55
-70
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3281,7 +3281,8 @@ defm declspec : BoolOption<"f", "declspec",
32813281
def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group<i_Group>,
32823282
Flags<[]>, Visibility<[ClangOption, CC1Option]>,
32833283
MetaVarName<"<directory>">,
3284-
HelpText<"Specify the module cache path">;
3284+
HelpText<"Specify the module cache path">,
3285+
MarshallingInfoString<HeaderSearchOpts<"ModuleCachePath">>;
32853286
def fmodules_user_build_path : Separate<["-"], "fmodules-user-build-path">, Group<i_Group>,
32863287
Flags<[]>, Visibility<[ClangOption, CC1Option]>,
32873288
MetaVarName<"<directory>">,

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,9 +548,14 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
548548
}
549549

550550
std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) {
551+
if (getHeaderSearchOpts().ModuleCachePath.empty())
552+
return "";
553+
551554
// Set up the module path, including the hash for the module-creation options.
552555
SmallString<256> SpecificModuleCache(getHeaderSearchOpts().ModuleCachePath);
553-
if (!SpecificModuleCache.empty() && !getHeaderSearchOpts().DisableModuleHash)
556+
FileMgr->makeAbsolutePath(SpecificModuleCache);
557+
llvm::sys::path::remove_dots(SpecificModuleCache);
558+
if (!getHeaderSearchOpts().DisableModuleHash)
554559
llvm::sys::path::append(SpecificModuleCache, ModuleHash);
555560
return std::string(SpecificModuleCache);
556561
}

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3315,9 +3315,6 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
33153315
if (Opts.UseLibcxx)
33163316
GenerateArg(Consumer, OPT_stdlib_EQ, "libc++");
33173317

3318-
if (!Opts.ModuleCachePath.empty())
3319-
GenerateArg(Consumer, OPT_fmodules_cache_path, Opts.ModuleCachePath);
3320-
33213318
for (const auto &File : Opts.PrebuiltModuleFiles)
33223319
GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second);
33233320

@@ -3420,8 +3417,7 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
34203417
}
34213418

34223419
static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
3423-
DiagnosticsEngine &Diags,
3424-
const std::string &WorkingDir) {
3420+
DiagnosticsEngine &Diags) {
34253421
unsigned NumErrorsBefore = Diags.getNumErrors();
34263422

34273423
HeaderSearchOptions *HeaderSearchOpts = &Opts;
@@ -3434,17 +3430,6 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
34343430
if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
34353431
Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
34363432

3437-
// Canonicalize -fmodules-cache-path before storing it.
3438-
SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path));
3439-
if (!(P.empty() || llvm::sys::path::is_absolute(P))) {
3440-
if (WorkingDir.empty())
3441-
llvm::sys::fs::make_absolute(P);
3442-
else
3443-
llvm::sys::fs::make_absolute(WorkingDir, P);
3444-
}
3445-
llvm::sys::path::remove_dots(P);
3446-
Opts.ModuleCachePath = std::string(P);
3447-
34483433
// Only the -fmodule-file=<name>=<file> form.
34493434
for (const auto *A : Args.filtered(OPT_fmodule_file)) {
34503435
StringRef Val = A->getValue();
@@ -5021,8 +5006,7 @@ bool CompilerInvocation::CreateFromArgsImpl(
50215006
InputKind DashX = Res.getFrontendOpts().DashX;
50225007
ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
50235008
llvm::Triple T(Res.getTargetOpts().Triple);
5024-
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,
5025-
Res.getFileSystemOpts().WorkingDir);
5009+
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags);
50265010
if (Res.getFrontendOpts().GenReducedBMI ||
50275011
Res.getFrontendOpts().ProgramAction ==
50285012
frontend::GenerateReducedModuleInterface ||

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 27 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,51 +1185,36 @@ static bool cleanPathForOutput(FileManager &FileMgr,
11851185
return Changed | llvm::sys::path::remove_dots(Path);
11861186
}
11871187

1188-
/// Adjusts the given filename to only write out the portion of the
1189-
/// filename that is not part of the system root directory.
1188+
/// Adjusts the given filename to only write out the portion of the filename
1189+
/// that is not part of the base directory.
11901190
///
11911191
/// \param Filename the file name to adjust.
11921192
///
1193-
/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and
1194-
/// the returned filename will be adjusted by this root directory.
1193+
/// \param BasePath When not empty, the AST file is relocatable and the returned
1194+
/// filename will be adjusted to be relative to this path.
11951195
///
1196-
/// \returns either the original filename (if it needs no adjustment) or the
1197-
/// adjusted filename (which points into the @p Filename parameter).
1198-
static const char *
1199-
adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {
1200-
assert(Filename && "No file name to adjust?");
1201-
1202-
if (BaseDir.empty())
1203-
return Filename;
1204-
1205-
// Verify that the filename and the system root have the same prefix.
1206-
unsigned Pos = 0;
1207-
for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos)
1208-
if (Filename[Pos] != BaseDir[Pos])
1209-
return Filename; // Prefixes don't match.
1210-
1211-
// We hit the end of the filename before we hit the end of the system root.
1212-
if (!Filename[Pos])
1213-
return Filename;
1214-
1215-
// If there's not a path separator at the end of the base directory nor
1216-
// immediately after it, then this isn't within the base directory.
1217-
if (!llvm::sys::path::is_separator(Filename[Pos])) {
1218-
if (!llvm::sys::path::is_separator(BaseDir.back()))
1219-
return Filename;
1220-
} else {
1221-
// If the file name has a '/' at the current position, skip over the '/'.
1222-
// We distinguish relative paths from absolute paths by the
1223-
// absence of '/' at the beginning of relative paths.
1224-
//
1225-
// FIXME: This is wrong. We distinguish them by asking if the path is
1226-
// absolute, which isn't the same thing. And there might be multiple '/'s
1227-
// in a row. Use a better mechanism to indicate whether we have emitted an
1228-
// absolute or relative path.
1229-
++Pos;
1230-
}
1196+
/// \returns true when \c Filename was adjusted, false otherwise.
1197+
static bool adjustFilenameForRelocatableAST(SmallVectorImpl<char> &Filename,
1198+
StringRef BasePath) {
1199+
auto FileIt = llvm::sys::path::begin({Filename.begin(), Filename.size()});
1200+
auto FileEnd = llvm::sys::path::end({Filename.begin(), Filename.size()});
1201+
1202+
auto BaseIt = llvm::sys::path::begin(BasePath);
1203+
auto BaseEnd = llvm::sys::path::end(BasePath);
1204+
1205+
for (; FileIt != FileEnd && BaseIt != BaseEnd; ++FileIt, ++BaseIt)
1206+
if (*FileIt != *BaseIt)
1207+
return false;
1208+
1209+
if (FileIt == FileEnd)
1210+
return false;
1211+
1212+
SmallString<128> Clean;
1213+
for (; FileIt != FileEnd; ++FileIt)
1214+
llvm::sys::path::append(Clean, *FileIt);
12311215

1232-
return Filename + Pos;
1216+
Filename.assign(Clean.begin(), Clean.end());
1217+
return true;
12331218
}
12341219

12351220
std::pair<ASTFileSignature, ASTFileSignature>
@@ -1712,7 +1697,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
17121697

17131698
AddString(HSOpts.Sysroot, Record);
17141699
AddString(HSOpts.ResourceDir, Record);
1715-
AddString(HSOpts.ModuleCachePath, Record);
1700+
AddPath(HSOpts.ModuleCachePath, Record);
17161701
AddString(HSOpts.ModuleUserBuildPath, Record);
17171702
Record.push_back(HSOpts.DisableModuleHash);
17181703
Record.push_back(HSOpts.ImplicitModuleMaps);
@@ -5342,16 +5327,8 @@ bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {
53425327
return false;
53435328

53445329
bool Changed = cleanPathForOutput(PP->getFileManager(), Path);
5345-
5346-
// Remove a prefix to make the path relative, if relevant.
5347-
const char *PathBegin = Path.data();
5348-
const char *PathPtr =
5349-
adjustFilenameForRelocatableAST(PathBegin, BaseDirectory);
5350-
if (PathPtr != PathBegin) {
5351-
Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin));
5330+
if (adjustFilenameForRelocatableAST(Path, BaseDirectory))
53525331
Changed = true;
5353-
}
5354-
53555332
return Changed;
53565333
}
53575334

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// This checks that implicitly-built modules produce identical PCM
2+
// files regardless of the spelling of the same module cache path.
3+
4+
// RUN: rm -rf %t
5+
// RUN: split-file %s %t
6+
7+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fsyntax-only %t/tu.c \
8+
// RUN: -fmodules-cache-path=%t/cache -fdisable-module-hash
9+
// RUN: mv %t/cache/M.pcm %t/M.pcm
10+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fsyntax-only %t/tu.c \
11+
// RUN: -fmodules-cache-path=%t/./cache -fdisable-module-hash
12+
// RUN: diff %t/./cache/M.pcm %t/M.pcm
13+
14+
//--- tu.c
15+
#include "M.h"
16+
//--- M.h
17+
//--- module.modulemap
18+
module M { header "M.h" }

0 commit comments

Comments
 (0)