clang  15.0.0git
PartialDiagnostic.h
Go to the documentation of this file.
1 //===- PartialDiagnostic.h - Diagnostic "closures" --------------*- 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 /// \file
10 /// Implements a partial diagnostic that can be emitted anwyhere
11 /// in a DiagnosticBuilder stream.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
16 #define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
17 
18 #include "clang/Basic/Diagnostic.h"
19 #include "clang/Basic/LLVM.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
23 #include <cassert>
24 #include <cstdint>
25 #include <string>
26 #include <type_traits>
27 #include <utility>
28 
29 namespace clang {
30 
32 private:
33  // NOTE: Sema assumes that PartialDiagnostic is location-invariant
34  // in the sense that its bits can be safely memcpy'ed and destructed
35  // in the new location.
36 
37  /// The diagnostic ID.
38  mutable unsigned DiagID = 0;
39 public:
40  struct NullDiagnostic {};
41 
42  /// Create a null partial diagnostic, which cannot carry a payload,
43  /// and only exists to be swapped with a real partial diagnostic.
45 
46  PartialDiagnostic(unsigned DiagID, DiagStorageAllocator &Allocator_)
47  : StreamingDiagnostic(Allocator_), DiagID(DiagID) {}
48 
50  : StreamingDiagnostic(), DiagID(Other.DiagID) {
51  Allocator = Other.Allocator;
52  if (Other.DiagStorage) {
54  *DiagStorage = *Other.DiagStorage;
55  }
56  }
57 
58  template <typename T> const PartialDiagnostic &operator<<(const T &V) const {
59  const StreamingDiagnostic &DB = *this;
60  DB << V;
61  return *this;
62  }
63 
64  // It is necessary to limit this to rvalue reference to avoid calling this
65  // function with a bitfield lvalue argument since non-const reference to
66  // bitfield is not allowed.
67  template <typename T, typename = typename std::enable_if<
68  !std::is_lvalue_reference<T>::value>::type>
69  const PartialDiagnostic &operator<<(T &&V) const {
70  const StreamingDiagnostic &DB = *this;
71  DB << std::move(V);
72  return *this;
73  }
74 
75  PartialDiagnostic(PartialDiagnostic &&Other) : DiagID(Other.DiagID) {
76  Allocator = Other.Allocator;
77  DiagStorage = Other.DiagStorage;
78  Other.DiagStorage = nullptr;
79  }
80 
82  DiagnosticStorage *DiagStorage_)
83  : DiagID(Other.DiagID) {
84  Allocator = reinterpret_cast<DiagStorageAllocator *>(~uintptr_t(0));
85  DiagStorage = DiagStorage_;
86  if (Other.DiagStorage)
87  *this->DiagStorage = *Other.DiagStorage;
88  }
89 
91  : DiagID(Other.getID()) {
92  Allocator = &Allocator_;
93  // Copy arguments.
94  for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
96  AddString(Other.getArgStdStr(I));
97  else
98  AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I));
99  }
100 
101  // Copy source ranges.
102  for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I)
103  AddSourceRange(Other.getRange(I));
104 
105  // Copy fix-its.
106  for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I)
107  AddFixItHint(Other.getFixItHint(I));
108  }
109 
111  DiagID = Other.DiagID;
112  if (Other.DiagStorage) {
113  if (!DiagStorage)
115 
116  *DiagStorage = *Other.DiagStorage;
117  } else {
118  freeStorage();
119  }
120 
121  return *this;
122  }
123 
125  freeStorage();
126 
127  DiagID = Other.DiagID;
128  DiagStorage = Other.DiagStorage;
129  Allocator = Other.Allocator;
130 
131  Other.DiagStorage = nullptr;
132  return *this;
133  }
134 
136  std::swap(DiagID, PD.DiagID);
137  std::swap(DiagStorage, PD.DiagStorage);
138  std::swap(Allocator, PD.Allocator);
139  }
140 
141  unsigned getDiagID() const { return DiagID; }
142  void setDiagID(unsigned ID) { DiagID = ID; }
143 
144  void Emit(const DiagnosticBuilder &DB) const {
145  if (!DiagStorage)
146  return;
147 
148  // Add all arguments.
149  for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
153  else
156  }
157 
158  // Add all ranges.
159  for (const CharSourceRange &Range : DiagStorage->DiagRanges)
160  DB.AddSourceRange(Range);
161 
162  // Add all fix-its.
163  for (const FixItHint &Fix : DiagStorage->FixItHints)
164  DB.AddFixItHint(Fix);
165  }
166 
168  SmallVectorImpl<char> &Buf) const {
169  // FIXME: It should be possible to render a diagnostic to a string without
170  // messing with the state of the diagnostics engine.
171  DiagnosticBuilder DB(Diags.Report(getDiagID()));
172  Emit(DB);
173  Diagnostic(&Diags).FormatDiagnostic(Buf);
174  DB.Clear();
175  Diags.Clear();
176  }
177 
178  /// Clear out this partial diagnostic, giving it a new diagnostic ID
179  /// and removing all of its arguments, ranges, and fix-it hints.
180  void Reset(unsigned DiagID = 0) {
181  this->DiagID = DiagID;
182  freeStorage();
183  }
184 
185  bool hasStorage() const { return DiagStorage != nullptr; }
186 
187  /// Retrieve the string argument at the given index.
188  StringRef getStringArg(unsigned I) {
189  assert(DiagStorage && "No diagnostic storage?");
190  assert(I < DiagStorage->NumDiagArgs && "Not enough diagnostic args");
191  assert(DiagStorage->DiagArgumentsKind[I]
192  == DiagnosticsEngine::ak_std_string && "Not a string arg");
193  return DiagStorage->DiagArgumentsStr[I];
194  }
195 };
196 
198  const PartialDiagnostic &PD) {
199  PD.Emit(DB);
200  return DB;
201 }
202 
203 /// A partial diagnostic along with the source location where this
204 /// diagnostic occurs.
205 using PartialDiagnosticAt = std::pair<SourceLocation, PartialDiagnostic>;
206 
207 } // namespace clang
208 
209 #endif // LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
clang::Diagnostic::getNumFixItHints
unsigned getNumFixItHints() const
Definition: Diagnostic.h:1655
clang::PartialDiagnostic::operator=
PartialDiagnostic & operator=(PartialDiagnostic &&Other)
Definition: PartialDiagnostic.h:124
clang::PartialDiagnostic::hasStorage
bool hasStorage() const
Definition: PartialDiagnostic.h:185
clang::DiagnosticBuilder
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1265
type
clang::Diagnostic::getArgStdStr
const std::string & getArgStdStr(unsigned Idx) const
Return the provided argument string specified by Idx.
Definition: Diagnostic.h:1591
clang::PartialDiagnostic::NullDiagnostic
Definition: PartialDiagnostic.h:40
clang::DiagnosticStorage::DiagArgumentsKind
unsigned char DiagArgumentsKind[MaxArguments]
Specifies for each argument whether it is in DiagArgumentsStr or in DiagArguments.
Definition: Diagnostic.h:163
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
clang::Diagnostic::getRawArg
uint64_t getRawArg(unsigned Idx) const
Return the specified non-string argument in an opaque form.
Definition: Diagnostic.h:1633
clang::PartialDiagnostic::operator=
PartialDiagnostic & operator=(const PartialDiagnostic &Other)
Definition: PartialDiagnostic.h:110
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(NullDiagnostic)
Create a null partial diagnostic, which cannot carry a payload, and only exists to be swapped with a ...
Definition: PartialDiagnostic.h:44
clang::StreamingDiagnostic::AddTaggedVal
void AddTaggedVal(uint64_t V, DiagnosticsEngine::ArgumentKind Kind) const
Definition: Diagnostic.h:1183
clang::DiagnosticStorage
Definition: Diagnostic.h:148
clang::DiagnosticStorage::DiagRanges
SmallVector< CharSourceRange, 8 > DiagRanges
The list of ranges added to this diagnostic.
Definition: Diagnostic.h:177
clang::FixItHint
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:71
clang::Diagnostic
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1560
clang::PartialDiagnostic::Reset
void Reset(unsigned DiagID=0)
Clear out this partial diagnostic, giving it a new diagnostic ID and removing all of its arguments,...
Definition: PartialDiagnostic.h:180
clang::StreamingDiagnostic::Allocator
DiagStorageAllocator * Allocator
Allocator used to allocate storage for this diagnostic.
Definition: Diagnostic.h:1150
clang::DiagnosticStorage::DiagArgumentsStr
std::string DiagArgumentsStr[MaxArguments]
The values for the various substitution positions that have string arguments.
Definition: Diagnostic.h:174
clang::DiagnosticsEngine::ArgumentKind
ArgumentKind
Definition: Diagnostic.h:204
V
#define V(N, I)
Definition: ASTContext.h:3176
clang::PartialDiagnosticAt
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
Definition: PartialDiagnostic.h:205
clang::DiagnosticBuilder::Clear
void Clear() const
Clear out the current diagnostic.
Definition: Diagnostic.h:1297
clang::StreamingDiagnostic::DiagStorage
DiagnosticStorage * DiagStorage
Definition: Diagnostic.h:1147
clang::StreamingDiagnostic
The streaming interface shared between DiagnosticBuilder and PartialDiagnostic.
Definition: Diagnostic.h:1109
clang::DiagnosticsEngine::Clear
void Clear()
Clear out the current diagnostic.
Definition: Diagnostic.h:976
Diagnostic.h
clang::Diagnostic::getNumArgs
unsigned getNumArgs() const
Definition: Diagnostic.h:1575
uintptr_t
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
Definition: opencl-c-base.h:138
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(unsigned DiagID, DiagStorageAllocator &Allocator_)
Definition: PartialDiagnostic.h:46
clang::operator<<
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
Definition: ASTContext.cpp:12296
clang::PartialDiagnostic::operator<<
const PartialDiagnostic & operator<<(const T &V) const
Definition: PartialDiagnostic.h:58
SourceLocation.h
clang::PartialDiagnostic::EmitToString
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
Definition: PartialDiagnostic.h:167
clang::PartialDiagnostic::Emit
void Emit(const DiagnosticBuilder &DB) const
Definition: PartialDiagnostic.h:144
clang::PartialDiagnostic::operator<<
const PartialDiagnostic & operator<<(T &&V) const
Definition: PartialDiagnostic.h:69
clang::Diagnostic::getFixItHint
const FixItHint & getFixItHint(unsigned Idx) const
Definition: Diagnostic.h:1659
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(const Diagnostic &Other, DiagStorageAllocator &Allocator_)
Definition: PartialDiagnostic.h:90
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(PartialDiagnostic &&Other)
Definition: PartialDiagnostic.h:75
clang::StreamingDiagnostic::AddString
void AddString(StringRef V) const
Definition: Diagnostic.h:1193
clang::CharSourceRange
Represents a character-granular source range.
Definition: SourceLocation.h:253
LLVM.h
clang::StreamingDiagnostic::getStorage
DiagnosticStorage * getStorage() const
Retrieve storage for this particular diagnostic.
Definition: Diagnostic.h:1154
clang::StreamingDiagnostic::freeStorage
void freeStorage()
Definition: Diagnostic.h:1163
clang::Diagnostic::getArgKind
DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const
Return the kind of the specified index.
Definition: Diagnostic.h:1583
clang::PartialDiagnostic::setDiagID
void setDiagID(unsigned ID)
Definition: PartialDiagnostic.h:142
clang::PartialDiagnostic::getDiagID
unsigned getDiagID() const
Definition: PartialDiagnostic.h:141
clang::PartialDiagnostic
Definition: PartialDiagnostic.h:31
clang::PartialDiagnostic::swap
void swap(PartialDiagnostic &PD)
Definition: PartialDiagnostic.h:135
clang::Builtin::ID
ID
Definition: Builtins.h:49
clang
Definition: CalledOnceCheck.h:17
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(const PartialDiagnostic &Other)
Definition: PartialDiagnostic.h:49
clang::DiagnosticStorage::NumDiagArgs
unsigned char NumDiagArgs
The number of entries in Arguments.
Definition: Diagnostic.h:159
clang::Diagnostic::getRange
const CharSourceRange & getRange(unsigned Idx) const
Definition: Diagnostic.h:1645
clang::StreamingDiagnostic::AddFixItHint
void AddFixItHint(const FixItHint &Hint) const
Definition: Diagnostic.h:1211
clang::DiagnosticStorage::DiagArgumentsVal
uint64_t DiagArgumentsVal[MaxArguments]
The values for the various substitution positions.
Definition: Diagnostic.h:170
llvm::SmallVectorImpl< char >
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(const PartialDiagnostic &Other, DiagnosticStorage *DiagStorage_)
Definition: PartialDiagnostic.h:81
clang::PartialDiagnostic::getStringArg
StringRef getStringArg(unsigned I)
Retrieve the string argument at the given index.
Definition: PartialDiagnostic.h:188
clang::Diagnostic::FormatDiagnostic
void FormatDiagnostic(SmallVectorImpl< char > &OutStr) const
Format this diagnostic into a string, substituting the formal arguments into the %0 slots.
Definition: Diagnostic.cpp:792
clang::DiagnosticsEngine::ak_std_string
@ ak_std_string
std::string
Definition: Diagnostic.h:206
clang::DiagnosticStorage::FixItHints
SmallVector< FixItHint, 6 > FixItHints
If valid, provides a hint with some code to insert, remove, or modify at a particular position.
Definition: Diagnostic.h:181
clang::StreamingDiagnostic::DiagStorageAllocator
An allocator for DiagnosticStorage objects, which uses a small cache to objects, used to reduce mallo...
Definition: Diagnostic.h:1113
clang::StreamingDiagnostic::AddSourceRange
void AddSourceRange(const CharSourceRange &R) const
Definition: Diagnostic.h:1204
clang::Diagnostic::getNumRanges
unsigned getNumRanges() const
Return the number of source ranges associated with this diagnostic.
Definition: Diagnostic.h:1640
clang::DiagnosticsEngine::Report
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1536