clang  14.0.0git
TextDiagnostics.cpp
Go to the documentation of this file.
1 //===--- TextDiagnostics.cpp - Text Diagnostics for Paths -------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the TextDiagnostics object.
10 //
11 //===----------------------------------------------------------------------===//
12 
16 #include "clang/Basic/Version.h"
18 #include "clang/Frontend/ASTUnit.h"
19 #include "clang/Lex/Preprocessor.h"
24 #include "clang/Tooling/Tooling.h"
25 #include "llvm/ADT/SmallPtrSet.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/Support/Casting.h"
28 
29 using namespace clang;
30 using namespace ento;
31 using namespace tooling;
32 
33 namespace {
34 /// Emitsd minimal diagnostics (report message + notes) for the 'none' output
35 /// type to the standard error, or to to compliment many others. Emits detailed
36 /// diagnostics in textual format for the 'text' output type.
37 class TextDiagnostics : public PathDiagnosticConsumer {
38  PathDiagnosticConsumerOptions DiagOpts;
39  DiagnosticsEngine &DiagEng;
40  const LangOptions &LO;
41  bool ShouldDisplayPathNotes;
42 
43 public:
44  TextDiagnostics(PathDiagnosticConsumerOptions DiagOpts,
45  DiagnosticsEngine &DiagEng, const LangOptions &LO,
46  bool ShouldDisplayPathNotes)
47  : DiagOpts(std::move(DiagOpts)), DiagEng(DiagEng), LO(LO),
48  ShouldDisplayPathNotes(ShouldDisplayPathNotes) {}
49  ~TextDiagnostics() override {}
50 
51  StringRef getName() const override { return "TextDiagnostics"; }
52 
53  bool supportsLogicalOpControlFlow() const override { return true; }
54  bool supportsCrossFileDiagnostics() const override { return true; }
55 
56  PathGenerationScheme getGenerationScheme() const override {
57  return ShouldDisplayPathNotes ? Minimal : None;
58  }
59 
60  void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
61  FilesMade *filesMade) override {
62  unsigned WarnID =
63  DiagOpts.ShouldDisplayWarningsAsErrors
66  unsigned NoteID = DiagEng.getCustomDiagID(DiagnosticsEngine::Note, "%0");
67  SourceManager &SM = DiagEng.getSourceManager();
68 
69  Replacements Repls;
70  auto reportPiece = [&](unsigned ID, FullSourceLoc Loc, StringRef String,
71  ArrayRef<SourceRange> Ranges,
72  ArrayRef<FixItHint> Fixits) {
73  if (!DiagOpts.ShouldApplyFixIts) {
74  DiagEng.Report(Loc, ID) << String << Ranges << Fixits;
75  return;
76  }
77 
78  DiagEng.Report(Loc, ID) << String << Ranges;
79  for (const FixItHint &Hint : Fixits) {
80  Replacement Repl(SM, Hint.RemoveRange, Hint.CodeToInsert);
81 
82  if (llvm::Error Err = Repls.add(Repl)) {
83  llvm::errs() << "Error applying replacement " << Repl.toString()
84  << ": " << Err << "\n";
85  }
86  }
87  };
88 
89  for (std::vector<const PathDiagnostic *>::iterator I = Diags.begin(),
90  E = Diags.end();
91  I != E; ++I) {
92  const PathDiagnostic *PD = *I;
93  std::string WarningMsg = (DiagOpts.ShouldDisplayDiagnosticName
94  ? " [" + PD->getCheckerName() + "]"
95  : "")
96  .str();
97 
98  reportPiece(WarnID, PD->getLocation().asLocation(),
99  (PD->getShortDescription() + WarningMsg).str(),
100  PD->path.back()->getRanges(), PD->path.back()->getFixits());
101 
102  // First, add extra notes, even if paths should not be included.
103  for (const auto &Piece : PD->path) {
104  if (!isa<PathDiagnosticNotePiece>(Piece.get()))
105  continue;
106 
107  reportPiece(NoteID, Piece->getLocation().asLocation(),
108  Piece->getString(), Piece->getRanges(),
109  Piece->getFixits());
110  }
111 
112  if (!ShouldDisplayPathNotes)
113  continue;
114 
115  // Then, add the path notes if necessary.
116  PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true);
117  for (const auto &Piece : FlatPath) {
118  if (isa<PathDiagnosticNotePiece>(Piece.get()))
119  continue;
120 
121  reportPiece(NoteID, Piece->getLocation().asLocation(),
122  Piece->getString(), Piece->getRanges(),
123  Piece->getFixits());
124  }
125  }
126 
127  if (Repls.empty())
128  return;
129 
130  Rewriter Rewrite(SM, LO);
131  if (!applyAllReplacements(Repls, Rewrite)) {
132  llvm::errs() << "An error occured during applying fix-it.\n";
133  }
134 
135  Rewrite.overwriteChangedFiles();
136  }
137 };
138 } // end anonymous namespace
139 
140 void ento::createTextPathDiagnosticConsumer(
141  PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
142  const std::string &Prefix, const Preprocessor &PP,
144  const MacroExpansionContext &MacroExpansions) {
145  C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),
146  PP.getLangOpts(),
147  /*ShouldDisplayPathNotes=*/true));
148 }
149 
150 void ento::createTextMinimalPathDiagnosticConsumer(
151  PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C,
152  const std::string &Prefix, const Preprocessor &PP,
154  const MacroExpansionContext &MacroExpansions) {
155  C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(),
156  PP.getLangOpts(),
157  /*ShouldDisplayPathNotes=*/false));
158 }
AnalyzerOptions.h
clang::FullSourceLoc
A SourceLocation and its associated SourceManager.
Definition: SourceLocation.h:370
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
PathDiagnosticConsumers.h
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:54
clang::TemplateSubstitutionKind::Rewrite
@ Rewrite
We are substituting template parameters for (typically) other template parameters in order to rewrite...
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:191
SourceManager.h
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:626
clang::Preprocessor::getLangOpts
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:960
Preprocessor.h
clang::FixItHint
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:70
clang::XRayInstrKind::None
constexpr XRayInstrMask None
Definition: XRayInstr.h:38
clang::cross_tu::CrossTranslationUnitContext
This class is used for tools that requires cross translation unit capability.
Definition: CrossTranslationUnit.h:125
Version.h
clang::DiagnosticsEngine::Error
@ Error
Definition: Diagnostic.h:199
PathDiagnostic.h
getName
static std::string getName(const CallEvent &Call)
Definition: ReturnValueChecker.cpp:60
MacroExpansionContext.h
Tooling.h
Replacement.h
llvm::ArrayRef
Definition: LLVM.h:34
ASTUnit.h
clang::MacroExpansionContext
MacroExpansionContext tracks the macro expansions processed by the Preprocessor.
Definition: MacroExpansionContext.h:73
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:58
std
Definition: Format.h:4034
clang::DiagnosticsEngine::getCustomDiagID
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition: Diagnostic.h:866
clang::ento::PathDiagnosticConsumers
std::vector< PathDiagnosticConsumer * > PathDiagnosticConsumers
Definition: PathDiagnosticConsumers.h:33
clang::Builtin::ID
ID
Definition: Builtins.h:48
clang
Definition: CalledOnceCheck.h:17
clang::Preprocessor::getDiagnostics
DiagnosticsEngine & getDiagnostics() const
Definition: Preprocessor.h:957
clang::Rewriter
Rewriter - This is the main interface to the rewrite buffers.
Definition: Rewriter.h:32
clang::DiagnosticsEngine::Note
@ Note
Definition: Diagnostic.h:196
Rewriter.h
clang::StructuralEquivalenceKind::Minimal
@ Minimal
clang::DiagnosticsEngine::getSourceManager
SourceManager & getSourceManager() const
Definition: Diagnostic.h:577
clang::tooling::applyAllReplacements
bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite)
Apply all replacements in Replaces to the Rewriter Rewrite.
Definition: Replacement.cpp:567
clang::Preprocessor
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:130
CrossTranslationUnit.h
SM
#define SM(sm)
Definition: Cuda.cpp:78
clang::DiagnosticsEngine::Warning
@ Warning
Definition: Diagnostic.h:198
clang::DiagnosticsEngine::Report
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1523