clang  19.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,
68  typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>>
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) {
95  if (Other.getArgKind(I) == DiagnosticsEngine::ak_std_string)
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.
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
#define V(N, I)
Definition: ASTContext.h:3299
static char ID
Definition: Arena.cpp:183
Defines the Diagnostic-related interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
SourceRange Range
Definition: SemaObjC.cpp:754
Defines the clang::SourceLocation class and associated facilities.
Represents a character-granular source range.
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1277
void Clear() const
Clear out the current diagnostic.
Definition: Diagnostic.h:1309
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1577
void FormatDiagnostic(SmallVectorImpl< char > &OutStr) const
Format this diagnostic into a string, substituting the formal arguments into the %0 slots.
Definition: Diagnostic.cpp:791
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:193
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1553
void Clear()
Clear out the current diagnostic.
Definition: Diagnostic.h:988
@ ak_std_string
std::string
Definition: Diagnostic.h:207
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:72
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
PartialDiagnostic(const PartialDiagnostic &Other, DiagnosticStorage *DiagStorage_)
const PartialDiagnostic & operator<<(T &&V) const
PartialDiagnostic & operator=(PartialDiagnostic &&Other)
PartialDiagnostic(const PartialDiagnostic &Other)
PartialDiagnostic(const Diagnostic &Other, DiagStorageAllocator &Allocator_)
StringRef getStringArg(unsigned I)
Retrieve the string argument at the given index.
void Emit(const DiagnosticBuilder &DB) const
void setDiagID(unsigned ID)
PartialDiagnostic(unsigned DiagID, DiagStorageAllocator &Allocator_)
void Reset(unsigned DiagID=0)
Clear out this partial diagnostic, giving it a new diagnostic ID and removing all of its arguments,...
PartialDiagnostic & operator=(const PartialDiagnostic &Other)
const PartialDiagnostic & operator<<(const T &V) const
void swap(PartialDiagnostic &PD)
PartialDiagnostic(NullDiagnostic)
Create a null partial diagnostic, which cannot carry a payload, and only exists to be swapped with a ...
PartialDiagnostic(PartialDiagnostic &&Other)
An allocator for DiagnosticStorage objects, which uses a small cache to objects, used to reduce mallo...
Definition: Diagnostic.h:1125
The streaming interface shared between DiagnosticBuilder and PartialDiagnostic.
Definition: Diagnostic.h:1121
DiagStorageAllocator * Allocator
Allocator used to allocate storage for this diagnostic.
Definition: Diagnostic.h:1162
DiagnosticStorage * getStorage() const
Retrieve storage for this particular diagnostic.
Definition: Diagnostic.h:1166
DiagnosticStorage * DiagStorage
Definition: Diagnostic.h:1159
void AddString(StringRef V) const
Definition: Diagnostic.h:1205
void AddTaggedVal(uint64_t V, DiagnosticsEngine::ArgumentKind Kind) const
Definition: Diagnostic.h:1195
void AddSourceRange(const CharSourceRange &R) const
Definition: Diagnostic.h:1216
void AddFixItHint(const FixItHint &Hint) const
Definition: Diagnostic.h:1223
static unsigned getID(const CFGBlock &B)
The JSON file list parser is used to communicate input to InstallAPI.
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
const FunctionProtoType * T
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
@ Other
Other implicit parameter.
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
unsigned char DiagArgumentsKind[MaxArguments]
Specifies for each argument whether it is in DiagArgumentsStr or in DiagArguments.
Definition: Diagnostic.h:164
SmallVector< CharSourceRange, 8 > DiagRanges
The list of ranges added to this diagnostic.
Definition: Diagnostic.h:178
unsigned char NumDiagArgs
The number of entries in Arguments.
Definition: Diagnostic.h:160
SmallVector< FixItHint, 6 > FixItHints
If valid, provides a hint with some code to insert, remove, or modify at a particular position.
Definition: Diagnostic.h:182
std::string DiagArgumentsStr[MaxArguments]
The values for the various substitution positions that have string arguments.
Definition: Diagnostic.h:175
uint64_t DiagArgumentsVal[MaxArguments]
The values for the various substitution positions.
Definition: Diagnostic.h:171