Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions clang/include/clang/Frontend/CompilerInvocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ class CompilerInvocationBase {
}
/// @}

/// Visitation.
/// @{
/// Visits paths stored in the invocation. The callback may return true to
/// short-circuit the visitation, or return false to continue visiting.
void visitPaths(llvm::function_ref<bool(StringRef)> Callback) const;
/// @}

/// Command line generation.
/// @{
using StringAllocator = llvm::function_ref<const char *(const Twine &)>;
Expand Down Expand Up @@ -181,6 +188,12 @@ class CompilerInvocationBase {
/// This is a (less-efficient) wrapper over generateCC1CommandLine().
std::vector<std::string> getCC1CommandLine() const;

protected:
/// Visits paths stored in the invocation. This is generally unsafe to call
/// directly, and each sub-class need to ensure calling this doesn't violate
/// its invariants.
void visitPathsImpl(llvm::function_ref<bool(std::string &)> Predicate);

private:
/// Generate command line options from DiagnosticOptions.
static void GenerateDiagnosticArgs(const DiagnosticOptions &Opts,
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ class FrontendInputFile {
/// Whether we're dealing with a 'system' input (vs. a 'user' input).
bool IsSystem = false;

friend class CompilerInvocationBase;

public:
FrontendInputFile() = default;
FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
Expand Down
80 changes: 80 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5280,6 +5280,86 @@ std::string CompilerInvocation::getModuleHash() const {
return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);
}

void CompilerInvocationBase::visitPathsImpl(
llvm::function_ref<bool(std::string &)> Predicate) {
#define RETURN_IF(PATH) \
do { \
if (Predicate(PATH)) \
return; \
} while (0)

#define RETURN_IF_MANY(PATHS) \
do { \
if (llvm::any_of(PATHS, Predicate)) \
return; \
} while (0)

auto &HeaderSearchOpts = *this->HSOpts;
// Header search paths.
RETURN_IF(HeaderSearchOpts.Sysroot);
for (auto &Entry : HeaderSearchOpts.UserEntries)
if (Entry.IgnoreSysRoot)
RETURN_IF(Entry.Path);
RETURN_IF(HeaderSearchOpts.ResourceDir);
RETURN_IF(HeaderSearchOpts.ModuleCachePath);
RETURN_IF(HeaderSearchOpts.ModuleUserBuildPath);
for (auto &[Name, File] : HeaderSearchOpts.PrebuiltModuleFiles)
RETURN_IF(File);
RETURN_IF_MANY(HeaderSearchOpts.PrebuiltModulePaths);
RETURN_IF_MANY(HeaderSearchOpts.VFSOverlayFiles);

// Preprocessor options.
auto &PPOpts = *this->PPOpts;
RETURN_IF_MANY(PPOpts.MacroIncludes);
RETURN_IF_MANY(PPOpts.Includes);
RETURN_IF(PPOpts.ImplicitPCHInclude);

// Frontend options.
auto &FrontendOpts = *this->FrontendOpts;
for (auto &Input : FrontendOpts.Inputs) {
if (Input.isBuffer())
continue;

RETURN_IF(Input.File);
}
RETURN_IF(FrontendOpts.CodeCompletionAt.FileName);
RETURN_IF_MANY(FrontendOpts.ModuleMapFiles);
RETURN_IF_MANY(FrontendOpts.ModuleFiles);
RETURN_IF_MANY(FrontendOpts.ModulesEmbedFiles);
RETURN_IF_MANY(FrontendOpts.ASTMergeFiles);
RETURN_IF(FrontendOpts.OverrideRecordLayoutsFile);
RETURN_IF(FrontendOpts.StatsFile);

// Filesystem options.
auto &FileSystemOpts = *this->FSOpts;
RETURN_IF(FileSystemOpts.WorkingDir);

// Codegen options.
auto &CodeGenOpts = *this->CodeGenOpts;
RETURN_IF(CodeGenOpts.DebugCompilationDir);
RETURN_IF(CodeGenOpts.CoverageCompilationDir);

// Sanitizer options.
RETURN_IF_MANY(LangOpts->NoSanitizeFiles);

// Coverage mappings.
RETURN_IF(CodeGenOpts.ProfileInstrumentUsePath);
RETURN_IF(CodeGenOpts.SampleProfileFile);
RETURN_IF(CodeGenOpts.ProfileRemappingFile);

// Dependency output options.
for (auto &ExtraDep : DependencyOutputOpts->ExtraDeps)
RETURN_IF(ExtraDep.first);
}

void CompilerInvocationBase::visitPaths(
llvm::function_ref<bool(StringRef)> Callback) const {
// The const_cast here is OK, because visitPathsImpl() itself doesn't modify
// the invocation, and our callback takes immutable StringRefs.
return const_cast<CompilerInvocationBase *>(this)->visitPathsImpl(
[&Callback](std::string &Path) { return Callback(StringRef(Path)); });
}

void CompilerInvocationBase::generateCC1CommandLine(
ArgumentConsumer Consumer) const {
llvm::Triple T(getTargetOpts().Triple);
Expand Down
83 changes: 7 additions & 76 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,82 +471,13 @@ static bool isSafeToIgnoreCWD(const CowCompilerInvocation &CI) {
// Check if the command line input uses relative paths.
// It is not safe to ignore the current working directory if any of the
// command line inputs use relative paths.
#define IF_RELATIVE_RETURN_FALSE(PATH) \
do { \
if (!PATH.empty() && !llvm::sys::path::is_absolute(PATH)) \
return false; \
} while (0)

#define IF_ANY_RELATIVE_RETURN_FALSE(PATHS) \
do { \
if (llvm::any_of(PATHS, [](const auto &P) { \
return !P.empty() && !llvm::sys::path::is_absolute(P); \
})) \
return false; \
} while (0)

// Header search paths.
const auto &HeaderSearchOpts = CI.getHeaderSearchOpts();
IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.Sysroot);
for (auto &Entry : HeaderSearchOpts.UserEntries)
if (Entry.IgnoreSysRoot)
IF_RELATIVE_RETURN_FALSE(Entry.Path);
IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ResourceDir);
IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ModuleCachePath);
IF_RELATIVE_RETURN_FALSE(HeaderSearchOpts.ModuleUserBuildPath);
for (auto I = HeaderSearchOpts.PrebuiltModuleFiles.begin(),
E = HeaderSearchOpts.PrebuiltModuleFiles.end();
I != E;) {
auto Current = I++;
IF_RELATIVE_RETURN_FALSE(Current->second);
}
IF_ANY_RELATIVE_RETURN_FALSE(HeaderSearchOpts.PrebuiltModulePaths);
IF_ANY_RELATIVE_RETURN_FALSE(HeaderSearchOpts.VFSOverlayFiles);

// Preprocessor options.
const auto &PPOpts = CI.getPreprocessorOpts();
IF_ANY_RELATIVE_RETURN_FALSE(PPOpts.MacroIncludes);
IF_ANY_RELATIVE_RETURN_FALSE(PPOpts.Includes);
IF_RELATIVE_RETURN_FALSE(PPOpts.ImplicitPCHInclude);

// Frontend options.
const auto &FrontendOpts = CI.getFrontendOpts();
for (const FrontendInputFile &Input : FrontendOpts.Inputs) {
if (Input.isBuffer())
continue; // FIXME: Can this happen when parsing command-line?

IF_RELATIVE_RETURN_FALSE(Input.getFile());
}
IF_RELATIVE_RETURN_FALSE(FrontendOpts.CodeCompletionAt.FileName);
IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModuleMapFiles);
IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModuleFiles);
IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ModulesEmbedFiles);
IF_ANY_RELATIVE_RETURN_FALSE(FrontendOpts.ASTMergeFiles);
IF_RELATIVE_RETURN_FALSE(FrontendOpts.OverrideRecordLayoutsFile);
IF_RELATIVE_RETURN_FALSE(FrontendOpts.StatsFile);

// Filesystem options.
const auto &FileSystemOpts = CI.getFileSystemOpts();
IF_RELATIVE_RETURN_FALSE(FileSystemOpts.WorkingDir);

// Codegen options.
const auto &CodeGenOpts = CI.getCodeGenOpts();
IF_RELATIVE_RETURN_FALSE(CodeGenOpts.DebugCompilationDir);
IF_RELATIVE_RETURN_FALSE(CodeGenOpts.CoverageCompilationDir);

// Sanitizer options.
IF_ANY_RELATIVE_RETURN_FALSE(CI.getLangOpts().NoSanitizeFiles);

// Coverage mappings.
IF_RELATIVE_RETURN_FALSE(CodeGenOpts.ProfileInstrumentUsePath);
IF_RELATIVE_RETURN_FALSE(CodeGenOpts.SampleProfileFile);
IF_RELATIVE_RETURN_FALSE(CodeGenOpts.ProfileRemappingFile);

// Dependency output options.
for (auto &ExtraDep : CI.getDependencyOutputOpts().ExtraDeps)
IF_RELATIVE_RETURN_FALSE(ExtraDep.first);

return true;
bool AnyRelative = false;
CI.visitPaths([&](StringRef Path) {
assert(!AnyRelative && "Continuing path visitation despite returning true");
AnyRelative |= !Path.empty() && !llvm::sys::path::is_absolute(Path);
return AnyRelative;
});
return !AnyRelative;
}

static std::string getModuleContextHash(const ModuleDeps &MD,
Expand Down
Loading