diff options
author | Kadir Cetinkaya <kadircet@google.com> | 2024-11-13 09:34:23 +0100 |
---|---|---|
committer | Kadir Cetinkaya <kadircet@google.com> | 2024-11-13 10:35:22 +0100 |
commit | 5845688e91d85d46c0f47daaf4edfdfc772853cf (patch) | |
tree | 2041b20e105163e2a1297fe34c69b31e3a560960 /clang/unittests | |
parent | 42da81582ea5a0e5bb0e18af74e6c101f0307f36 (diff) | |
download | llvm-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.cpp | 169 | ||||
-rw-r--r-- | clang/unittests/Frontend/CompilerInvocationTest.cpp | 11 |
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 |