Skip to content

[clang][DependencyScanner] Remove all warning flags when suppressing warnings #71612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 14, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ enum class ScanningOptimizations {
/// Remove unused header search paths including header maps.
HeaderSearch = 1,

LLVM_MARK_AS_BITMASK_ENUM(HeaderSearch),
All = HeaderSearch,
/// Remove warnings from system modules.
SystemWarnings = 2,

LLVM_MARK_AS_BITMASK_ENUM(SystemWarnings),
All = HeaderSearch | SystemWarnings,
Default = All
};

Expand Down
26 changes: 26 additions & 0 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,28 @@ static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts,
Opts.UserEntries.push_back(Entries[Idx]);
}

static void optimizeDiagnosticOpts(DiagnosticOptions &Opts,
bool IsSystemModule) {
// If this is not a system module or -Wsystem-headers was passed, don't
// optimize.
if (!IsSystemModule)
return;
bool Wsystem_headers = false;
for (StringRef Opt : Opts.Warnings) {
bool isPositive = !Opt.consume_front("no-");
if (Opt == "system-headers")
Wsystem_headers = isPositive;
}
if (Wsystem_headers)
return;

// Remove all warning flags. System modules suppress most, but not all,
// warnings.
Opts.Warnings.clear();
Opts.UndefPrefixes.clear();
Opts.Remarks.clear();
}

static std::vector<std::string> splitString(std::string S, char Separator) {
SmallVector<StringRef> Segments;
StringRef(S).split(Segments, Separator, /*MaxSplit=*/-1, /*KeepEmpty=*/false);
Expand Down Expand Up @@ -532,6 +554,10 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
if (any(MDC.OptimizeArgs & ScanningOptimizations::HeaderSearch))
optimizeHeaderSearchOpts(BuildInvocation.getMutHeaderSearchOpts(),
*MDC.ScanInstance.getASTReader(), *MF);
if (any(MDC.OptimizeArgs & ScanningOptimizations::SystemWarnings))
optimizeDiagnosticOpts(
BuildInvocation.getMutDiagnosticOpts(),
BuildInvocation.getFrontendOpts().IsSystemModule);
});

MDC.associateWithContextHash(CI, MD);
Expand Down
123 changes: 123 additions & 0 deletions clang/test/ClangScanDeps/optimize-system-warnings.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// This test verifies that system module variants are mergable despite having
// different warning flags, as most warnings are disabled in system modules.
// This checks for system modules marked as such both via `-isystem` and
// `[system]`.

// RUN: rm -rf %t
// RUN: split-file %s %t
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands.json.in > %t/build/compile-commands.json
// RUN: clang-scan-deps -compilation-database %t/build/compile-commands.json \
// RUN: -j 1 -format experimental-full -optimize-args=system-warnings > %t/deps.db
// RUN: cat %t/deps.db | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t

// CHECK: {
// CHECK-NEXT: "modules": [
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file":
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-W
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file":
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-W
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "name": "B"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file":
// CHECK-NEXT: "command-line": [
// CHECK: "-Wmaybe-unused
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "name": "C"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK: ]
// CHECK: }

// A.m and B.m verify that system modules with different warning flags get
// merged. C.m verifies that -Wsystem-headers disables the optimization.
//--- build/compile-commands.json.in

[
{
"directory": "DIR",
"command": "clang -c DIR/A.m -isystem modules/A -I modules/B -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps",
"file": "DIR/A.m"
},
{
"directory": "DIR",
"command": "clang -c DIR/B.m -isystem modules/A -I modules/B -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Wmaybe-unused",
"file": "DIR/B.m"
},
{
"directory": "DIR",
"command": "clang -c DIR/C.m -isystem modules/C -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Wmaybe-unused -Wsystem-headers",
"file": "DIR/C.m"
}
]

//--- modules/A/module.modulemap

module A {
umbrella header "A.h"
}

//--- modules/A/A.h

typedef int A_t;

//--- modules/B/module.modulemap

module B [system] {
umbrella header "B.h"
}

//--- modules/B/B.h

typedef int B_t;

//--- modules/C/module.modulemap

module C [system] {
umbrella header "C.h"
}

//--- modules/C/C.h

typedef int C_t;

//--- A.m

#include <A.h>
#include <B.h>

A_t a = 0;

//--- B.m

#include <A.h>
#include <B.h>

A_t b = 0;

//--- C.m

#include <C.h>

C_t c = 0;
1 change: 1 addition & 0 deletions clang/tools/clang-scan-deps/ClangScanDeps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ static void ParseArgs(int argc, char **argv) {
llvm::StringSwitch<std::optional<ScanningOptimizations>>(Arg)
.Case("none", ScanningOptimizations::None)
.Case("header-search", ScanningOptimizations::HeaderSearch)
.Case("system-warnings", ScanningOptimizations::SystemWarnings)
.Case("all", ScanningOptimizations::All)
.Default(std::nullopt);
if (!Optimization) {
Expand Down