diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 2ef98e17cf9c0..4c9c619f2487a 100644 --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +#include "PlistDiagnostics.h" +#include "SarifDiagnostics.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/Stmt.h" @@ -169,6 +171,21 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ArrowMap &Indices) { } // namespace +/// Creates and registers an HTML diagnostic consumer, without any additional +/// text consumer. +static void createHTMLDiagnosticConsumerImpl( + PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, + const std::string &OutputDir, const Preprocessor &PP, + bool SupportMultipleFiles) { + + // TODO: Emit an error here. + if (OutputDir.empty()) + return; + + C.emplace_back(std::make_unique( + std::move(DiagOpts), OutputDir, PP, SupportMultipleFiles)); +} + void ento::createHTMLDiagnosticConsumer( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &OutputDir, const Preprocessor &PP, @@ -183,12 +200,8 @@ void ento::createHTMLDiagnosticConsumer( createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU, MacroExpansions); - // TODO: Emit an error here. - if (OutputDir.empty()) - return; - - C.emplace_back(std::make_unique(std::move(DiagOpts), - OutputDir, PP, true)); + createHTMLDiagnosticConsumerImpl(DiagOpts, C, OutputDir, PP, + /*SupportMultipleFiles=*/true); } void ento::createHTMLSingleFileDiagnosticConsumer( @@ -199,12 +212,8 @@ void ento::createHTMLSingleFileDiagnosticConsumer( createTextMinimalPathDiagnosticConsumer(DiagOpts, C, OutputDir, PP, CTU, MacroExpansions); - // TODO: Emit an error here. - if (OutputDir.empty()) - return; - - C.emplace_back(std::make_unique(std::move(DiagOpts), - OutputDir, PP, false)); + createHTMLDiagnosticConsumerImpl(DiagOpts, C, OutputDir, PP, + /*SupportMultipleFiles=*/false); } void ento::createPlistHTMLDiagnosticConsumer( @@ -212,11 +221,10 @@ void ento::createPlistHTMLDiagnosticConsumer( const std::string &prefix, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, const MacroExpansionContext &MacroExpansions) { - createHTMLDiagnosticConsumer( - DiagOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP, CTU, - MacroExpansions); - createPlistMultiFileDiagnosticConsumer(DiagOpts, C, prefix, PP, CTU, - MacroExpansions); + createHTMLDiagnosticConsumerImpl( + DiagOpts, C, std::string(llvm::sys::path::parent_path(prefix)), PP, true); + createPlistDiagnosticConsumerImpl(DiagOpts, C, prefix, PP, CTU, + MacroExpansions, true); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, prefix, PP, CTU, MacroExpansions); } @@ -226,11 +234,11 @@ void ento::createSarifHTMLDiagnosticConsumer( const std::string &sarif_file, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, const MacroExpansionContext &MacroExpansions) { - createHTMLDiagnosticConsumer( + createHTMLDiagnosticConsumerImpl( DiagOpts, C, std::string(llvm::sys::path::parent_path(sarif_file)), PP, - CTU, MacroExpansions); - createSarifDiagnosticConsumer(DiagOpts, C, sarif_file, PP, CTU, - MacroExpansions); + true); + createSarifDiagnosticConsumerImpl(DiagOpts, C, sarif_file, PP); + createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, sarif_file, PP, CTU, MacroExpansions); } diff --git a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp index 771d09e19f178..f4b08e265f9e7 100644 --- a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "PlistDiagnostics.h" #include "clang/Analysis/IssueHash.h" #include "clang/Analysis/MacroExpansionContext.h" #include "clang/Analysis/PathDiagnostic.h" @@ -528,19 +529,31 @@ PlistDiagnostics::PlistDiagnostics( (void)this->CTU; } -void ento::createPlistDiagnosticConsumer( +/// Creates and registers a Plist diagnostic consumer, without any additional +/// text consumer. +void ento::createPlistDiagnosticConsumerImpl( PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &OutputFile, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, - const MacroExpansionContext &MacroExpansions) { + const MacroExpansionContext &MacroExpansions, bool SupportsMultipleFiles) { // TODO: Emit an error here. if (OutputFile.empty()) return; C.push_back(std::make_unique( - DiagOpts, OutputFile, PP, CTU, MacroExpansions, - /*supportsMultipleFiles=*/false)); + DiagOpts, OutputFile, PP, CTU, MacroExpansions, SupportsMultipleFiles)); +} + +void ento::createPlistDiagnosticConsumer( + PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, + const std::string &OutputFile, const Preprocessor &PP, + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions) { + + createPlistDiagnosticConsumerImpl(DiagOpts, C, OutputFile, PP, CTU, + MacroExpansions, + /*SupportsMultipleFiles=*/false); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, PP, CTU, MacroExpansions); } @@ -551,13 +564,10 @@ void ento::createPlistMultiFileDiagnosticConsumer( const cross_tu::CrossTranslationUnitContext &CTU, const MacroExpansionContext &MacroExpansions) { - // TODO: Emit an error here. - if (OutputFile.empty()) - return; + createPlistDiagnosticConsumerImpl(DiagOpts, C, OutputFile, PP, CTU, + MacroExpansions, + /*SupportsMultipleFiles=*/true); - C.push_back(std::make_unique( - DiagOpts, OutputFile, PP, CTU, MacroExpansions, - /*supportsMultipleFiles=*/true)); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, PP, CTU, MacroExpansions); } diff --git a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.h b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.h new file mode 100644 index 0000000000000..d4ec998ad7d2d --- /dev/null +++ b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.h @@ -0,0 +1,27 @@ +//==- PlistDiagnostics.h - Plist Diagnostics for Paths -------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CORE_PLISTDIAGNOSTICS_H +#define LLVM_CLANG_LIB_STATICANALYZER_CORE_PLISTDIAGNOSTICS_H + +#include "clang/CrossTU/CrossTranslationUnit.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" +#include + +namespace clang::ento { + +void createPlistDiagnosticConsumerImpl( + PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, + const std::string &Output, const Preprocessor &PP, + const cross_tu::CrossTranslationUnitContext &CTU, + const MacroExpansionContext &MacroExpansions, bool SupportsMultipleFiles); + +} // namespace clang::ento + +#endif diff --git a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp index 94b2f486ab7d4..d2c46cf00ac80 100644 --- a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "SarifDiagnostics.h" #include "clang/Analysis/MacroExpansionContext.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Basic/Sarif.h" @@ -54,14 +55,24 @@ void ento::createSarifDiagnosticConsumer( const cross_tu::CrossTranslationUnitContext &CTU, const MacroExpansionContext &MacroExpansions) { + createSarifDiagnosticConsumerImpl(DiagOpts, C, Output, PP); + + createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP, + CTU, MacroExpansions); +} + +/// Creates and registers a SARIF diagnostic consumer, without any additional +/// text consumer. +void ento::createSarifDiagnosticConsumerImpl( + PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, + const std::string &Output, const Preprocessor &PP) { + // TODO: Emit an error here. if (Output.empty()) return; C.push_back(std::make_unique(Output, PP.getLangOpts(), PP.getSourceManager())); - createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP, - CTU, MacroExpansions); } static StringRef getRuleDescription(StringRef CheckName) { diff --git a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.h b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.h new file mode 100644 index 0000000000000..533ee99191926 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.h @@ -0,0 +1,25 @@ +//==- SarifDiagnostics.h - SARIF Diagnostics for Paths -------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CORE_SARIFDIAGNOSTICS_H +#define LLVM_CLANG_LIB_STATICANALYZER_CORE_SARIFDIAGNOSTICS_H + +#include "clang/Lex/Preprocessor.h" +#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" +#include + +namespace clang::ento { + +void createSarifDiagnosticConsumerImpl(PathDiagnosticConsumerOptions DiagOpts, + PathDiagnosticConsumers &C, + const std::string &Output, + const Preprocessor &PP); + +} // namespace clang::ento + +#endif diff --git a/clang/test/Analysis/diagnostics/Inputs/expected-plists/plist-html.c.plist b/clang/test/Analysis/diagnostics/Inputs/expected-plists/plist-html.c.plist new file mode 100644 index 0000000000000..e12a5a688f648 --- /dev/null +++ b/clang/test/Analysis/diagnostics/Inputs/expected-plists/plist-html.c.plist @@ -0,0 +1,197 @@ + + + kindcontrol + edges + + + start + + + line5 + col5 + file0 + + + line5 + col6 + file0 + + + end + + + line5 + col9 + file0 + + + line5 + col9 + file0 + + + + + + + kindevent + location + + line5 + col9 + file0 + + ranges + + + + line5 + col9 + file0 + + + line5 + col9 + file0 + + + + depth0 + extended_message + Assuming 'p' is null + message + Assuming 'p' is null + + + kindcontrol + edges + + + start + + + line5 + col9 + file0 + + + line5 + col9 + file0 + + + end + + + line8 + col9 + file0 + + + line8 + col14 + file0 + + + + + + + kindcontrol + edges + + + start + + + line8 + col9 + file0 + + + line8 + col14 + file0 + + + end + + + line8 + col16 + file0 + + + line8 + col16 + file0 + + + + + + + kindevent + location + + line8 + col16 + file0 + + ranges + + + + line8 + col17 + file0 + + + line8 + col17 + file0 + + + + depth0 + extended_message + Dereference of null pointer (loaded from variable 'p') + message + Dereference of null pointer (loaded from variable 'p') + + + descriptionDereference of null pointer (loaded from variable 'p') + categoryLogic error + typeDereference of null pointer + check_namecore.NullDereference + + issue_hash_content_of_line_in_context665591022ee1cf653566ea441043d888 + issue_context_kindfunction + issue_contextfoo + issue_hash_function_offset4 + location + + line8 + col16 + file0 + + HTMLDiagnostics_files + + report-665591.html + + ExecutedLines + + 0 + + 4 + 5 + 8 + + + + + files + + + + diff --git a/clang/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif b/clang/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif index 7f9deea304832..e35ab695bb38e 100644 --- a/clang/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif +++ b/clang/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif @@ -4,7 +4,7 @@ { "artifacts": [ { - "length": 1071, + "length": 1152, "location": { "index": 0, }, diff --git a/clang/test/Analysis/diagnostics/plist-html.c b/clang/test/Analysis/diagnostics/plist-html.c new file mode 100644 index 0000000000000..7ee0aa5681d3a --- /dev/null +++ b/clang/test/Analysis/diagnostics/plist-html.c @@ -0,0 +1,10 @@ +// RUN: rm -rf %t && mkdir %t && %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-html %s -o %t/plist-html.c.plist -verify +// RUN: tail -n +11 %t/plist-html.c.plist | %normalize_plist | diff -ub %S/Inputs/expected-plists/plist-html.c.plist - + +int foo(int *p) { + if (p) { + return 0; + } else { + return *p; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}} + } +} diff --git a/clang/test/Analysis/diagnostics/sarif-multi-diagnostic-test.c b/clang/test/Analysis/diagnostics/sarif-multi-diagnostic-test.c index eeafd178628b3..5842574793bce 100644 --- a/clang/test/Analysis/diagnostics/sarif-multi-diagnostic-test.c +++ b/clang/test/Analysis/diagnostics/sarif-multi-diagnostic-test.c @@ -1,8 +1,8 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.taint,debug.TaintTest,unix.Malloc %s -verify -analyzer-output=sarif -o - | %normalize_sarif | diff -U1 -b %S/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif - +// RUN: rm -rf %t && mkdir %t && %clang_analyze_cc1 -analyzer-checker=core,optin.taint,debug.TaintTest,unix.Malloc %s -verify -analyzer-output=sarif-html -o %t%{fs-sep}out.sarif +// RUN: cat %t%{fs-sep}out.sarif | %normalize_sarif | diff -U1 -b %S/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif - #include "../Inputs/system-header-simulator.h" #include "../Inputs/system-header-simulator-for-malloc.h" #define ERR -1 - int atoi(const char *nptr); void f(void) {