Index: clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -21,7 +21,9 @@ namespace clang { class AnalyzerOptions; +class MacroExpansionContext; class Preprocessor; + namespace cross_tu { class CrossTranslationUnitContext; } @@ -35,7 +37,8 @@ void CREATEFN(PathDiagnosticConsumerOptions Diagopts, \ PathDiagnosticConsumers &C, const std::string &Prefix, \ const Preprocessor &PP, \ - const cross_tu::CrossTranslationUnitContext &CTU); + const cross_tu::CrossTranslationUnitContext &CTU, \ + const MacroExpansionContext &MacroExpansions); #include "clang/StaticAnalyzer/Core/Analyses.def" } // end 'ento' namespace Index: clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -10,11 +10,12 @@ // //===----------------------------------------------------------------------===// -#include "clang/Analysis/IssueHash.h" -#include "clang/Analysis/PathDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/Stmt.h" +#include "clang/Analysis/IssueHash.h" +#include "clang/Analysis/MacroExpansionContext.h" +#include "clang/Analysis/PathDiagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" @@ -135,14 +136,16 @@ void ento::createHTMLDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &OutputDir, const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { // FIXME: HTML is currently our default output type, but if the output // directory isn't specified, it acts like if it was in the minimal text // output mode. This doesn't make much sense, we should have the minimal text // as our default. In the case of backward compatibility concerns, this could // be preserved with -analyzer-config-compatibility-mode=true. - createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU); + createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU, + MacroExpansions); // TODO: Emit an error here. if (OutputDir.empty()) @@ -154,8 +157,10 @@ void ento::createHTMLSingleFileDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &OutputDir, const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { - createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU); + const cross_tu::CrossTranslationUnitContext &CTU, + const clang::MacroExpansionContext &MacroExpansions) { + createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU, + MacroExpansions); // TODO: Emit an error here. if (OutputDir.empty()) @@ -167,23 +172,29 @@ void ento::createPlistHTMLDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &prefix, const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { createHTMLDiagnosticConsumer( - DiagOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP, - CTU); - createPlistMultiFileDiagnosticConsumer(DiagOpts, C, prefix, PP, CTU); + DiagOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP, CTU, + MacroExpansions); + createPlistMultiFileDiagnosticConsumer(DiagOpts, C, prefix, PP, CTU, + MacroExpansions); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, prefix, PP, - CTU); + CTU, MacroExpansions); } void ento::createSarifHTMLDiagnosticConsumer( - PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, + PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &sarif_file, const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { - createHTMLDiagnosticConsumer(DiagOpts, C, std::string(llvm::sys::path::parent_path(sarif_file)), PP, CTU); - createSarifDiagnosticConsumer(DiagOpts, C, sarif_file, PP, CTU); - createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, sarif_file, PP, - CTU); + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { + createHTMLDiagnosticConsumer( + DiagOpts, C, std::string(llvm::sys::path::parent_path(sarif_file)), PP, + CTU, MacroExpansions); + createSarifDiagnosticConsumer(DiagOpts, C, sarif_file, PP, CTU, + MacroExpansions); + createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, sarif_file, + PP, CTU, MacroExpansions); } //===----------------------------------------------------------------------===// Index: clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/IssueHash.h" +#include "clang/Analysis/MacroExpansionContext.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/PlistSupport.h" @@ -43,6 +44,7 @@ const std::string OutputFile; const Preprocessor &PP; const cross_tu::CrossTranslationUnitContext &CTU; + const MacroExpansionContext &MacroExpansions; const bool SupportsCrossFileDiagnostics; void printBugPath(llvm::raw_ostream &o, const FIDMap &FM, @@ -52,6 +54,7 @@ PlistDiagnostics(PathDiagnosticConsumerOptions DiagOpts, const std::string &OutputFile, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions, bool supportsMultipleFiles); ~PlistDiagnostics() override {} @@ -80,14 +83,14 @@ const FIDMap& FM; const Preprocessor &PP; const cross_tu::CrossTranslationUnitContext &CTU; + const MacroExpansionContext &MacroExpansions; llvm::SmallVector MacroPieces; public: - PlistPrinter(const FIDMap& FM, - const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) - : FM(FM), PP(PP), CTU(CTU) { - } + PlistPrinter(const FIDMap &FM, const Preprocessor &PP, + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) + : FM(FM), PP(PP), CTU(CTU), MacroExpansions(MacroExpansions) {} void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) { ReportPiece(o, P, /*indent*/ 4, /*depth*/ 0, /*includeControlFlow*/ true); @@ -522,8 +525,9 @@ PlistDiagnostics::PlistDiagnostics( PathDiagnosticConsumerOptions DiagOpts, const std::string &output, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, - bool supportsMultipleFiles) + const MacroExpansionContext &MacroExpansions, bool supportsMultipleFiles) : DiagOpts(std::move(DiagOpts)), OutputFile(output), PP(PP), CTU(CTU), + MacroExpansions(MacroExpansions), SupportsCrossFileDiagnostics(supportsMultipleFiles) { // FIXME: Will be used by a later planned change. (void)this->CTU; @@ -532,36 +536,40 @@ void ento::createPlistDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &OutputFile, const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { // TODO: Emit an error here. if (OutputFile.empty()) return; C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU, + MacroExpansions, /*supportsMultipleFiles=*/false)); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, - PP, CTU); + PP, CTU, MacroExpansions); } void ento::createPlistMultiFileDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &OutputFile, const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { // TODO: Emit an error here. if (OutputFile.empty()) return; C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU, + MacroExpansions, /*supportsMultipleFiles=*/true)); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, - PP, CTU); + PP, CTU, MacroExpansions); } void PlistDiagnostics::printBugPath(llvm::raw_ostream &o, const FIDMap &FM, const PathPieces &Path) { - PlistPrinter Printer(FM, PP, CTU); + PlistPrinter Printer(FM, PP, CTU, MacroExpansions); assert(std::is_partitioned(Path.begin(), Path.end(), [](const PathDiagnosticPieceRef &E) { return E->getKind() == PathDiagnosticPiece::Note; Index: clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp +++ clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Analysis/MacroExpansionContext.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/Version.h" @@ -48,7 +49,8 @@ void ento::createSarifDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &Output, const Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { // TODO: Emit an error here. if (Output.empty()) @@ -56,7 +58,7 @@ C.push_back(new SarifDiagnostics(Output, PP.getLangOpts())); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP, - CTU); + CTU, MacroExpansions); } static StringRef getFileName(const FileEntry &FE) { Index: clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp +++ clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Analysis/MacroExpansionContext.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" @@ -138,8 +139,9 @@ void ento::createTextPathDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, - const std::string &Prefix, const clang::Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { + const std::string &Prefix, const Preprocessor &PP, + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(), PP.getLangOpts(), /*ShouldDisplayPathNotes=*/true)); @@ -147,8 +149,9 @@ void ento::createTextMinimalPathDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, - const std::string &Prefix, const clang::Preprocessor &PP, - const cross_tu::CrossTranslationUnitContext &CTU) { + const std::string &Prefix, const Preprocessor &PP, + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(), PP.getLangOpts(), /*ShouldDisplayPathNotes=*/false)); Index: clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp =================================================================== --- clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -20,6 +20,7 @@ #include "clang/Analysis/CFG.h" #include "clang/Analysis/CallGraph.h" #include "clang/Analysis/CodeInjector.h" +#include "clang/Analysis/MacroExpansionContext.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/CrossTU/CrossTranslationUnit.h" @@ -98,6 +99,8 @@ /// working with a PCH file. SetOfDecls LocalTUDecls; + MacroExpansionContext MacroExpansions; + // Set of PathDiagnosticConsumers. Owned by AnalysisManager. PathDiagnosticConsumers PathConsumers; @@ -122,7 +125,8 @@ CodeInjector *injector) : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr), PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)), - Plugins(plugins), Injector(injector), CTU(CI) { + Plugins(plugins), Injector(injector), CTU(CI), + MacroExpansions(CI.getLangOpts()) { DigestAnalyzerOptions(); if (Opts->PrintStats || Opts->ShouldSerializeStats) { AnalyzerTimers = std::make_unique( @@ -136,6 +140,9 @@ *AnalyzerTimers); llvm::EnableStatistics(/* PrintOnExit= */ false); } + + if (Opts->ShouldDisplayMacroExpansions) + MacroExpansions.registerForPreprocessor(PP); } ~AnalysisConsumer() override { @@ -150,7 +157,8 @@ break; #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \ case PD_##NAME: \ - CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU); \ + CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU, \ + MacroExpansions); \ break; #include "clang/StaticAnalyzer/Core/Analyses.def" default: