Skip to content

Commit 5845688

Browse files
committed
Reapply "[clang] Introduce diagnostics suppression mappings (#112517)"
This reverts commit 5f140ba.
1 parent 42da815 commit 5845688

28 files changed

+637
-34
lines changed

clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks(
8181
Diags.setSourceManager(&Sources);
8282
// FIXME: Investigate whatever is there better way to initialize DiagEngine
8383
// or whatever DiagEngine can be shared by multiple preprocessors
84-
ProcessWarningOptions(Diags, Compiler.getDiagnosticOpts());
84+
ProcessWarningOptions(Diags, Compiler.getDiagnosticOpts(),
85+
Compiler.getVirtualFileSystem());
8586

8687
LangOpts.Modules = false;
8788

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,9 @@ New features
872872
attribute, the compiler can generate warnings about the use of any language features, or calls to
873873
other functions, which may block.
874874

875+
- Introduced ``-warning-suppression-mappings`` flag to control diagnostic
876+
suppressions per file. See `documentation <https://clang.llvm.org/docs/WarningSuppressionMappings.html>_` for details.
877+
875878
Crash and bug fixes
876879
^^^^^^^^^^^^^^^^^^^
877880

clang/docs/UsersManual.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ Options to Control Error and Warning Messages
151151
instantiation backtrace for a single warning or error. The default is 10, and
152152
the limit can be disabled with `-ftemplate-backtrace-limit=0`.
153153

154+
.. option:: --warning-suppression-mappings=foo.txt
155+
156+
:ref:`Suppress certain diagnostics for certain files. <warning_suppression_mappings>`
157+
154158
.. _cl_diag_formatting:
155159

156160
Formatting of Diagnostics
@@ -1315,6 +1319,34 @@ with its corresponding `Wno-` option.
13151319
Note that when combined with :option:`-w` (which disables all warnings),
13161320
disabling all warnings wins.
13171321

1322+
.. _warning_suppression_mappings:
1323+
1324+
Controlling Diagnostics via Suppression Mappings
1325+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1326+
1327+
Warning suppression mappings enable users to suppress Clang's diagnostics at a
1328+
per-file granularity. This allows enforcing diagnostics in specific parts of the
1329+
project even if there are violations in some headers.
1330+
1331+
.. code-block:: console
1332+
1333+
$ cat mappings.txt
1334+
[unused]
1335+
src:foo/*
1336+
1337+
$ clang --warning-suppression-mappings=mapping.txt -Wunused foo/bar.cc
1338+
# This compilation won't emit any unused findings for sources under foo/
1339+
# directory. But it'll still complain for all the other sources, e.g:
1340+
$ cat foo/bar.cc
1341+
#include "dir/include.h" // Clang flags unused declarations here.
1342+
#include "foo/include.h" // but unused warnings under this source is omitted.
1343+
#include "next_to_bar_cc.h" // as are unused warnings from this header file.
1344+
// Further, unused warnings in the remainder of bar.cc are also omitted.
1345+
1346+
1347+
See :doc:`WarningSuppressionMappings` for details about the file format and
1348+
functionality.
1349+
13181350
Controlling Static Analyzer Diagnostics
13191351
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13201352

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
============================
2+
Warning suppression mappings
3+
============================
4+
5+
.. contents::
6+
:local:
7+
8+
Introduction
9+
============
10+
11+
Warning suppression mappings enable users to suppress Clang's diagnostics at a
12+
per-file granularity. This allows enforcing diagnostics in specific parts of the
13+
project even if there are violations in some headers.
14+
15+
Goal and usage
16+
==============
17+
18+
Clang allows diagnostics to be configured at a translation-unit granularity.
19+
If a ``foo.cpp`` is compiled with ``-Wfoo``, all transitively included headers
20+
also need to be clean. Hence, turning on new warnings in large codebases
21+
requires cleaning up all the existing warnings. This might not be possible when
22+
some dependencies aren't in the project owner's control or because new
23+
violations are creeping up quicker than the clean up.
24+
25+
Warning suppression mappings aim to alleviate some of these concerns by making
26+
diagnostic configuration granularity finer, at a source file level.
27+
28+
To achieve this, user can create a file that lists which :doc:`diagnostic
29+
groups <DiagnosticsReference>` to suppress in which files or paths, and pass it
30+
as a command line argument to Clang with the ``--warning-suppression-mappings``
31+
flag.
32+
33+
Note that this mechanism won't enable any diagnostics on its own. Users should
34+
still turn on warnings in their compilations with explicit ``-Wfoo`` flags.
35+
`Controlling diagnostics pragmas
36+
<https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas>`_
37+
take precedence over suppression mappings. Ensuring code author's explicit
38+
intent is always preserved.
39+
40+
Example
41+
=======
42+
43+
.. code-block:: bash
44+
45+
$ cat my/user/code.cpp
46+
#include <foo/bar.h>
47+
namespace { void unused_func1(); }
48+
49+
$ cat foo/bar.h
50+
namespace { void unused_func2(); }
51+
52+
$ cat suppression_mappings.txt
53+
# Suppress -Wunused warnings in all files, apart from the ones under `foo/`.
54+
[unused]
55+
src:*
56+
src:*foo/*=emit
57+
$ clang -Wunused --warning-suppression-mappings=suppression_mappings.txt my/user/code.cpp
58+
# prints warning: unused function 'unused_func2', but no warnings for `unused_func1`.
59+
60+
Format
61+
======
62+
63+
Warning suppression mappings uses the same format as
64+
:doc:`SanitizerSpecialCaseList`.
65+
66+
Sections describe which diagnostic group's behaviour to change, e.g.
67+
``[unused]``. When a diagnostic is matched by multiple sections, the latest
68+
section takes precedence.
69+
70+
Afterwards in each section, users can have multiple entities that match source
71+
files based on the globs. These entities look like ``src:*/my/dir/*``.
72+
Users can also use the ``emit`` category to exclude a subdirectory from
73+
suppression.
74+
Source files are matched against these globs either:
75+
76+
- as paths relative to the current working directory
77+
- as absolute paths.
78+
79+
When a source file matches multiple globs in a section, the longest one takes
80+
precedence.
81+
82+
.. code-block:: bash
83+
84+
# Lines starting with # are ignored.
85+
# Configure suppression globs for `-Wunused` warnings
86+
[unused]
87+
# Suppress on all files by default.
88+
src:*
89+
# But enforce for all the sources under foo/.
90+
src:*foo/*=emit
91+
92+
# unused-function warnings are a subgroup of `-Wunused`. So this section
93+
# takes precedence over the previous one for unused-function warnings, but
94+
# not for unused-variable warnings.
95+
[unused-function]
96+
# Only suppress for sources under bar/.
97+
src:*bar/*

clang/docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Using Clang as a Compiler
2222
ClangCommandLineReference
2323
AttributeReference
2424
DiagnosticsReference
25+
WarningSuppressionMappings
2526
CrossCompilation
2627
ClangStaticAnalyzer
2728
ThreadSafetyAnalysis

clang/include/clang/Basic/Diagnostic.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
#include "clang/Basic/Specifiers.h"
2121
#include "llvm/ADT/ArrayRef.h"
2222
#include "llvm/ADT/DenseMap.h"
23+
#include "llvm/ADT/FunctionExtras.h"
2324
#include "llvm/ADT/IntrusiveRefCntPtr.h"
2425
#include "llvm/ADT/SmallVector.h"
25-
#include "llvm/ADT/StringRef.h"
2626
#include "llvm/ADT/iterator_range.h"
2727
#include "llvm/Support/Compiler.h"
2828
#include <cassert>
@@ -40,6 +40,10 @@
4040
namespace llvm {
4141
class Error;
4242
class raw_ostream;
43+
class MemoryBuffer;
44+
namespace vfs {
45+
class FileSystem;
46+
} // namespace vfs
4347
} // namespace llvm
4448

4549
namespace clang {
@@ -555,6 +559,10 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
555559
void *ArgToStringCookie = nullptr;
556560
ArgToStringFnTy ArgToStringFn;
557561

562+
/// Whether the diagnostic should be suppressed in FilePath.
563+
llvm::unique_function<bool(diag::kind, StringRef /*FilePath*/) const>
564+
DiagSuppressionMapping;
565+
558566
public:
559567
explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags,
560568
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
@@ -946,6 +954,26 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
946954
return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
947955
}
948956

957+
/// Diagnostic suppression mappings can be used to suppress specific
958+
/// diagnostics in specific files.
959+
/// Mapping file is expected to be a special case list with sections denoting
960+
/// diagnostic groups and `src` entries for globs to suppress. `emit` category
961+
/// can be used to disable suppression. Longest glob that matches a filepath
962+
/// takes precedence. For example:
963+
/// [unused]
964+
/// src:clang/*
965+
/// src:clang/foo/*=emit
966+
/// src:clang/foo/bar/*
967+
///
968+
/// Such a mappings file suppress all diagnostics produced by -Wunused in all
969+
/// sources under `clang/` directory apart from `clang/foo/`. Diagnostics
970+
/// under `clang/foo/bar/` will also be suppressed. Note that the FilePath is
971+
/// matched against the globs as-is.
972+
/// These take presumed locations into account, and can still be overriden by
973+
/// clang-diagnostics pragmas.
974+
void setDiagSuppressionMapping(llvm::MemoryBuffer &Input);
975+
bool isSuppressedViaMapping(diag::kind DiagId, StringRef FilePath) const;
976+
949977
/// Issue the message to the client.
950978
///
951979
/// This actually returns an instance of DiagnosticBuilder which emits the
@@ -1759,7 +1787,7 @@ const char ToggleHighlight = 127;
17591787
/// warning options specified on the command line.
17601788
void ProcessWarningOptions(DiagnosticsEngine &Diags,
17611789
const DiagnosticOptions &Opts,
1762-
bool ReportDiags = true);
1790+
llvm::vfs::FileSystem &VFS, bool ReportDiags = true);
17631791
void EscapeStringForDiagnostic(StringRef Str, SmallVectorImpl<char> &OutStr);
17641792
} // namespace clang
17651793

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,4 +834,7 @@ def err_drv_triple_version_invalid : Error<
834834

835835
def warn_missing_include_dirs : Warning<
836836
"no such include directory: '%0'">, InGroup<MissingIncludeDirs>, DefaultIgnore;
837+
838+
def err_drv_malformed_warning_suppression_mapping : Error<
839+
"failed to process suppression mapping file '%0': %1">;
837840
}

clang/include/clang/Basic/DiagnosticOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
108108
/// The file to serialize diagnostics to (non-appending).
109109
std::string DiagnosticSerializationFile;
110110

111+
/// Path for the file that defines diagnostic suppression mappings.
112+
std::string DiagnosticSuppressionMappingsFile;
113+
111114
/// The list of -W... options used to alter the diagnostic mappings, with the
112115
/// prefixes removed.
113116
std::vector<std::string> Warnings;

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,10 @@ def V : JoinedOrSeparate<["-"], "V">, Flags<[NoXarchOption, Unsupported]>;
965965
def Wa_COMMA : CommaJoined<["-"], "Wa,">,
966966
HelpText<"Pass the comma separated arguments in <arg> to the assembler">,
967967
MetaVarName<"<arg>">;
968+
def warning_suppression_mappings_EQ : Joined<["--"],
969+
"warning-suppression-mappings=">, Group<Diag_Group>,
970+
HelpText<"File containing diagnostic suppresion mappings. See user manual "
971+
"for file format.">, Visibility<[ClangOption, CC1Option]>;
968972
def Wall : Flag<["-"], "Wall">, Group<W_Group>, Flags<[HelpHidden]>,
969973
Visibility<[ClangOption, CC1Option, FlangOption]>;
970974
def WCL4 : Flag<["-"], "WCL4">, Group<W_Group>, Flags<[HelpHidden]>,

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/ADT/StringRef.h"
2525
#include "llvm/Support/BuryPointer.h"
2626
#include "llvm/Support/FileSystem.h"
27+
#include "llvm/Support/VirtualFileSystem.h"
2728
#include <cassert>
2829
#include <list>
2930
#include <memory>
@@ -701,11 +702,10 @@ class CompilerInstance : public ModuleLoader {
701702
/// used by some diagnostics printers (for logging purposes only).
702703
///
703704
/// \return The new object on success, or null on failure.
704-
static IntrusiveRefCntPtr<DiagnosticsEngine>
705-
createDiagnostics(DiagnosticOptions *Opts,
706-
DiagnosticConsumer *Client = nullptr,
707-
bool ShouldOwnClient = true,
708-
const CodeGenOptions *CodeGenOpts = nullptr);
705+
static IntrusiveRefCntPtr<DiagnosticsEngine> createDiagnostics(
706+
DiagnosticOptions *Opts, DiagnosticConsumer *Client = nullptr,
707+
bool ShouldOwnClient = true, const CodeGenOptions *CodeGenOpts = nullptr,
708+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
709709

710710
/// Create the file manager and replace any existing one with it.
711711
///

0 commit comments

Comments
 (0)