aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests
diff options
context:
space:
mode:
authorKadir Cetinkaya <kadircet@google.com>2024-11-13 09:34:23 +0100
committerKadir Cetinkaya <kadircet@google.com>2024-11-13 10:35:22 +0100
commit5845688e91d85d46c0f47daaf4edfdfc772853cf (patch)
tree2041b20e105163e2a1297fe34c69b31e3a560960 /clang/unittests
parent42da81582ea5a0e5bb0e18af74e6c101f0307f36 (diff)
downloadllvm-5845688e91d85d46c0f47daaf4edfdfc772853cf.zip
llvm-5845688e91d85d46c0f47daaf4edfdfc772853cf.tar.gz
llvm-5845688e91d85d46c0f47daaf4edfdfc772853cf.tar.bz2
Reapply "[clang] Introduce diagnostics suppression mappings (#112517)"
This reverts commit 5f140ba54794fe6ca379362b133eb27780e363d7.
Diffstat (limited to 'clang/unittests')
-rw-r--r--clang/unittests/Basic/DiagnosticTest.cpp169
-rw-r--r--clang/unittests/Frontend/CompilerInvocationTest.cpp11
2 files changed, 180 insertions, 0 deletions
diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp
index d8d23e3..36a77c7 100644
--- a/clang/unittests/Basic/DiagnosticTest.cpp
+++ b/clang/unittests/Basic/DiagnosticTest.cpp
@@ -10,8 +10,18 @@
#include "clang/Basic/DiagnosticError.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticLex.h"
+#include "clang/Basic/DiagnosticSema.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <optional>
+#include <vector>
using namespace llvm;
using namespace clang;
@@ -28,6 +38,9 @@ void clang::DiagnosticsTestHelper(DiagnosticsEngine &diag) {
}
namespace {
+using testing::AllOf;
+using testing::ElementsAre;
+using testing::IsEmpty;
// Check that DiagnosticErrorTrap works with SuppressAllDiagnostics.
TEST(DiagnosticTest, suppressAndTrap) {
@@ -167,4 +180,160 @@ TEST(DiagnosticTest, storedDiagEmptyWarning) {
// Make sure an empty warning can round-trip with \c StoredDiagnostic.
Diags.Report(CaptureConsumer.StoredDiags.front());
}
+
+class SuppressionMappingTest : public testing::Test {
+public:
+ SuppressionMappingTest() {
+ Diags.setClient(&CaptureConsumer, /*ShouldOwnClient=*/false);
+ }
+
+protected:
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
+ DiagnosticsEngine Diags{new DiagnosticIDs(), new DiagnosticOptions};
+
+ llvm::ArrayRef<StoredDiagnostic> diags() {
+ return CaptureConsumer.StoredDiags;
+ }
+
+private:
+ class CaptureDiagnosticConsumer : public DiagnosticConsumer {
+ public:
+ std::vector<StoredDiagnostic> StoredDiags;
+
+ void HandleDiagnostic(DiagnosticsEngine::Level level,
+ const Diagnostic &Info) override {
+ StoredDiags.push_back(StoredDiagnostic(level, Info));
+ }
+ };
+ CaptureDiagnosticConsumer CaptureConsumer;
+};
+
+MATCHER_P(WithMessage, Msg, "has diagnostic message") {
+ return arg.getMessage() == Msg;
+}
+MATCHER(IsError, "has error severity") {
+ return arg.getLevel() == DiagnosticsEngine::Level::Error;
+}
+
+TEST_F(SuppressionMappingTest, MissingMappingFile) {
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ EXPECT_THAT(diags(), ElementsAre(AllOf(
+ WithMessage("no such file or directory: 'foo.txt'"),
+ IsError())));
+}
+
+TEST_F(SuppressionMappingTest, MalformedFile) {
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ FS->addFile("foo.txt", /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBuffer("asdf", "foo.txt"));
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ EXPECT_THAT(diags(),
+ ElementsAre(AllOf(
+ WithMessage("failed to process suppression mapping file "
+ "'foo.txt': malformed line 1: 'asdf'"),
+ IsError())));
+}
+
+TEST_F(SuppressionMappingTest, UnknownDiagName) {
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ FS->addFile("foo.txt", /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBuffer("[non-existing-warning]"));
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ EXPECT_THAT(diags(), ElementsAre(WithMessage(
+ "unknown warning option 'non-existing-warning'")));
+}
+
+TEST_F(SuppressionMappingTest, SuppressesGroup) {
+ llvm::StringLiteral SuppressionMappingFile = R"(
+ [unused]
+ src:*)";
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ FS->addFile("foo.txt", /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile));
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ EXPECT_THAT(diags(), IsEmpty());
+
+ EXPECT_TRUE(
+ Diags.isSuppressedViaMapping(diag::warn_unused_function, "foo.cpp"));
+ EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_deprecated, "foo.cpp"));
+}
+
+TEST_F(SuppressionMappingTest, EmitCategoryIsExcluded) {
+ llvm::StringLiteral SuppressionMappingFile = R"(
+ [unused]
+ src:*
+ src:*foo.cpp=emit)";
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ FS->addFile("foo.txt", /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile));
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ EXPECT_THAT(diags(), IsEmpty());
+
+ EXPECT_TRUE(
+ Diags.isSuppressedViaMapping(diag::warn_unused_function, "bar.cpp"));
+ EXPECT_FALSE(
+ Diags.isSuppressedViaMapping(diag::warn_unused_function, "foo.cpp"));
+}
+
+TEST_F(SuppressionMappingTest, LongestMatchWins) {
+ llvm::StringLiteral SuppressionMappingFile = R"(
+ [unused]
+ src:*clang/*
+ src:*clang/lib/Sema/*=emit
+ src:*clang/lib/Sema/foo*)";
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ FS->addFile("foo.txt", /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile));
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ EXPECT_THAT(diags(), IsEmpty());
+
+ EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
+ "clang/lib/Basic/foo.h"));
+ EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
+ "clang/lib/Sema/bar.h"));
+ EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
+ "clang/lib/Sema/foo.h"));
+}
+
+TEST_F(SuppressionMappingTest, IsIgnored) {
+ llvm::StringLiteral SuppressionMappingFile = R"(
+ [unused]
+ src:*clang/*)";
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ Diags.getDiagnosticOptions().Warnings = {"unused"};
+ FS->addFile("foo.txt", /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile));
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ ASSERT_THAT(diags(), IsEmpty());
+
+ FileManager FM({}, FS);
+ SourceManager SM(Diags, FM);
+
+ auto ClangID =
+ SM.createFileID(llvm::MemoryBuffer::getMemBuffer("", "clang/foo.h"));
+ auto NonClangID =
+ SM.createFileID(llvm::MemoryBuffer::getMemBuffer("", "llvm/foo.h"));
+ auto PresumedClangID =
+ SM.createFileID(llvm::MemoryBuffer::getMemBuffer("", "llvm/foo2.h"));
+ // Add a line directive to point into clang/foo.h
+ SM.AddLineNote(SM.getLocForStartOfFile(PresumedClangID), 42,
+ SM.getLineTableFilenameID("clang/foo.h"), false, false,
+ clang::SrcMgr::C_User);
+
+ EXPECT_TRUE(Diags.isIgnored(diag::warn_unused_function,
+ SM.getLocForStartOfFile(ClangID)));
+ EXPECT_FALSE(Diags.isIgnored(diag::warn_unused_function,
+ SM.getLocForStartOfFile(NonClangID)));
+ EXPECT_TRUE(Diags.isIgnored(diag::warn_unused_function,
+ SM.getLocForStartOfFile(PresumedClangID)));
+
+ // Pretend we have a clang-diagnostic pragma to enforce the warning. Make sure
+ // suppressing mapping doesn't take over.
+ Diags.setSeverity(diag::warn_unused_function, diag::Severity::Error,
+ SM.getLocForStartOfFile(ClangID));
+ EXPECT_FALSE(Diags.isIgnored(diag::warn_unused_function,
+ SM.getLocForStartOfFile(ClangID)));
}
+} // namespace
diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp b/clang/unittests/Frontend/CompilerInvocationTest.cpp
index 7912253..45478de 100644
--- a/clang/unittests/Frontend/CompilerInvocationTest.cpp
+++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp
@@ -1046,4 +1046,15 @@ TEST_F(CommandLineTest, PluginArgsRoundTripDeterminism) {
ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
}
+
+TEST_F(CommandLineTest, WarningSuppressionMappings) {
+ const char *Args[] = {"--warning-suppression-mappings=foo.txt"};
+
+ EXPECT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
+ EXPECT_EQ(Invocation.getDiagnosticOpts().DiagnosticSuppressionMappingsFile,
+ "foo.txt");
+
+ Invocation.generateCC1CommandLine(GeneratedArgs, *this);
+ EXPECT_THAT(GeneratedArgs, Contains(StrEq(Args[0])));
+}
} // anonymous namespace