Skip to content
Draft
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
7 changes: 7 additions & 0 deletions clang/include/clang/Lex/PreprocessorOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,13 @@ class PreprocessorOptions {
FileEntryRef)>
DependencyDirectivesForFile;

/// True if doing dependency scanning.
///
/// NOTE: Used for making \c LangOptions.NeededByPCHOrCompilationUsesPCH
/// benign in the context of explicit modules, it can be removed if
/// \c NeededByPCHOrCompilationUsesPCH is removed.
bool DependencyScanning = false;

/// Set up preprocessor for RunAnalysis action.
bool SetUpStaticAnalyzer = false;

Expand Down
31 changes: 28 additions & 3 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,30 @@ ASTReaderListener::~ASTReaderListener() = default;
static bool checkLanguageOptions(const LangOptions &LangOpts,
const LangOptions &ExistingLangOpts,
DiagnosticsEngine *Diags,
bool AllowCompatibleDifferences = true) {
bool AllowCompatibleDifferences = true,
bool IsDependencyScanning = false) {
// For explicit modules workflow \c NeededByPCHOrCompilationUsesPCH is not a
// meaningful difference for the explicit modules and we canonicalize it away.
// Treat it as "benign" for this ASTReader check.
// NOTE: This can go away if we get rid of NeededByPCHOrCompilationUsesPCH.
bool IsExplicitModulesWorkflow =
IsDependencyScanning || !ExistingLangOpts.ImplicitModules;
bool ExistingNeededByPCHOrCompilationUsesPCH =
ExistingLangOpts.NeededByPCHOrCompilationUsesPCH;
if (IsExplicitModulesWorkflow) {
// Match NeededByPCHOrCompilationUsesPCH to make it "benign".
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't particularly like this hack but I wanted to minimize the differences from upstream when dealing with NeededByPCHOrCompilationUsesPCH.

const_cast<LangOptions &>(ExistingLangOpts)
.NeededByPCHOrCompilationUsesPCH =
LangOpts.NeededByPCHOrCompilationUsesPCH;
}
auto _ = llvm::make_scope_exit([&] {
// Restore original value of NeededByPCHOrCompilationUsesPCH.
if (IsExplicitModulesWorkflow)
const_cast<LangOptions &>(ExistingLangOpts)
.NeededByPCHOrCompilationUsesPCH =
ExistingNeededByPCHOrCompilationUsesPCH;
});

#define LANGOPT(Name, Bits, Default, Description) \
if (ExistingLangOpts.Name != LangOpts.Name) { \
if (Diags) \
Expand Down Expand Up @@ -459,7 +482,8 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
const LangOptions &ExistingLangOpts = PP.getLangOpts();
return checkLanguageOptions(LangOpts, ExistingLangOpts,
Complain ? &Reader.Diags : nullptr,
AllowCompatibleDifferences);
AllowCompatibleDifferences,
PP.getPreprocessorOpts().DependencyScanning);
}

bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
Expand Down Expand Up @@ -5241,7 +5265,8 @@ namespace {
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
bool AllowCompatibleDifferences) override {
return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr,
AllowCompatibleDifferences);
AllowCompatibleDifferences,
ExistingPPOpts.DependencyScanning);
}

bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ class DependencyScanningAction : public tooling::ToolAction {
FileManager *FileMgr,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override {
Invocation->getPreprocessorOpts().DependencyScanning = true;
// Make a deep copy of the original Clang invocation.
CompilerInvocation OriginalInvocation(*Invocation);
// Restore the value of DisableFree, which may be modified by Tooling.
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(

CI.resetNonModularOptions();
CI.clearImplicitModuleBuildOptions();
CI.getLangOpts()->NeededByPCHOrCompilationUsesPCH = false;

// Remove options incompatible with explicit module build or are likely to
// differ between identical modules discovered from different translation
Expand All @@ -109,6 +110,7 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
CI.getCodeGenOpts().CoverageCompilationDir.clear();
CI.getCodeGenOpts().CoverageDataFile.clear();
CI.getCodeGenOpts().CoverageNotesFile.clear();
CI.getCodeGenOpts().RelaxAll = false;
}

// Map output paths that affect behaviour to "-" so their existence is in the
Expand Down
42 changes: 42 additions & 0 deletions clang/test/ClangScanDeps/shared-module-for-tu-and-pch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// RUN: rm -rf %t
// RUN: split-file %s %t

// RUN: sed "s|DIR|%/t|g" %t/cdb.json.debug.template > %t/cdb.debug.json
// RUN: sed "s|DIR|%/t|g" %t/cdb.json.release.template > %t/cdb.release.json

// RUN: clang-scan-deps -compilation-database %t/cdb.debug.json -format=experimental-full -brief | FileCheck %s
// RUN: clang-scan-deps -compilation-database %t/cdb.release.json -format=experimental-full -brief | FileCheck %s
// CHECK: num modules: 1

//--- cdb.json.debug.template
[{
"directory": "DIR",
"file": "DIR/tu.c",
"command": "clang -target x86_64-apple-macosx12 -x c -fmodules -gmodules -fmodules-cache-path=DIR/cache -I DIR/include -c DIR/tu.c -o DIR/tu.o -O0 -g"
},
{
"directory": "DIR",
"file": "DIR/tu.prefix.h",
"command": "clang -target x86_64-apple-macosx12 -x c-header -fmodules -gmodules -fmodules-cache-path=DIR/cache -I DIR/include -c DIR/tu.prefix.h -o DIR/tu.pch -O0 -g"
}]
//--- cdb.json.release.template
[{
"directory": "DIR",
"file": "DIR/tu.c",
"command": "clang -target x86_64-apple-macosx12 -x c -fmodules -gmodules -fmodules-cache-path=DIR/cache -I DIR/include -c DIR/tu.c -o DIR/tu.o -Os -g"
},
{
"directory": "DIR",
"file": "DIR/tu.prefix.h",
"command": "clang -target x86_64-apple-macosx12 -x c-header -fmodules -gmodules -fmodules-cache-path=DIR/cache -I DIR/include -c DIR/tu.prefix.h -o DIR/tu.pch -Os -g"
}]

//--- include/module.modulemap
module Top { header "top.h" }
//--- include/top.h
#define TOP int
//--- tu.c
#include "top.h"
TOP fn(void);
//--- tu.prefix.h
#include "top.h"
9 changes: 9 additions & 0 deletions clang/tools/clang-scan-deps/ClangScanDeps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static std::vector<std::string> ModuleDepTargets;
static bool DeprecatedDriverCommand;
static ResourceDirRecipeKind ResourceDirRecipe;
static bool Verbose;
static bool BriefResult;
static std::vector<const char *> CommandLine;
static bool EmitCASCompDB;
static std::string OnDiskCASPath;
Expand Down Expand Up @@ -239,6 +240,7 @@ static void ParseArgs(int argc, char **argv) {
A->getValues().end());

Verbose = Args.hasArg(OPT_verbose);
BriefResult = Args.hasArg(OPT_brief_result);

RoundTripArgs = Args.hasArg(OPT_round_trip_args);

Expand Down Expand Up @@ -739,6 +741,8 @@ class FullDeps {
OS << llvm::formatv("{0:2}\n", Value(std::move(Output)));
}

size_t getNumModules() const { return Modules.size(); }

private:
struct IndexedModuleID {
ModuleID ID;
Expand Down Expand Up @@ -1316,6 +1320,11 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
if (FD && FD->roundTripCommands(llvm::errs()))
HadErrors = true;

if (BriefResult && FD) {
llvm::outs() << "num modules: " << FD->getNumModules() << '\n';
return HadErrors;
}

std::sort(TreeResults.begin(), TreeResults.end(),
[](const DepTreeResult &LHS, const DepTreeResult &RHS) -> bool {
return LHS.Index < RHS.Index;
Expand Down
2 changes: 2 additions & 0 deletions clang/tools/clang-scan-deps/Opts.td
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ defm prefix_map : Eq<"prefix-map", "Path to remap, as \"<old>=<new>\".">;

def verbose : F<"v", "Use verbose output">;

def brief_result : F<"brief", "Use brief dependency info output">;

def round_trip_args : F<"round-trip-args", "verify that command-line arguments are canonical by parsing and re-serializing">;

def DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>;