}
bool isBuiltinDiagnosticSuppressed(unsigned ID,
- const llvm::StringSet<> &Suppress) {
+ const llvm::StringSet<> &Suppress,
+ const LangOptions &LangOpts) {
+ // Don't complain about header-only stuff in mainfiles if it's a header.
+ // FIXME: would be cleaner to suppress in clang, once we decide whether the
+ // behavior should be to silently-ignore or respect the pragma.
+ if (ID == diag::pp_pragma_sysheader_in_main_file && LangOpts.IsHeaderFile)
+ return true;
+
if (const char *CodePtr = getDiagnosticCode(ID)) {
if (Suppress.contains(normalizeSuppressedCode(CodePtr)))
return true;
/// Determine whether a (non-clang-tidy) diagnostic is suppressed by config.
bool isBuiltinDiagnosticSuppressed(unsigned ID,
- const llvm::StringSet<> &Suppressed);
+ const llvm::StringSet<> &Suppressed,
+ const LangOptions &);
/// Take a user-specified diagnostic code, and convert it to a normalized form
/// stored in the config and consumed by isBuiltinDiagnosticsSuppressed.
///
ASTDiags.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &Info) {
if (Cfg.Diagnostics.SuppressAll ||
- isBuiltinDiagnosticSuppressed(Info.getID(), Cfg.Diagnostics.Suppress))
+ isBuiltinDiagnosticSuppressed(Info.getID(), Cfg.Diagnostics.Suppress,
+ Clang->getLangOpts()))
return DiagnosticsEngine::Ignored;
auto It = OverriddenSeverity.find(Info.getID());
PreambleDiagnostics.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel,
const clang::Diagnostic &Info) {
if (Cfg.Diagnostics.SuppressAll ||
- isBuiltinDiagnosticSuppressed(Info.getID(), Cfg.Diagnostics.Suppress))
+ isBuiltinDiagnosticSuppressed(Info.getID(), Cfg.Diagnostics.Suppress,
+ *CI.getLangOpts()))
return DiagnosticsEngine::Ignored;
switch (Info.getID()) {
case diag::warn_no_newline_eof:
"unreachable-code", "unused-variable",
"typecheck_bool_condition",
"unexpected_friend", "warn_alloca"));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(diag::warn_unreachable,
- Conf.Diagnostics.Suppress));
+ EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
+ diag::warn_unreachable, Conf.Diagnostics.Suppress, LangOptions()));
// Subcategory not respected/suppressed.
- EXPECT_FALSE(isBuiltinDiagnosticSuppressed(diag::warn_unreachable_break,
- Conf.Diagnostics.Suppress));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(diag::warn_unused_variable,
- Conf.Diagnostics.Suppress));
+ EXPECT_FALSE(isBuiltinDiagnosticSuppressed(
+ diag::warn_unreachable_break, Conf.Diagnostics.Suppress, LangOptions()));
+ EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
+ diag::warn_unused_variable, Conf.Diagnostics.Suppress, LangOptions()));
EXPECT_TRUE(isBuiltinDiagnosticSuppressed(diag::err_typecheck_bool_condition,
- Conf.Diagnostics.Suppress));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(diag::err_unexpected_friend,
- Conf.Diagnostics.Suppress));
- EXPECT_TRUE(isBuiltinDiagnosticSuppressed(diag::warn_alloca,
- Conf.Diagnostics.Suppress));
+ Conf.Diagnostics.Suppress,
+ LangOptions()));
+ EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
+ diag::err_unexpected_friend, Conf.Diagnostics.Suppress, LangOptions()));
+ EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
+ diag::warn_alloca, Conf.Diagnostics.Suppress, LangOptions()));
Frag.Diagnostics.Suppress.emplace_back("*");
EXPECT_TRUE(compileAndApply());
Not(WithFix(_)))));
}
+TEST(DiagnosticsTest, PragmaSystemHeader) {
+ Annotations Test("#pragma clang [[system_header]]\n");
+ auto TU = TestTU::withCode(Test.code());
+ EXPECT_THAT(
+ *TU.build().getDiagnostics(),
+ ElementsAre(AllOf(
+ Diag(Test.range(), "#pragma system_header ignored in main file"))));
+ TU.Filename = "TestTU.h";
+ EXPECT_THAT(*TU.build().getDiagnostics(), IsEmpty());
+}
+
TEST(ClangdTest, MSAsm) {
// Parsing MS assembly tries to use the target MCAsmInfo, which we don't link.
// We used to crash here. Now clang emits a diagnostic, which we filter out.