Add option to exclude headers from clang-tidy analysis (#91400)

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
This commit is contained in:
Justin Cady 2024-05-14 08:48:04 -04:00 committed by GitHub
parent 415616daa0
commit cc54129b98
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 207 additions and 126 deletions

View File

@ -311,7 +311,18 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
: Context(Ctx), ExternalDiagEngine(ExternalDiagEngine), : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
RemoveIncompatibleErrors(RemoveIncompatibleErrors), RemoveIncompatibleErrors(RemoveIncompatibleErrors),
GetFixesFromNotes(GetFixesFromNotes), GetFixesFromNotes(GetFixesFromNotes),
EnableNolintBlocks(EnableNolintBlocks) {} EnableNolintBlocks(EnableNolintBlocks) {
if (Context.getOptions().HeaderFilterRegex &&
!Context.getOptions().HeaderFilterRegex->empty())
HeaderFilter =
std::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
if (Context.getOptions().ExcludeHeaderFilterRegex &&
!Context.getOptions().ExcludeHeaderFilterRegex->empty())
ExcludeHeaderFilter = std::make_unique<llvm::Regex>(
*Context.getOptions().ExcludeHeaderFilterRegex);
}
void ClangTidyDiagnosticConsumer::finalizeLastError() { void ClangTidyDiagnosticConsumer::finalizeLastError() {
if (!Errors.empty()) { if (!Errors.empty()) {
@ -562,22 +573,17 @@ void ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
} }
StringRef FileName(File->getName()); StringRef FileName(File->getName());
LastErrorRelatesToUserCode = LastErrorRelatesToUserCode || LastErrorRelatesToUserCode =
Sources.isInMainFile(Location) || LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
getHeaderFilter()->match(FileName); (HeaderFilter &&
(HeaderFilter->match(FileName) &&
!(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName))));
unsigned LineNumber = Sources.getExpansionLineNumber(Location); unsigned LineNumber = Sources.getExpansionLineNumber(Location);
LastErrorPassesLineFilter = LastErrorPassesLineFilter =
LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber); LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
} }
llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
if (!HeaderFilter)
HeaderFilter =
std::make_unique<llvm::Regex>(*Context.getOptions().HeaderFilterRegex);
return HeaderFilter.get();
}
void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() { void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
// Each error is modelled as the set of intervals in which it applies // Each error is modelled as the set of intervals in which it applies
// replacements. To detect overlapping replacements, we use a sweep line // replacements. To detect overlapping replacements, we use a sweep line

View File

@ -313,6 +313,7 @@ private:
bool EnableNolintBlocks; bool EnableNolintBlocks;
std::vector<ClangTidyError> Errors; std::vector<ClangTidyError> Errors;
std::unique_ptr<llvm::Regex> HeaderFilter; std::unique_ptr<llvm::Regex> HeaderFilter;
std::unique_ptr<llvm::Regex> ExcludeHeaderFilter;
bool LastErrorRelatesToUserCode = false; bool LastErrorRelatesToUserCode = false;
bool LastErrorPassesLineFilter = false; bool LastErrorPassesLineFilter = false;
bool LastErrorWasIgnored = false; bool LastErrorWasIgnored = false;

View File

@ -170,6 +170,8 @@ template <> struct MappingTraits<ClangTidyOptions> {
IO.mapOptional("ImplementationFileExtensions", IO.mapOptional("ImplementationFileExtensions",
Options.ImplementationFileExtensions); Options.ImplementationFileExtensions);
IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex); IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
IO.mapOptional("ExcludeHeaderFilterRegex",
Options.ExcludeHeaderFilterRegex);
IO.mapOptional("FormatStyle", Options.FormatStyle); IO.mapOptional("FormatStyle", Options.FormatStyle);
IO.mapOptional("User", Options.User); IO.mapOptional("User", Options.User);
IO.mapOptional("CheckOptions", Options.CheckOptions); IO.mapOptional("CheckOptions", Options.CheckOptions);
@ -191,7 +193,8 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
Options.WarningsAsErrors = ""; Options.WarningsAsErrors = "";
Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"}; Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"}; Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
Options.HeaderFilterRegex = ""; Options.HeaderFilterRegex = std::nullopt;
Options.ExcludeHeaderFilterRegex = std::nullopt;
Options.SystemHeaders = false; Options.SystemHeaders = false;
Options.FormatStyle = "none"; Options.FormatStyle = "none";
Options.User = std::nullopt; Options.User = std::nullopt;
@ -231,6 +234,7 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other,
overrideValue(ImplementationFileExtensions, overrideValue(ImplementationFileExtensions,
Other.ImplementationFileExtensions); Other.ImplementationFileExtensions);
overrideValue(HeaderFilterRegex, Other.HeaderFilterRegex); overrideValue(HeaderFilterRegex, Other.HeaderFilterRegex);
overrideValue(ExcludeHeaderFilterRegex, Other.ExcludeHeaderFilterRegex);
overrideValue(SystemHeaders, Other.SystemHeaders); overrideValue(SystemHeaders, Other.SystemHeaders);
overrideValue(FormatStyle, Other.FormatStyle); overrideValue(FormatStyle, Other.FormatStyle);
overrideValue(User, Other.User); overrideValue(User, Other.User);

View File

@ -83,6 +83,10 @@ struct ClangTidyOptions {
/// main files will always be displayed. /// main files will always be displayed.
std::optional<std::string> HeaderFilterRegex; std::optional<std::string> HeaderFilterRegex;
/// \brief Exclude warnings from headers matching this filter, even if they
/// match \c HeaderFilterRegex.
std::optional<std::string> ExcludeHeaderFilterRegex;
/// Output warnings from system headers matching \c HeaderFilterRegex. /// Output warnings from system headers matching \c HeaderFilterRegex.
std::optional<bool> SystemHeaders; std::optional<bool> SystemHeaders;

View File

@ -53,6 +53,7 @@ Configuration files:
Checks - Same as '--checks'. Additionally, the list of Checks - Same as '--checks'. Additionally, the list of
globs can be specified as a list instead of a globs can be specified as a list instead of a
string. string.
ExcludeHeaderFilterRegex - Same as '--exclude-header-filter'.
ExtraArgs - Same as '--extra-args'. ExtraArgs - Same as '--extra-args'.
ExtraArgsBefore - Same as '--extra-args-before'. ExtraArgsBefore - Same as '--extra-args-before'.
FormatStyle - Same as '--format-style'. FormatStyle - Same as '--format-style'.
@ -132,6 +133,20 @@ option in .clang-tidy file, if any.
cl::init(""), cl::init(""),
cl::cat(ClangTidyCategory)); cl::cat(ClangTidyCategory));
static cl::opt<std::string> ExcludeHeaderFilter("exclude-header-filter",
desc(R"(
Regular expression matching the names of the
headers to exclude diagnostics from. Diagnostics
from the main file of each translation unit are
always displayed.
Must be used together with --header-filter.
Can be used together with -line-filter.
This option overrides the 'ExcludeHeaderFilterRegex'
option in .clang-tidy file, if any.
)"),
cl::init(""),
cl::cat(ClangTidyCategory));
static cl::opt<bool> SystemHeaders("system-headers", desc(R"( static cl::opt<bool> SystemHeaders("system-headers", desc(R"(
Display the errors from system headers. Display the errors from system headers.
This option overrides the 'SystemHeaders' option This option overrides the 'SystemHeaders' option
@ -353,6 +368,7 @@ static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
DefaultOptions.Checks = DefaultChecks; DefaultOptions.Checks = DefaultChecks;
DefaultOptions.WarningsAsErrors = ""; DefaultOptions.WarningsAsErrors = "";
DefaultOptions.HeaderFilterRegex = HeaderFilter; DefaultOptions.HeaderFilterRegex = HeaderFilter;
DefaultOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
DefaultOptions.SystemHeaders = SystemHeaders; DefaultOptions.SystemHeaders = SystemHeaders;
DefaultOptions.FormatStyle = FormatStyle; DefaultOptions.FormatStyle = FormatStyle;
DefaultOptions.User = llvm::sys::Process::GetEnv("USER"); DefaultOptions.User = llvm::sys::Process::GetEnv("USER");
@ -367,6 +383,8 @@ static std::unique_ptr<ClangTidyOptionsProvider> createOptionsProvider(
OverrideOptions.WarningsAsErrors = WarningsAsErrors; OverrideOptions.WarningsAsErrors = WarningsAsErrors;
if (HeaderFilter.getNumOccurrences() > 0) if (HeaderFilter.getNumOccurrences() > 0)
OverrideOptions.HeaderFilterRegex = HeaderFilter; OverrideOptions.HeaderFilterRegex = HeaderFilter;
if (ExcludeHeaderFilter.getNumOccurrences() > 0)
OverrideOptions.ExcludeHeaderFilterRegex = ExcludeHeaderFilter;
if (SystemHeaders.getNumOccurrences() > 0) if (SystemHeaders.getNumOccurrences() > 0)
OverrideOptions.SystemHeaders = SystemHeaders; OverrideOptions.SystemHeaders = SystemHeaders;
if (FormatStyle.getNumOccurrences() > 0) if (FormatStyle.getNumOccurrences() > 0)

View File

@ -106,11 +106,14 @@ def get_tidy_invocation(
use_color, use_color,
plugins, plugins,
warnings_as_errors, warnings_as_errors,
exclude_header_filter,
): ):
"""Gets a command line for clang-tidy.""" """Gets a command line for clang-tidy."""
start = [clang_tidy_binary] start = [clang_tidy_binary]
if allow_enabling_alpha_checkers: if allow_enabling_alpha_checkers:
start.append("-allow-enabling-analyzer-alpha-checkers") start.append("-allow-enabling-analyzer-alpha-checkers")
if exclude_header_filter is not None:
start.append("--exclude-header-filter=" + exclude_header_filter)
if header_filter is not None: if header_filter is not None:
start.append("-header-filter=" + header_filter) start.append("-header-filter=" + header_filter)
if line_filter is not None: if line_filter is not None:
@ -228,6 +231,7 @@ def run_tidy(args, clang_tidy_binary, tmpdir, build_path, queue, lock, failed_fi
args.use_color, args.use_color,
args.plugins, args.plugins,
args.warnings_as_errors, args.warnings_as_errors,
args.exclude_header_filter,
) )
proc = subprocess.Popen( proc = subprocess.Popen(
@ -292,6 +296,14 @@ def main():
"-config option after reading specified config file. " "-config option after reading specified config file. "
"Use either -config-file or -config, not both.", "Use either -config-file or -config, not both.",
) )
parser.add_argument(
"-exclude-header-filter",
default=None,
help="Regular expression matching the names of the "
"headers to exclude diagnostics from. Diagnostics from "
"the main file of each translation unit are always "
"displayed.",
)
parser.add_argument( parser.add_argument(
"-header-filter", "-header-filter",
default=None, default=None,
@ -450,6 +462,7 @@ def main():
args.use_color, args.use_color,
args.plugins, args.plugins,
args.warnings_as_errors, args.warnings_as_errors,
args.exclude_header_filter,
) )
invocation.append("-list-checks") invocation.append("-list-checks")
invocation.append("-") invocation.append("-")

View File

@ -115,6 +115,9 @@ Improvements to clang-tidy
- Fixed `--verify-config` option not properly parsing checks when using the - Fixed `--verify-config` option not properly parsing checks when using the
literal operator in the `.clang-tidy` config. literal operator in the `.clang-tidy` config.
- Added argument `--exclude-header-filter` and config option `ExcludeHeaderFilterRegex`
to exclude headers from analysis via a RegEx.
New checks New checks
^^^^^^^^^^ ^^^^^^^^^^

View File

@ -157,6 +157,14 @@ An overview of all the command-line options:
to detect macro definitions within modules. This to detect macro definitions within modules. This
feature may cause performance and parsing issues feature may cause performance and parsing issues
and is therefore considered experimental. and is therefore considered experimental.
--exclude-header-filter=<string> - Regular expression matching the names of the
headers to exclude diagnostics from. Diagnostics
from the main file of each translation unit are
always displayed.
Must be used together with --header-filter.
Can be used together with -line-filter.
This option overrides the 'ExcludeHeaderFilterRegex'
option in .clang-tidy file, if any.
--explain-config - For each enabled check explains, where it is --explain-config - For each enabled check explains, where it is
enabled, i.e. in clang-tidy binary, command enabled, i.e. in clang-tidy binary, command
line or a specific configuration file. line or a specific configuration file.
@ -269,6 +277,7 @@ An overview of all the command-line options:
Checks - Same as '--checks'. Additionally, the list of Checks - Same as '--checks'. Additionally, the list of
globs can be specified as a list instead of a globs can be specified as a list instead of a
string. string.
ExcludeHeaderFilterRegex - Same as '--exclude-header-filter'.
ExtraArgs - Same as '--extra-args'. ExtraArgs - Same as '--extra-args'.
ExtraArgsBefore - Same as '--extra-args-before'. ExtraArgsBefore - Same as '--extra-args-before'.
FormatStyle - Same as '--format-style'. FormatStyle - Same as '--format-style'.

View File

@ -1,2 +1,3 @@
Checks: 'from-parent' Checks: 'from-parent'
HeaderFilterRegex: 'parent' HeaderFilterRegex: 'parent'
ExcludeHeaderFilterRegex: 'exc-parent'

View File

@ -1,2 +1,3 @@
Checks: 'from-child1' Checks: 'from-child1'
HeaderFilterRegex: 'child1' HeaderFilterRegex: 'child1'
ExcludeHeaderFilterRegex: 'exc-child1'

View File

@ -1,3 +1,4 @@
InheritParentConfig: true InheritParentConfig: true
Checks: 'from-child3' Checks: 'from-child3'
HeaderFilterRegex: 'child3' HeaderFilterRegex: 'child3'
ExcludeHeaderFilterRegex: 'exc-child3'

View File

@ -1,18 +1,23 @@
// RUN: clang-tidy -dump-config %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-BASE // RUN: clang-tidy -dump-config %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-BASE
// CHECK-BASE: Checks: {{.*}}from-parent // CHECK-BASE: Checks: {{.*}}from-parent
// CHECK-BASE: HeaderFilterRegex: parent // CHECK-BASE: HeaderFilterRegex: parent
// CHECK-BASE: ExcludeHeaderFilterRegex: exc-parent
// RUN: clang-tidy -dump-config %S/Inputs/config-files/1/- -- | FileCheck %s -check-prefix=CHECK-CHILD1 // RUN: clang-tidy -dump-config %S/Inputs/config-files/1/- -- | FileCheck %s -check-prefix=CHECK-CHILD1
// CHECK-CHILD1: Checks: {{.*}}from-child1 // CHECK-CHILD1: Checks: {{.*}}from-child1
// CHECK-CHILD1: HeaderFilterRegex: child1 // CHECK-CHILD1: HeaderFilterRegex: child1
// CHECK-CHILD1: ExcludeHeaderFilterRegex: exc-child1
// RUN: clang-tidy -dump-config %S/Inputs/config-files/2/- -- | FileCheck %s -check-prefix=CHECK-CHILD2 // RUN: clang-tidy -dump-config %S/Inputs/config-files/2/- -- | FileCheck %s -check-prefix=CHECK-CHILD2
// CHECK-CHILD2: Checks: {{.*}}from-parent // CHECK-CHILD2: Checks: {{.*}}from-parent
// CHECK-CHILD2: HeaderFilterRegex: parent // CHECK-CHILD2: HeaderFilterRegex: parent
// CHECK-CHILD2: ExcludeHeaderFilterRegex: exc-parent
// RUN: clang-tidy -dump-config %S/Inputs/config-files/3/- -- | FileCheck %s -check-prefix=CHECK-CHILD3 // RUN: clang-tidy -dump-config %S/Inputs/config-files/3/- -- | FileCheck %s -check-prefix=CHECK-CHILD3
// CHECK-CHILD3: Checks: {{.*}}from-parent,from-child3 // CHECK-CHILD3: Checks: {{.*}}from-parent,from-child3
// CHECK-CHILD3: HeaderFilterRegex: child3 // CHECK-CHILD3: HeaderFilterRegex: child3
// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-COMMAND-LINE // CHECK-CHILD3: ExcludeHeaderFilterRegex: exc-child3
// RUN: clang-tidy -dump-config -checks='from-command-line' -header-filter='from command line' -exclude-header-filter='from_command_line' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-COMMAND-LINE
// CHECK-COMMAND-LINE: Checks: {{.*}}from-parent,from-command-line // CHECK-COMMAND-LINE: Checks: {{.*}}from-parent,from-command-line
// CHECK-COMMAND-LINE: HeaderFilterRegex: from command line // CHECK-COMMAND-LINE: HeaderFilterRegex: from command line
// CHECK-COMMAND-LINE: ExcludeHeaderFilterRegex: from_command_line
// For this test we have to use names of the real checks because otherwise values are ignored. // For this test we have to use names of the real checks because otherwise values are ignored.
// Running with the old key: <Key>, value: <value> CheckOptions // Running with the old key: <Key>, value: <value> CheckOptions
@ -68,3 +73,11 @@
// Dumped config does not overflow for unsigned options // Dumped config does not overflow for unsigned options
// RUN: clang-tidy --dump-config %S/Inputs/config-files/5/- -- | FileCheck %s -check-prefix=CHECK-OVERFLOW // RUN: clang-tidy --dump-config %S/Inputs/config-files/5/- -- | FileCheck %s -check-prefix=CHECK-OVERFLOW
// CHECK-OVERFLOW: misc-throw-by-value-catch-by-reference.MaxSize: '1152921504606846976' // CHECK-OVERFLOW: misc-throw-by-value-catch-by-reference.MaxSize: '1152921504606846976'
// RUN: clang-tidy -dump-config -checks='readability-function-size' -header-filter='foo/*' -exclude-header-filter='bar*' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=CHECK-EXCLUDE-HEADERS
// CHECK-EXCLUDE-HEADERS: HeaderFilterRegex: 'foo/*'
// CHECK-EXCLUDE-HEADERS: ExcludeHeaderFilterRegex: 'bar*'
// RUN: clang-tidy -dump-config -checks='readability-function-size' -header-filter='' -exclude-header-filter='' %S/Inputs/config-files/- -- | FileCheck %s -check-prefix=EMPTY-CHECK-EXCLUDE-HEADERS
// EMPTY-CHECK-EXCLUDE-HEADERS: HeaderFilterRegex: ''
// EMPTY-CHECK-EXCLUDE-HEADERS: ExcludeHeaderFilterRegex: ''

View File

@ -11,6 +11,7 @@
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers -quiet %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4-QUIET %s // RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -system-headers -quiet %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK4-QUIET %s
// RUN: clang-tidy -checks='-*,cppcoreguidelines-pro-type-cstyle-cast' -header-filter='.*' -system-headers %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK5 %s // RUN: clang-tidy -checks='-*,cppcoreguidelines-pro-type-cstyle-cast' -header-filter='.*' -system-headers %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK5 %s
// RUN: clang-tidy -checks='-*,cppcoreguidelines-pro-type-cstyle-cast' -header-filter='.*' %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK5-NO-SYSTEM-HEADERS %s // RUN: clang-tidy -checks='-*,cppcoreguidelines-pro-type-cstyle-cast' -header-filter='.*' %s -- -I %S/Inputs/file-filter/system/.. -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK5-NO-SYSTEM-HEADERS %s
// RUN: clang-tidy -checks='-*,google-explicit-constructor' -header-filter='.*' -exclude-header-filter='header1\.h' %s -- -I %S/Inputs/file-filter/ -isystem %S/Inputs/file-filter/system 2>&1 | FileCheck --check-prefix=CHECK6 %s
#include "header1.h" #include "header1.h"
// CHECK-NOT: warning: // CHECK-NOT: warning:
@ -21,6 +22,7 @@
// CHECK3-QUIET-NOT: warning: // CHECK3-QUIET-NOT: warning:
// CHECK4: header1.h:1:12: warning: single-argument constructors // CHECK4: header1.h:1:12: warning: single-argument constructors
// CHECK4-QUIET: header1.h:1:12: warning: single-argument constructors // CHECK4-QUIET: header1.h:1:12: warning: single-argument constructors
// CHECK6-NOT: warning:
#include "header2.h" #include "header2.h"
// CHECK-NOT: warning: // CHECK-NOT: warning:
@ -31,6 +33,7 @@
// CHECK3-QUIET: header2.h:1:12: warning: single-argument constructors // CHECK3-QUIET: header2.h:1:12: warning: single-argument constructors
// CHECK4: header2.h:1:12: warning: single-argument constructors // CHECK4: header2.h:1:12: warning: single-argument constructors
// CHECK4-QUIET: header2.h:1:12: warning: single-argument constructors // CHECK4-QUIET: header2.h:1:12: warning: single-argument constructors
// CHECK6: header2.h:1:12: warning: single-argument constructors
#include <system-header.h> #include <system-header.h>
// CHECK-NOT: warning: // CHECK-NOT: warning:
@ -41,6 +44,7 @@
// CHECK3-QUIET-NOT: warning: // CHECK3-QUIET-NOT: warning:
// CHECK4: system-header.h:1:12: warning: single-argument constructors // CHECK4: system-header.h:1:12: warning: single-argument constructors
// CHECK4-QUIET: system-header.h:1:12: warning: single-argument constructors // CHECK4-QUIET: system-header.h:1:12: warning: single-argument constructors
// CHECK6-NOT: warning:
class A { A(int); }; class A { A(int); };
// CHECK: :[[@LINE-1]]:11: warning: single-argument constructors // CHECK: :[[@LINE-1]]:11: warning: single-argument constructors
@ -51,6 +55,7 @@ class A { A(int); };
// CHECK3-QUIET: :[[@LINE-6]]:11: warning: single-argument constructors // CHECK3-QUIET: :[[@LINE-6]]:11: warning: single-argument constructors
// CHECK4: :[[@LINE-7]]:11: warning: single-argument constructors // CHECK4: :[[@LINE-7]]:11: warning: single-argument constructors
// CHECK4-QUIET: :[[@LINE-8]]:11: warning: single-argument constructors // CHECK4-QUIET: :[[@LINE-8]]:11: warning: single-argument constructors
// CHECK6: :[[@LINE-9]]:11: warning: single-argument constructors
// CHECK-NOT: warning: // CHECK-NOT: warning:
// CHECK-QUIET-NOT: warning: // CHECK-QUIET-NOT: warning:
@ -73,6 +78,8 @@ class A { A(int); };
// CHECK4-NOT: Suppressed {{.*}} warnings // CHECK4-NOT: Suppressed {{.*}} warnings
// CHECK4-NOT: Use -header-filter=.* {{.*}} // CHECK4-NOT: Use -header-filter=.* {{.*}}
// CHECK4-QUIET-NOT: Suppressed // CHECK4-QUIET-NOT: Suppressed
// CHECK6: Suppressed 2 warnings (2 in non-user code)
// CHECK6: Use -header-filter=.* {{.*}}
int x = 123; int x = 123;
auto x_ptr = TO_FLOAT_PTR(&x); auto x_ptr = TO_FLOAT_PTR(&x);