Index: clang/include/clang/Analysis/PathDiagnosticConsumers.h =================================================================== --- clang/include/clang/Analysis/PathDiagnosticConsumers.h +++ clang/include/clang/Analysis/PathDiagnosticConsumers.h @@ -34,7 +34,7 @@ PathDiagnosticConsumers &C, const std::string &Prefix, \ const Preprocessor &PP, \ const cross_tu::CrossTranslationUnitContext &CTU); -#include "clang/StaticAnalyzer/Core/Analyses.def" +#include "clang/Analysis/PathDiagnosticConsumers.def" } // end 'ento' namespace } // end 'clang' namespace Index: clang/include/clang/Analysis/PathDiagnosticConsumers.def =================================================================== --- /dev/null +++ clang/include/clang/Analysis/PathDiagnosticConsumers.def @@ -0,0 +1,26 @@ +//===-- PathDiagnosticConsumers.def - Visualizing warnings ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the set of path diagnostic consumers - objects that +// implement different representations of static analysis results. +// +//===----------------------------------------------------------------------===// + +#ifndef ANALYSIS_DIAGNOSTICS +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) +#endif + +ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(HTML_SINGLE_FILE, "html-single-file", "Output analysis results using HTML (not allowing for multi-file bugs)", createHTMLSingleFileDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for multi-file bugs)", createPlistMultiFileDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(SARIF, "sarif", "Output analysis results in a SARIF file", createSarifDiagnosticConsumer) +ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer) + +#undef ANALYSIS_DIAGNOSTICS Index: clang/include/clang/StaticAnalyzer/Core/Analyses.def =================================================================== --- clang/include/clang/StaticAnalyzer/Core/Analyses.def +++ clang/include/clang/StaticAnalyzer/Core/Analyses.def @@ -23,18 +23,6 @@ ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager) ANALYSIS_CONSTRAINTS(Z3Constraints, "z3", "Use Z3 contraint solver", CreateZ3ConstraintManager) -#ifndef ANALYSIS_DIAGNOSTICS -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) -#endif - -ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer) -ANALYSIS_DIAGNOSTICS(HTML_SINGLE_FILE, "html-single-file", "Output analysis results using HTML (not allowing for multi-file bugs)", createHTMLSingleFileDiagnosticConsumer) -ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer) -ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for multi-file bugs)", createPlistMultiFileDiagnosticConsumer) -ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer) -ANALYSIS_DIAGNOSTICS(SARIF, "sarif", "Output analysis results in a SARIF file", createSarifDiagnosticConsumer) -ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer) - #ifndef ANALYSIS_PURGE #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) #endif @@ -52,7 +40,6 @@ #undef ANALYSIS_STORE #undef ANALYSIS_CONSTRAINTS -#undef ANALYSIS_DIAGNOSTICS #undef ANALYSIS_PURGE #undef ANALYSIS_INLINING_MODE #undef ANALYSIS_IPA Index: clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -58,7 +58,7 @@ /// analysis results. enum AnalysisDiagClients { #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME, -#include "clang/StaticAnalyzer/Core/Analyses.def" +#include "clang/Analysis/PathDiagnosticConsumers.def" PD_NONE, NUM_ANALYSIS_DIAG_CLIENTS }; Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -16,9 +16,9 @@ #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/PathDiagnosticConsumers.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" -#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" namespace clang { Index: clang/lib/Analysis/CMakeLists.txt =================================================================== --- clang/lib/Analysis/CMakeLists.txt +++ clang/lib/Analysis/CMakeLists.txt @@ -16,14 +16,19 @@ CodeInjector.cpp Dominators.cpp ExprMutationAnalyzer.cpp + HTMLDiagnostics.cpp IssueHash.cpp LiveVariables.cpp ObjCNoReturn.cpp PathDiagnostic.cpp + PlistDiagnostics.cpp + PlistHTMLDiagnostics.cpp PostOrderCFGView.cpp ProgramPoint.cpp ReachableCode.cpp RetainSummaryManager.cpp + SarifDiagnostics.cpp + TextDiagnostics.cpp ThreadSafety.cpp ThreadSafetyCommon.cpp ThreadSafetyLogical.cpp Index: clang/lib/Analysis/HTMLDiagnostics.cpp =================================================================== --- clang/lib/Analysis/HTMLDiagnostics.cpp +++ clang/lib/Analysis/HTMLDiagnostics.cpp @@ -12,6 +12,7 @@ #include "clang/Analysis/IssueHash.h" #include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/PathDiagnosticConsumers.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/Stmt.h" @@ -24,7 +25,6 @@ #include "clang/Lex/Token.h" #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/Rewrite/Core/Rewriter.h" -#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" Index: clang/lib/Analysis/PlistDiagnostics.cpp =================================================================== --- clang/lib/Analysis/PlistDiagnostics.cpp +++ clang/lib/Analysis/PlistDiagnostics.cpp @@ -12,6 +12,7 @@ #include "clang/Analysis/IssueHash.h" #include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/PathDiagnosticConsumers.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/PlistSupport.h" #include "clang/Basic/SourceManager.h" @@ -21,7 +22,6 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Lex/TokenConcatenation.h" #include "clang/Rewrite/Core/HTMLRewrite.h" -#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" Index: clang/lib/Analysis/PlistHTMLDiagnostics.cpp =================================================================== --- /dev/null +++ clang/lib/Analysis/PlistHTMLDiagnostics.cpp @@ -0,0 +1,32 @@ +//===--- PlistHTMLDiagnostics.cpp - The Plist-HTML Diagnostic Consumer. ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This diagnostic consumer produces both the HTML output and the Plist output. +// +//===----------------------------------------------------------------------===// + +#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" +#include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/PathDiagnosticConsumers.h" +#include "clang/Basic/SourceManager.h" +#include "clang/CrossTU/CrossTranslationUnit.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; +using namespace ento; + +void ento::createPlistHTMLDiagnosticConsumer( + PathDiagnosticConsumerOptions &&DiagOpts, PathDiagnosticConsumers &C, + const std::string &prefix, const Preprocessor &PP, + const cross_tu::CrossTranslationUnitContext &CTU) { + // Duplicate the DiagOpts object into both consumers. + createHTMLDiagnosticConsumer(PathDiagnosticConsumerOptions(DiagOpts), C, + llvm::sys::path::parent_path(prefix), PP, CTU); + createPlistMultiFileDiagnosticConsumer( + PathDiagnosticConsumerOptions(DiagOpts), C, prefix, PP, CTU); +} Index: clang/lib/Analysis/SarifDiagnostics.cpp =================================================================== --- clang/lib/Analysis/SarifDiagnostics.cpp +++ clang/lib/Analysis/SarifDiagnostics.cpp @@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/PathDiagnosticConsumers.h" #include "clang/Basic/Version.h" #include "clang/Lex/Preprocessor.h" -#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/JSON.h" Index: clang/lib/Analysis/TextDiagnostics.cpp =================================================================== --- /dev/null +++ clang/lib/Analysis/TextDiagnostics.cpp @@ -0,0 +1,117 @@ +//===--- TextDiagnostics.cpp - Emit Path Diagnostics as Clang Warnings ----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This diagnostic consumer emits path diagnostics as Clang warnings and notes. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/PathDiagnosticConsumers.h" +#include "clang/Basic/SourceManager.h" +#include "clang/CrossTU/CrossTranslationUnit.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; +using namespace ento; + +namespace { +class TextDiagnostics : public PathDiagnosticConsumer { + DiagnosticsEngine &Diag; + bool IncludePath = false, ShouldEmitAsError = false, FixitsAsRemarks = false; + +public: + TextDiagnostics(PathDiagnosticConsumerOptions &&DiagOpts, + DiagnosticsEngine &Diag) + : Diag(Diag), IncludePath(DiagOpts.ShouldDisplayPathNotes), + ShouldEmitAsError(DiagOpts.ShouldDisplayWarningsAsErrors), + FixitsAsRemarks(DiagOpts.ShouldEmitFixItHintsAsRemarks) {} + ~TextDiagnostics() override = default; + StringRef getName() const override { return "ClangDiags"; } + + bool supportsLogicalOpControlFlow() const override { return true; } + bool supportsCrossFileDiagnostics() const override { return true; } + + PathGenerationScheme getGenerationScheme() const override { + return IncludePath ? Minimal : None; + } + + void FlushDiagnosticsImpl(std::vector &Diags, + FilesMade *filesMade) override; +}; +} // end anonymous namespace + +void TextDiagnostics::FlushDiagnosticsImpl( + std::vector &Diags, FilesMade *filesMade) { + unsigned WarnID = + ShouldEmitAsError + ? Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0") + : Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0"); + unsigned NoteID = Diag.getCustomDiagID(DiagnosticsEngine::Note, "%0"); + unsigned RemarkID = Diag.getCustomDiagID(DiagnosticsEngine::Remark, "%0"); + + auto reportPiece = [&](unsigned ID, SourceLocation Loc, StringRef String, + ArrayRef Ranges, + ArrayRef Fixits) { + if (!FixitsAsRemarks) { + Diag.Report(Loc, ID) << String << Ranges << Fixits; + } else { + Diag.Report(Loc, ID) << String << Ranges; + for (const FixItHint &Hint : Fixits) { + SourceManager &SM = Diag.getSourceManager(); + llvm::SmallString<128> Str; + llvm::raw_svector_ostream OS(Str); + // FIXME: Add support for InsertFromRange and + // BeforePreviousInsertion. + assert(!Hint.InsertFromRange.isValid() && "Not implemented yet!"); + assert(!Hint.BeforePreviousInsertions && "Not implemented yet!"); + OS << SM.getSpellingColumnNumber(Hint.RemoveRange.getBegin()) << "-" + << SM.getSpellingColumnNumber(Hint.RemoveRange.getEnd()) << ": '" + << Hint.CodeToInsert << "'"; + Diag.Report(Loc, RemarkID) << OS.str(); + } + } + }; + + for (std::vector::iterator I = Diags.begin(), + E = Diags.end(); + I != E; ++I) { + const PathDiagnostic *PD = *I; + reportPiece(WarnID, PD->getLocation().asLocation(), + PD->getShortDescription(), PD->path.back()->getRanges(), + PD->path.back()->getFixits()); + + // First, add extra notes, even if paths should not be included. + for (const auto &Piece : PD->path) { + if (!isa(Piece.get())) + continue; + + reportPiece(NoteID, Piece->getLocation().asLocation(), Piece->getString(), + Piece->getRanges(), Piece->getFixits()); + } + + if (!IncludePath) + continue; + + // Then, add the path notes if necessary. + PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true); + for (const auto &Piece : FlatPath) { + if (isa(Piece.get())) + continue; + + reportPiece(NoteID, Piece->getLocation().asLocation(), Piece->getString(), + Piece->getRanges(), Piece->getFixits()); + } + } +} + +void ento::createTextPathDiagnosticConsumer( + PathDiagnosticConsumerOptions &&DiagOpts, PathDiagnosticConsumers &C, + const std::string &Prefix, const clang::Preprocessor &PP, + const cross_tu::CrossTranslationUnitContext &CTU) { + C.push_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics())); +} Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -241,7 +241,7 @@ AnalysisDiagClients Value = llvm::StringSwitch(Name) #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \ .Case(CMDFLAG, PD_##NAME) -#include "clang/StaticAnalyzer/Core/Analyses.def" +#include "clang/Analysis/PathDiagnosticConsumers.def" .Default(NUM_ANALYSIS_DIAG_CLIENTS); if (Value == NUM_ANALYSIS_DIAG_CLIENTS) { Diags.Report(diag::err_drv_invalid_value) Index: clang/lib/StaticAnalyzer/Core/CMakeLists.txt =================================================================== --- clang/lib/StaticAnalyzer/Core/CMakeLists.txt +++ clang/lib/StaticAnalyzer/Core/CMakeLists.txt @@ -25,16 +25,13 @@ ExprEngineCallAndReturn.cpp ExprEngineObjC.cpp FunctionSummary.cpp - HTMLDiagnostics.cpp LoopUnrolling.cpp LoopWidening.cpp MemRegion.cpp - PlistDiagnostics.cpp ProgramState.cpp RangeConstraintManager.cpp RangedConstraintManager.cpp RegionStore.cpp - SarifDiagnostics.cpp SimpleConstraintManager.cpp SimpleSValBuilder.cpp SMTConstraintManager.cpp Index: clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp =================================================================== --- clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -13,6 +13,7 @@ #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" #include "ModelInjector.h" #include "clang/Analysis/PathDiagnostic.h" +#include "clang/Analysis/PathDiagnosticConsumers.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -29,7 +30,6 @@ #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" @@ -60,116 +60,6 @@ STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks."); STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function."); -//===----------------------------------------------------------------------===// -// Special PathDiagnosticConsumers. -//===----------------------------------------------------------------------===// - -void ento::createPlistHTMLDiagnosticConsumer( - PathDiagnosticConsumerOptions &&DiagOpts, PathDiagnosticConsumers &C, - const std::string &prefix, const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { - // Duplicate the DiagOpts object into both consumers. - createHTMLDiagnosticConsumer(PathDiagnosticConsumerOptions(DiagOpts), C, - llvm::sys::path::parent_path(prefix), PP, CTU); - createPlistMultiFileDiagnosticConsumer( - PathDiagnosticConsumerOptions(DiagOpts), C, prefix, PP, CTU); -} - -namespace { -class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer { - DiagnosticsEngine &Diag; - bool IncludePath = false, ShouldEmitAsError = false, FixitsAsRemarks = false; - -public: - ClangDiagPathDiagConsumer(PathDiagnosticConsumerOptions &&DiagOpts, - DiagnosticsEngine &Diag) - : Diag(Diag), IncludePath(DiagOpts.ShouldDisplayPathNotes), - ShouldEmitAsError(DiagOpts.ShouldDisplayWarningsAsErrors), - FixitsAsRemarks(DiagOpts.ShouldEmitFixItHintsAsRemarks) {} - ~ClangDiagPathDiagConsumer() override {} - StringRef getName() const override { return "ClangDiags"; } - - bool supportsLogicalOpControlFlow() const override { return true; } - bool supportsCrossFileDiagnostics() const override { return true; } - - PathGenerationScheme getGenerationScheme() const override { - return IncludePath ? Minimal : None; - } - - void FlushDiagnosticsImpl(std::vector &Diags, - FilesMade *filesMade) override { - unsigned WarnID = - ShouldEmitAsError - ? Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0") - : Diag.getCustomDiagID(DiagnosticsEngine::Warning, "%0"); - unsigned NoteID = Diag.getCustomDiagID(DiagnosticsEngine::Note, "%0"); - unsigned RemarkID = Diag.getCustomDiagID(DiagnosticsEngine::Remark, "%0"); - - auto reportPiece = - [&](unsigned ID, SourceLocation Loc, StringRef String, - ArrayRef Ranges, ArrayRef Fixits) { - if (!FixitsAsRemarks) { - Diag.Report(Loc, ID) << String << Ranges << Fixits; - } else { - Diag.Report(Loc, ID) << String << Ranges; - for (const FixItHint &Hint : Fixits) { - SourceManager &SM = Diag.getSourceManager(); - llvm::SmallString<128> Str; - llvm::raw_svector_ostream OS(Str); - // FIXME: Add support for InsertFromRange and - // BeforePreviousInsertion. - assert(!Hint.InsertFromRange.isValid() && "Not implemented yet!"); - assert(!Hint.BeforePreviousInsertions && "Not implemented yet!"); - OS << SM.getSpellingColumnNumber(Hint.RemoveRange.getBegin()) - << "-" << SM.getSpellingColumnNumber(Hint.RemoveRange.getEnd()) - << ": '" << Hint.CodeToInsert << "'"; - Diag.Report(Loc, RemarkID) << OS.str(); - } - } - }; - - for (std::vector::iterator I = Diags.begin(), - E = Diags.end(); - I != E; ++I) { - const PathDiagnostic *PD = *I; - reportPiece(WarnID, PD->getLocation().asLocation(), - PD->getShortDescription(), PD->path.back()->getRanges(), - PD->path.back()->getFixits()); - - // First, add extra notes, even if paths should not be included. - for (const auto &Piece : PD->path) { - if (!isa(Piece.get())) - continue; - - reportPiece(NoteID, Piece->getLocation().asLocation(), - Piece->getString(), Piece->getRanges(), Piece->getFixits()); - } - - if (!IncludePath) - continue; - - // Then, add the path notes if necessary. - PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true); - for (const auto &Piece : FlatPath) { - if (isa(Piece.get())) - continue; - - reportPiece(NoteID, Piece->getLocation().asLocation(), - Piece->getString(), Piece->getRanges(), Piece->getFixits()); - } - } - } -}; -} // end anonymous namespace - -void ento::createTextPathDiagnosticConsumer( - PathDiagnosticConsumerOptions &&DiagOpts, PathDiagnosticConsumers &C, - const std::string &Prefix, const clang::Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { - C.push_back( - new ClangDiagPathDiagConsumer(std::move(DiagOpts), PP.getDiagnostics())); -} - //===----------------------------------------------------------------------===// // AnalysisConsumer declaration. //===----------------------------------------------------------------------===// @@ -272,7 +162,7 @@ case PD_##NAME: \ CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU); \ break; -#include "clang/StaticAnalyzer/Core/Analyses.def" +#include "clang/Analysis/PathDiagnosticConsumers.def" } } }