https://github.com/kadircet updated https://github.com/llvm/llvm-project/pull/112517
From 01a538fbbd93a7f26e1309c9c95d5be0c8500402 Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya <kadir...@google.com> Date: Mon, 14 Oct 2024 11:20:55 +0200 Subject: [PATCH 1/2] [clang] Introduce diagnostics suppression mappings This implements https://discourse.llvm.org/t/rfc-add-support-for-controlling-diagnostics-severities-at-file-level-granularity-through-command-line/81292. Users now can suppress warnings for certain headers by providing a mapping with globs, a sample file looks like: ``` [unused] src:* src:*clang/*=emit ``` This will suppress warnings from `-Wunused` group in all files that aren't under `clang/` directory. This mapping file can be passed to clang via `--warning-suppression-mappings=foo.txt`. At a high level, mapping file is stored in DiagnosticOptions and then processed with rest of the warning flags when creating a DiagnosticsEngine. This is a functor that uses SpecialCaseLists underneath to match against globs coming from the mappings file. This implies processing warning options now performs IO, relevant interfaces are updated to take in a VFS, falling back to RealFileSystem when one is not available. --- .../ExpandModularHeadersPPCallbacks.cpp | 3 +- clang/include/clang/Basic/Diagnostic.h | 15 +- .../clang/Basic/DiagnosticDriverKinds.td | 3 + clang/include/clang/Basic/DiagnosticOptions.h | 3 + clang/include/clang/Driver/Options.td | 5 + .../include/clang/Frontend/CompilerInstance.h | 10 +- clang/lib/Basic/Diagnostic.cpp | 12 ++ clang/lib/Basic/DiagnosticIDs.cpp | 27 ++- clang/lib/Basic/Warnings.cpp | 107 ++++++++++++ clang/lib/Driver/ToolChains/Clang.cpp | 7 + clang/lib/Frontend/ASTUnit.cpp | 15 +- clang/lib/Frontend/CompilerInstance.cpp | 21 ++- clang/lib/Frontend/CompilerInvocation.cpp | 8 + clang/lib/Frontend/PrecompiledPreamble.cpp | 2 +- clang/lib/Interpreter/CodeCompletion.cpp | 4 +- clang/lib/Serialization/ASTReader.cpp | 4 +- .../test/Misc/Inputs/suppression-mapping.txt | 4 + .../Misc/warning-suppression-mappings.cpp | 16 ++ clang/tools/driver/cc1gen_reproducer_main.cpp | 7 +- clang/tools/driver/driver.cpp | 7 +- clang/unittests/Basic/DiagnosticTest.cpp | 164 ++++++++++++++++++ .../Frontend/CompilerInvocationTest.cpp | 10 ++ llvm/include/llvm/Support/SpecialCaseList.h | 1 - 23 files changed, 419 insertions(+), 36 deletions(-) create mode 100644 clang/test/Misc/Inputs/suppression-mapping.txt create mode 100644 clang/test/Misc/warning-suppression-mappings.cpp diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp index fef086c5a99d86..4c34f9ea122d9e 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp @@ -81,7 +81,8 @@ ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks( Diags.setSourceManager(&Sources); // FIXME: Investigate whatever is there better way to initialize DiagEngine // or whatever DiagEngine can be shared by multiple preprocessors - ProcessWarningOptions(Diags, Compiler.getDiagnosticOpts()); + ProcessWarningOptions(Diags, Compiler.getDiagnosticOpts(), + Compiler.getVirtualFileSystem()); LangOpts.Modules = false; diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index 3b1efdb12824c7..79b7545e92d6da 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -20,11 +20,13 @@ #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/VirtualFileSystem.h" #include <cassert> #include <cstdint> #include <limits> @@ -555,6 +557,10 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { void *ArgToStringCookie = nullptr; ArgToStringFnTy ArgToStringFn; + /// Whether the diagnostic should be suppressed in FilePath. + llvm::unique_function<bool(diag::kind, llvm::StringRef /*FilePath*/) const> + DiagSuppressionMapping; + public: explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags, IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, @@ -946,6 +952,13 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this); } + /// Diagnostic suppression mappings can be used to ignore diagnostics based on + /// the file they occur in. + /// These take presumed locations into account, and can still be overriden by + /// clang-diagnostics pragmas. + void setDiagSuppressionMapping(decltype(DiagSuppressionMapping) Mapping); + bool isSuppressedViaMapping(diag::kind D, llvm::StringRef FilePath) const; + /// Issue the message to the client. /// /// This actually returns an instance of DiagnosticBuilder which emits the @@ -1759,7 +1772,7 @@ const char ToggleHighlight = 127; /// warning options specified on the command line. void ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, - bool ReportDiags = true); + llvm::vfs::FileSystem &VFS, bool ReportDiags = true); void EscapeStringForDiagnostic(StringRef Str, SmallVectorImpl<char> &OutStr); } // namespace clang diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 68722ad9633120..cbad93904a899f 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -831,4 +831,7 @@ def err_drv_triple_version_invalid : Error< def warn_missing_include_dirs : Warning< "no such include directory: '%0'">, InGroup<MissingIncludeDirs>, DefaultIgnore; + +def err_drv_malformed_warning_suppression_mapping : Error< + "failed to process suppression mapping file '%0' : %1">; } diff --git a/clang/include/clang/Basic/DiagnosticOptions.h b/clang/include/clang/Basic/DiagnosticOptions.h index 30141c2b8f4475..0770805624cec8 100644 --- a/clang/include/clang/Basic/DiagnosticOptions.h +++ b/clang/include/clang/Basic/DiagnosticOptions.h @@ -108,6 +108,9 @@ class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{ /// The file to serialize diagnostics to (non-appending). std::string DiagnosticSerializationFile; + /// File that defines suppression mappings. + std::string SuppressionMappingsFile; + /// The list of -W... options used to alter the diagnostic mappings, with the /// prefixes removed. std::vector<std::string> Warnings; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 379e75b197cf96..827126f5af30ca 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -8979,3 +8979,8 @@ def wasm_opt : Flag<["--"], "wasm-opt">, Group<m_Group>, HelpText<"Enable the wasm-opt optimizer (default)">, MarshallingInfoNegativeFlag<LangOpts<"NoWasmOpt">>; + +def warning_suppression_mappings_EQ : Joined<["--"], + "warning-suppression-mappings=">, Group<Diag_Group>, + HelpText<"File containing list of sources to suppress diagnostics for. See XXX for format">, + Visibility<[ClangOption, CC1Option]>; diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 3464654284f199..338eb3c6bd028d 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -24,6 +24,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/VirtualFileSystem.h" #include <cassert> #include <list> #include <memory> @@ -701,11 +702,10 @@ class CompilerInstance : public ModuleLoader { /// used by some diagnostics printers (for logging purposes only). /// /// \return The new object on success, or null on failure. - static IntrusiveRefCntPtr<DiagnosticsEngine> - createDiagnostics(DiagnosticOptions *Opts, - DiagnosticConsumer *Client = nullptr, - bool ShouldOwnClient = true, - const CodeGenOptions *CodeGenOpts = nullptr); + static IntrusiveRefCntPtr<DiagnosticsEngine> createDiagnostics( + DiagnosticOptions *Opts, DiagnosticConsumer *Client = nullptr, + bool ShouldOwnClient = true, const CodeGenOptions *CodeGenOpts = nullptr, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr); /// Create the file manager and replace any existing one with it. /// diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index e23362fc7af00d..e536effd25072f 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -21,6 +21,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TokenKinds.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -28,6 +29,7 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/Unicode.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -477,6 +479,16 @@ void DiagnosticsEngine::setSeverityForAll(diag::Flavor Flavor, setSeverity(Diag, Map, Loc); } +void DiagnosticsEngine::setDiagSuppressionMapping( + decltype(DiagSuppressionMapping) Mapping) { + DiagSuppressionMapping = std::move(Mapping); +} + +bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind D, + llvm::StringRef FilePath) const { + return DiagSuppressionMapping && DiagSuppressionMapping(D, FilePath); +} + void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) { DiagnosticStorage DiagStorage; DiagStorage.DiagRanges.append(storedDiag.range_begin(), diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index d45bb0f392d457..4f213e02fa9324 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -575,6 +575,12 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, DiagID != diag::fatal_too_many_errors && Diag.FatalsAsError) Result = diag::Severity::Error; + // Rest of the mappings are only applicable for diagnostics associated with a + // SourceLocation, bail out early for others. + if (!Diag.hasSourceManager()) + return Result; + + const auto &SM = Diag.getSourceManager(); // Custom diagnostics always are emitted in system headers. bool ShowInSystemHeader = !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; @@ -582,18 +588,29 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, // If we are in a system header, we ignore it. We look at the diagnostic class // because we also want to ignore extensions and warnings in -Werror and // -pedantic-errors modes, which *map* warnings/extensions to errors. - if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() && - Diag.getSourceManager().isInSystemHeader( - Diag.getSourceManager().getExpansionLoc(Loc))) + if (State->SuppressSystemWarnings && !ShowInSystemHeader && + SM.isInSystemHeader(SM.getExpansionLoc(Loc))) return diag::Severity::Ignored; // We also ignore warnings due to system macros bool ShowInSystemMacro = !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro; - if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() && - Diag.getSourceManager().isInSystemMacro(Loc)) + if (State->SuppressSystemWarnings && !ShowInSystemMacro && + SM.isInSystemMacro(Loc)) return diag::Severity::Ignored; + // Apply suppression mappings if severity wasn't explicitly mapped with a + // clang-diagnostics pragma to ensure pragmas always take precedence over + // mappings. + // We also use presumed locations here to improve reproducibility for + // preprocessed inputs. + if (!Mapping.isPragma()) { + if (auto PLoc = SM.getPresumedLoc(Loc); + PLoc.isValid() && + Diag.isSuppressedViaMapping(DiagID, PLoc.getFilename())) + return diag::Severity::Ignored; + } + return Result; } diff --git a/clang/lib/Basic/Warnings.cpp b/clang/lib/Basic/Warnings.cpp index 5a5ac555633886..1047980b84d7db 100644 --- a/clang/lib/Basic/Warnings.cpp +++ b/clang/lib/Basic/Warnings.cpp @@ -23,10 +23,21 @@ // simpler because a remark can't be promoted to an error. #include "clang/Basic/AllDiagnostics.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticDriver.h" +#include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticOptions.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMapEntry.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SpecialCaseList.h" +#include "llvm/Support/VirtualFileSystem.h" #include <algorithm> #include <cstring> +#include <memory> #include <utility> +#include <vector> using namespace clang; // EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning @@ -41,8 +52,96 @@ static void EmitUnknownDiagWarning(DiagnosticsEngine &Diags, << (Prefix.str() += std::string(Suggestion)); } +namespace { +class WarningsSpecialCaseList : public llvm::SpecialCaseList { +public: + static std::unique_ptr<WarningsSpecialCaseList> + create(const llvm::MemoryBuffer &MB, std::string &Err) { + auto SCL = std::make_unique<WarningsSpecialCaseList>(); + if (SCL->createInternal(&MB, Err)) + return SCL; + return nullptr; + } + + // Section names refer to diagnostic groups, which cover multiple individual + // diagnostics. Expand diagnostic groups here to individual diagnostics. + // A diagnostic can have multiple diagnostic groups associated with it, we let + // the last section take precedence in such cases. + void processSections(DiagnosticsEngine &Diags) { + // Drop the default section introduced by special case list, we only support + // exact diagnostic group names. + Sections.erase("*"); + // Make sure we iterate sections by their line numbers. + std::vector<std::pair<unsigned, const llvm::StringMapEntry<Section> *>> + LineAndSection; + for (const auto &Entry : Sections) { + LineAndSection.emplace_back( + Entry.second.SectionMatcher->Globs.at(Entry.first()).second, &Entry); + } + llvm::sort(LineAndSection); + for (const auto &[_, Entry] : LineAndSection) { + SmallVector<diag::kind, 256> GroupDiags; + if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup( + clang::diag::Flavor::WarningOrError, Entry->first(), + GroupDiags)) { + EmitUnknownDiagWarning(Diags, clang::diag::Flavor::WarningOrError, "", + Entry->first()); + continue; + } + for (auto D : GroupDiags) + DiagToSection[D] = &Entry->getValue(); + } + } + + bool isDiagSuppressed(diag::kind D, llvm::StringRef FilePath) const { + auto Section = DiagToSection.find(D); + if (Section == DiagToSection.end()) + return false; + auto SrcEntries = Section->second->Entries.find("src"); + if(SrcEntries == Section->second->Entries.end()) + return false; + // Find the longest glob pattern that matches FilePath. A positive match + // implies D should be suppressed for FilePath. + llvm::StringRef LongestMatch; + bool LongestWasNegative; + for (const auto &CatIt : SrcEntries->second) { + bool IsNegative = CatIt.first() == "emit"; + for (const auto &GlobIt : CatIt.second.Globs) { + if (GlobIt.getKeyLength() < LongestMatch.size()) + continue; + if (!GlobIt.second.first.match(FilePath)) + continue; + LongestMatch = GlobIt.getKey(); + LongestWasNegative = IsNegative; + } + } + return !LongestMatch.empty() && !LongestWasNegative; + } + +private: + llvm::DenseMap<diag::kind, const Section*> DiagToSection; +}; + +void parseSuppressionMappings(const llvm::MemoryBuffer &MB, + DiagnosticsEngine &Diags) { + std::string Err; + auto SCL = WarningsSpecialCaseList::create(MB, Err); + if (!SCL) { + Diags.Report(diag::err_drv_malformed_warning_suppression_mapping) + << MB.getBufferIdentifier() << Err; + return; + } + SCL->processSections(Diags); + Diags.setDiagSuppressionMapping( + [SCL(std::move(SCL))](diag::kind K, llvm::StringRef Path) { + return SCL->isDiagSuppressed(K, Path); + }); +} +} // namespace + void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, + llvm::vfs::FileSystem& VFS, bool ReportDiags) { Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings); @@ -70,6 +169,14 @@ void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, else Diags.setExtensionHandlingBehavior(diag::Severity::Ignored); + if (!Opts.SuppressionMappingsFile.empty()) { + if (auto Buf = VFS.getBufferForFile(Opts.SuppressionMappingsFile)) { + parseSuppressionMappings(**Buf, Diags); + } else if (ReportDiags) { + Diags.Report(diag::err_drv_no_such_file) << Opts.SuppressionMappingsFile; + } + } + SmallVector<diag::kind, 10> _Diags; const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs = Diags.getDiagnosticIDs(); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3fc39296f44281..55ec543c5de514 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4456,6 +4456,13 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args, Args.addOptOutFlag(CmdArgs, options::OPT_fspell_checking, options::OPT_fno_spell_checking); + + if (const Arg *A = + Args.getLastArg(options::OPT_warning_suppression_mappings_EQ)) { + if (!D.getVFS().exists(A->getValue())) + D.Diag(clang::diag::err_drv_no_such_file) << A->getValue(); + CmdArgs.push_back(Args.MakeArgString(A->getSpelling() + A->getValue())); + } } DwarfFissionKind tools::getDebugFissionKind(const Driver &D, diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index bffff0d27af3ab..464ed8090a0ec5 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1367,7 +1367,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( // after parsing the preamble. getDiagnostics().Reset(); ProcessWarningOptions(getDiagnostics(), - PreambleInvocationIn.getDiagnosticOpts()); + PreambleInvocationIn.getDiagnosticOpts(), *VFS); getDiagnostics().setNumWarnings(NumWarningsInPreamble); PreambleRebuildCountdown = 1; @@ -1593,7 +1593,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( // We'll manage file buffers ourselves. CI->getPreprocessorOpts().RetainRemappedFileBuffers = true; CI->getFrontendOpts().DisableFree = false; - ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts()); + ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts(), + AST->getFileManager().getVirtualFileSystem()); // Create the compiler instance to use for building the AST. std::unique_ptr<CompilerInstance> Clang( @@ -1701,7 +1702,7 @@ bool ASTUnit::LoadFromCompilerInvocation( Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true; Invocation->getFrontendOpts().DisableFree = false; getDiagnostics().Reset(); - ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); + ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(), *VFS); std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; if (PrecompilePreambleAfterNParses > 0) { @@ -1709,7 +1710,7 @@ bool ASTUnit::LoadFromCompilerInvocation( OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); getDiagnostics().Reset(); - ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); + ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(), *VFS); } SimpleTimer ParsingTimer(WantTiming); @@ -1902,7 +1903,8 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, // Clear out the diagnostics state. FileMgr.reset(); getDiagnostics().Reset(); - ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); + ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(), + *VFS); if (OverrideMainBuffer) getDiagnostics().setNumWarnings(NumWarningsInPreamble); @@ -2241,7 +2243,8 @@ void ASTUnit::CodeComplete( CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All, Clang->getDiagnostics(), &StoredDiagnostics, nullptr); - ProcessWarningOptions(Diag, Inv.getDiagnosticOpts()); + ProcessWarningOptions(Diag, Inv.getDiagnosticOpts(), + FileMgr.getVirtualFileSystem()); // Create the target instance. if (!Clang->createTarget()) { diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 240305b33824b8..ecc6782c7cb4fb 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -39,6 +39,7 @@ #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/GlobalModuleIndex.h" #include "clang/Serialization/InMemoryModuleCache.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/Statistic.h" @@ -54,6 +55,7 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" #include <optional> @@ -332,19 +334,22 @@ static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts, void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client, bool ShouldOwnClient) { - Diagnostics = createDiagnostics(&getDiagnosticOpts(), Client, - ShouldOwnClient, &getCodeGenOpts()); + Diagnostics = createDiagnostics( + &getDiagnosticOpts(), Client, ShouldOwnClient, &getCodeGenOpts(), + FileMgr ? FileMgr->getVirtualFileSystemPtr() : nullptr); } -IntrusiveRefCntPtr<DiagnosticsEngine> -CompilerInstance::createDiagnostics(DiagnosticOptions *Opts, - DiagnosticConsumer *Client, - bool ShouldOwnClient, - const CodeGenOptions *CodeGenOpts) { +IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics( + DiagnosticOptions *Opts, DiagnosticConsumer *Client, bool ShouldOwnClient, + const CodeGenOptions *CodeGenOpts, + llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr<DiagnosticsEngine> Diags(new DiagnosticsEngine(DiagID, Opts)); + if (!VFS) + VFS = llvm::vfs::getRealFileSystem(); + // Create the diagnostic client for reporting errors or for // implementing -verify. if (Client) { @@ -367,7 +372,7 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts, Opts->DiagnosticSerializationFile); // Configure our handling of diagnostics. - ProcessWarningOptions(*Diags, *Opts); + ProcessWarningOptions(*Diags, *Opts, *VFS); return Diags; } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index db7c791059a32e..5efb159bdea3bd 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2521,6 +2521,11 @@ void CompilerInvocationBase::GenerateDiagnosticArgs( Consumer(StringRef("-R") + Remark); } + + if (!Opts.SuppressionMappingsFile.empty()) { + GenerateArg(Consumer, OPT_warning_suppression_mappings_EQ, + Opts.SuppressionMappingsFile); + } } std::unique_ptr<DiagnosticOptions> @@ -2597,6 +2602,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.TabStop = DiagnosticOptions::DefaultTabStop; } + if (const Arg *A = Args.getLastArg(OPT_warning_suppression_mappings_EQ)) + Opts.SuppressionMappingsFile = A->getValue(); + addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings); addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks); diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp index cab5838fceb24d..d1bac09830b04b 100644 --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -479,7 +479,7 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( // Clear out old caches and data. Diagnostics.Reset(); - ProcessWarningOptions(Diagnostics, Clang->getDiagnosticOpts()); + ProcessWarningOptions(Diagnostics, Clang->getDiagnosticOpts(), *VFS); VFS = createVFSFromCompilerInvocation(Clang->getInvocation(), Diagnostics, VFS); diff --git a/clang/lib/Interpreter/CodeCompletion.cpp b/clang/lib/Interpreter/CodeCompletion.cpp index 791426807cb91d..bbc8830d76bc00 100644 --- a/clang/lib/Interpreter/CodeCompletion.cpp +++ b/clang/lib/Interpreter/CodeCompletion.cpp @@ -380,8 +380,8 @@ void ReplCodeCompleter::codeComplete(CompilerInstance *InterpCI, AU->CodeComplete(CodeCompletionFileName, 1, Col, RemappedFiles, false, false, false, consumer, std::make_shared<clang::PCHContainerOperations>(), *diag, - InterpCI->getLangOpts(), InterpCI->getSourceManager(), - InterpCI->getFileManager(), sd, tb, std::move(Act)); + InterpCI->getLangOpts(), AU->getSourceManager(), + AU->getFileManager(), sd, tb, std::move(Act)); } } // namespace clang diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 1b2473f2457344..93b362bfb569b7 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -602,7 +602,9 @@ bool PCHValidator::ReadDiagnosticOptions( new DiagnosticsEngine(DiagIDs, DiagOpts.get())); // This should never fail, because we would have processed these options // before writing them to an ASTFile. - ProcessWarningOptions(*Diags, *DiagOpts, /*Report*/false); + ProcessWarningOptions(*Diags, *DiagOpts, + PP.getFileManager().getVirtualFileSystem(), + /*Report*/ false); ModuleManager &ModuleMgr = Reader.getModuleManager(); assert(ModuleMgr.size() >= 1 && "what ASTFile is this then"); diff --git a/clang/test/Misc/Inputs/suppression-mapping.txt b/clang/test/Misc/Inputs/suppression-mapping.txt new file mode 100644 index 00000000000000..d1fd0e89256d3b --- /dev/null +++ b/clang/test/Misc/Inputs/suppression-mapping.txt @@ -0,0 +1,4 @@ +# Suppress unused warnings in all files, apart from the ones under `foo/`. +[unused] +src:* +src:*foo/*=emit diff --git a/clang/test/Misc/warning-suppression-mappings.cpp b/clang/test/Misc/warning-suppression-mappings.cpp new file mode 100644 index 00000000000000..0626d7279e804a --- /dev/null +++ b/clang/test/Misc/warning-suppression-mappings.cpp @@ -0,0 +1,16 @@ +// Check for warnings +// RUN: not %clang --warning-suppression-mappings=foo.txt -fsyntax-only %s 2>&1 | FileCheck -check-prefix MISSING_MAPPING %s +// RUN: not %clang -cc1 --warning-suppression-mappings=foo.txt -fsyntax-only %s 2>&1 | FileCheck -check-prefix MISSING_MAPPING %s +// MISSING_MAPPING: error: no such file or directory: 'foo.txt' + +// Check that it's no-op when diagnostics aren't enabled. +// RUN: %clang -cc1 -Werror --warning-suppression-mappings=%S/Inputs/suppression-mapping.txt -fsyntax-only %s 2>&1 | FileCheck -check-prefix WARNINGS_DISABLED --allow-empty %s +// WARNINGS_DISABLED-NOT: warning: +// WARNINGS_DISABLED-NOT: error: + +// RUN: %clang -cc1 -verify -Wunused --warning-suppression-mappings=%S/Inputs/suppression-mapping.txt -fsyntax-only %s + +namespace { void foo(); } + +#line 42 "foo/bar.h" +namespace { void bar(); } // expected-warning{{unused function 'bar'}} diff --git a/clang/tools/driver/cc1gen_reproducer_main.cpp b/clang/tools/driver/cc1gen_reproducer_main.cpp index be081cac8c03b1..df59b53f9ef186 100644 --- a/clang/tools/driver/cc1gen_reproducer_main.cpp +++ b/clang/tools/driver/cc1gen_reproducer_main.cpp @@ -121,9 +121,10 @@ generateReproducerForInvocationArguments(ArrayRef<const char *> Argv, IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); DiagnosticsEngine Diags(DiagID, &*DiagOpts, new IgnoringDiagConsumer()); - ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false); - Driver TheDriver(ToolContext.Path, llvm::sys::getDefaultTargetTriple(), - Diags); + auto VFS = llvm::vfs::getRealFileSystem(); + ProcessWarningOptions(Diags, *DiagOpts, *VFS, /*ReportDiags=*/false); + Driver TheDriver(ToolContext.Path, llvm::sys::getDefaultTargetTriple(), Diags, + /*Title=*/"clang LLVM compiler", VFS); TheDriver.setTargetAndMode(TargetAndMode); if (ToolContext.NeedsPrependArg) TheDriver.setPrependArg(ToolContext.PrependArg); diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 686eaea0aa7c83..12038de476ace1 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -47,6 +47,7 @@ #include "llvm/Support/StringSaver.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" #include <memory> @@ -334,9 +335,11 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) { Diags.takeClient(), std::move(SerializedConsumer))); } - ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false); + auto VFS = llvm::vfs::getRealFileSystem(); + ProcessWarningOptions(Diags, *DiagOpts, *VFS, /*ReportDiags=*/false); - Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); + Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags, + /*Title=*/"clang LLVM compiler", VFS); auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(ProgName); TheDriver.setTargetAndMode(TargetAndMode); // If -canonical-prefixes is set, GetExecutablePath will have resolved Path diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp index 691d74f697f278..1be446d86403df 100644 --- a/clang/unittests/Basic/DiagnosticTest.cpp +++ b/clang/unittests/Basic/DiagnosticTest.cpp @@ -10,8 +10,17 @@ #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/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; @@ -162,4 +171,159 @@ 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}; + + std::vector<StoredDiagnostic> takeDiags() { + return std::move(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; +} + +TEST_F(SuppressionMappingTest, MissingMappingFile) { + Diags.getDiagnosticOptions().SuppressionMappingsFile = "foo.txt"; + clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); + EXPECT_THAT(takeDiags(), testing::ElementsAre(WithMessage( + "no such file or directory: 'foo.txt'"))); +} + +TEST_F(SuppressionMappingTest, MalformedFile) { + Diags.getDiagnosticOptions().SuppressionMappingsFile = "foo.txt"; + FS->addFile("foo.txt", /*ModificationTime=*/{}, + llvm::MemoryBuffer::getMemBuffer("asdf", "foo.txt")); + clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); + EXPECT_THAT(takeDiags(), testing::ElementsAre(WithMessage( + "failed to process suppression mapping file " + "'foo.txt' : malformed line 1: 'asdf'"))); +} + +TEST_F(SuppressionMappingTest, UnknownDiagName) { + Diags.getDiagnosticOptions().SuppressionMappingsFile = "foo.txt"; + FS->addFile("foo.txt", /*ModificationTime=*/{}, + llvm::MemoryBuffer::getMemBuffer("[non-existing-warning]")); + clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); + EXPECT_THAT(takeDiags(), + testing::ElementsAre(WithMessage( + "unknown warning option 'non-existing-warning'"))); +} + +TEST_F(SuppressionMappingTest, SuppressesGroup) { + llvm::StringLiteral SuppressionMappingFile = R"txt( + [unused] + src:* + )txt"; + Diags.getDiagnosticOptions().SuppressionMappingsFile = "foo.txt"; + FS->addFile("foo.txt", /*ModificationTime=*/{}, + llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile)); + clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); + EXPECT_THAT(takeDiags(), testing::IsEmpty()); + + EXPECT_TRUE( + Diags.isSuppressedViaMapping(diag::warn_unused_function, "foo.cpp")); + EXPECT_FALSE(Diags.isSuppressedViaMapping(diag::warn_deprecated, "foo.cpp")); +} + +TEST_F(SuppressionMappingTest, ExclusionsWork) { + llvm::StringLiteral SuppressionMappingFile = R"txt( + [unused] + src:* + src:*foo.cpp=emit + )txt"; + Diags.getDiagnosticOptions().SuppressionMappingsFile = "foo.txt"; + FS->addFile("foo.txt", /*ModificationTime=*/{}, + llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile)); + clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); + EXPECT_THAT(takeDiags(), testing::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"txt( + [unused] + src:*clang/* + src:*clang/lib/Sema/*=emit + src:*clang/lib/Sema/foo* + )txt"; + Diags.getDiagnosticOptions().SuppressionMappingsFile = "foo.txt"; + FS->addFile("foo.txt", /*ModificationTime=*/{}, + llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile)); + clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); + EXPECT_THAT(takeDiags(), testing::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"txt( + [unused] + src:*clang/* + )txt"; + Diags.getDiagnosticOptions().SuppressionMappingsFile = "foo.txt"; + Diags.getDiagnosticOptions().Warnings = {"unused"}; + FS->addFile("foo.txt", /*ModificationTime=*/{}, + llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile)); + clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS); + EXPECT_THAT(takeDiags(), testing::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 7912253b761e9b..1cf2bbb6576621 100644 --- a/clang/unittests/Frontend/CompilerInvocationTest.cpp +++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp @@ -1046,4 +1046,14 @@ 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().SuppressionMappingsFile, "foo.txt"); + + Invocation.generateCC1CommandLine(GeneratedArgs, *this); + EXPECT_THAT(GeneratedArgs, Contains(StrEq(Args[0]))); +} } // anonymous namespace diff --git a/llvm/include/llvm/Support/SpecialCaseList.h b/llvm/include/llvm/Support/SpecialCaseList.h index 6dc1a29c5a281d..30e3fc644bbc33 100644 --- a/llvm/include/llvm/Support/SpecialCaseList.h +++ b/llvm/include/llvm/Support/SpecialCaseList.h @@ -122,7 +122,6 @@ class SpecialCaseList { // Returns zero if no match is found. unsigned match(StringRef Query) const; - private: StringMap<std::pair<GlobPattern, unsigned>> Globs; std::vector<std::pair<std::unique_ptr<Regex>, unsigned>> RegExes; }; From 5fb6c79e68a314f754d52fe07ebd80ae614e5af1 Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya <kadir...@google.com> Date: Thu, 17 Oct 2024 10:40:14 +0200 Subject: [PATCH 2/2] clang-format --- clang/lib/Basic/Warnings.cpp | 6 +++--- clang/lib/Frontend/ASTUnit.cpp | 6 ++++-- clang/unittests/Basic/DiagnosticTest.cpp | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/clang/lib/Basic/Warnings.cpp b/clang/lib/Basic/Warnings.cpp index 1047980b84d7db..c074d719a77234 100644 --- a/clang/lib/Basic/Warnings.cpp +++ b/clang/lib/Basic/Warnings.cpp @@ -98,7 +98,7 @@ class WarningsSpecialCaseList : public llvm::SpecialCaseList { if (Section == DiagToSection.end()) return false; auto SrcEntries = Section->second->Entries.find("src"); - if(SrcEntries == Section->second->Entries.end()) + if (SrcEntries == Section->second->Entries.end()) return false; // Find the longest glob pattern that matches FilePath. A positive match // implies D should be suppressed for FilePath. @@ -119,7 +119,7 @@ class WarningsSpecialCaseList : public llvm::SpecialCaseList { } private: - llvm::DenseMap<diag::kind, const Section*> DiagToSection; + llvm::DenseMap<diag::kind, const Section *> DiagToSection; }; void parseSuppressionMappings(const llvm::MemoryBuffer &MB, @@ -141,7 +141,7 @@ void parseSuppressionMappings(const llvm::MemoryBuffer &MB, void clang::ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, - llvm::vfs::FileSystem& VFS, + llvm::vfs::FileSystem &VFS, bool ReportDiags) { Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings); diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 464ed8090a0ec5..5739eeca4d7826 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1702,7 +1702,8 @@ bool ASTUnit::LoadFromCompilerInvocation( Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true; Invocation->getFrontendOpts().DisableFree = false; getDiagnostics().Reset(); - ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(), *VFS); + ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(), + *VFS); std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; if (PrecompilePreambleAfterNParses > 0) { @@ -1710,7 +1711,8 @@ bool ASTUnit::LoadFromCompilerInvocation( OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); getDiagnostics().Reset(); - ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(), *VFS); + ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts(), + *VFS); } SimpleTimer ParsingTimer(WantTiming); diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp index 1be446d86403df..cffe9d32a66e8f 100644 --- a/clang/unittests/Basic/DiagnosticTest.cpp +++ b/clang/unittests/Basic/DiagnosticTest.cpp @@ -190,7 +190,7 @@ class SuppressionMappingTest : public testing::Test { private: class CaptureDiagnosticConsumer : public DiagnosticConsumer { public: - std::vector<StoredDiagnostic> StoredDiags; + std::vector<StoredDiagnostic> StoredDiags; void HandleDiagnostic(DiagnosticsEngine::Level level, const Diagnostic &Info) override { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits