clang  14.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 
31 class DeclContext;
32 class IdentifierInfo;
33 
35 private:
36  // NOTE: Sema assumes that PartialDiagnostic is location-invariant
37  // in the sense that its bits can be safely memcpy'ed and destructed
38  // in the new location.
39 
40  /// The diagnostic ID.
41  mutable unsigned DiagID = 0;
42 public:
43  struct NullDiagnostic {};
44 
45  /// Create a null partial diagnostic, which cannot carry a payload,
46  /// and only exists to be swapped with a real partial diagnostic.
48 
49  PartialDiagnostic(unsigned DiagID, DiagStorageAllocator &Allocator_)
50  : StreamingDiagnostic(Allocator_), DiagID(DiagID) {}
51 
53  : StreamingDiagnostic(), DiagID(Other.DiagID) {
54  Allocator = Other.Allocator;
55  if (Other.DiagStorage) {
57  *DiagStorage = *Other.DiagStorage;
58  }
59  }
60 
61  template <typename T> const PartialDiagnostic &operator<<(const T &V) const {
62  const StreamingDiagnostic &DB = *this;
63  DB << V;
64  return *this;
65  }
66 
67  // It is necessary to limit this to rvalue reference to avoid calling this
68  // function with a bitfield lvalue argument since non-const reference to
69  // bitfield is not allowed.
70  template <typename T, typename = typename std::enable_if<
71  !std::is_lvalue_reference<T>::value>::type>
72  const PartialDiagnostic &operator<<(T &&V) const {
73  const StreamingDiagnostic &DB = *this;
74  DB << std::move(V);
75  return *this;
76  }
77 
78  PartialDiagnostic(PartialDiagnostic &&Other) : DiagID(Other.DiagID) {
79  Allocator = Other.Allocator;
80  DiagStorage = Other.DiagStorage;
81  Other.DiagStorage = nullptr;
82  }
83 
85  DiagnosticStorage *DiagStorage_)
86  : DiagID(Other.DiagID) {
87  Allocator = reinterpret_cast<DiagStorageAllocator *>(~uintptr_t(0));
88  DiagStorage = DiagStorage_;
89  if (Other.DiagStorage)
90  *this->DiagStorage = *Other.DiagStorage;
91  }
92 
94  : DiagID(Other.getID()) {
95  Allocator = &Allocator_;
96  // Copy arguments.
97  for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
99  AddString(Other.getArgStdStr(I));
100  else
101  AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I));
102  }
103 
104  // Copy source ranges.
105  for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I)
106  AddSourceRange(Other.getRange(I));
107 
108  // Copy fix-its.
109  for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I)
110  AddFixItHint(Other.getFixItHint(I));
111  }
112 
114  DiagID = Other.DiagID;
115  if (Other.DiagStorage) {
116  if (!DiagStorage)
118 
119  *DiagStorage = *Other.DiagStorage;
120  } else {
121  freeStorage();
122  }
123 
124  return *this;
125  }
126 
128  freeStorage();
129 
130  DiagID = Other.DiagID;
131  DiagStorage = Other.DiagStorage;
132  Allocator = Other.Allocator;
133 
134  Other.DiagStorage = nullptr;
135  return *this;
136  }
137 
139  std::swap(DiagID, PD.DiagID);
140  std::swap(DiagStorage, PD.DiagStorage);
141  std::swap(Allocator, PD.Allocator);
142  }
143 
144  unsigned getDiagID() const { return DiagID; }
145  void setDiagID(unsigned ID) { DiagID = ID; }
146 
147  void Emit(const DiagnosticBuilder &DB) const {
148  if (!DiagStorage)
149  return;
150 
151  // Add all arguments.
152  for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
156  else
159  }
160 
161  // Add all ranges.
162  for (const CharSourceRange &Range : DiagStorage->DiagRanges)
163  DB.AddSourceRange(Range);
164 
165  // Add all fix-its.
166  for (const FixItHint &Fix : DiagStorage->FixItHints)
167  DB.AddFixItHint(Fix);
168  }
169 
171  SmallVectorImpl<char> &Buf) const {
172  // FIXME: It should be possible to render a diagnostic to a string without
173  // messing with the state of the diagnostics engine.
174  DiagnosticBuilder DB(Diags.Report(getDiagID()));
175  Emit(DB);
176  Diagnostic(&Diags).FormatDiagnostic(Buf);
177  DB.Clear();
178  Diags.Clear();
179  }
180 
181  /// Clear out this partial diagnostic, giving it a new diagnostic ID
182  /// and removing all of its arguments, ranges, and fix-it hints.
183  void Reset(unsigned DiagID = 0) {
184  this->DiagID = DiagID;
185  freeStorage();
186  }
187 
188  bool hasStorage() const { return DiagStorage != nullptr; }
189 
190  /// Retrieve the string argument at the given index.
191  StringRef getStringArg(unsigned I) {
192  assert(DiagStorage && "No diagnostic storage?");
193  assert(I < DiagStorage->NumDiagArgs && "Not enough diagnostic args");
194  assert(DiagStorage->DiagArgumentsKind[I]
195  == DiagnosticsEngine::ak_std_string && "Not a string arg");
196  return DiagStorage->DiagArgumentsStr[I];
197  }
198 };
199 
201  const PartialDiagnostic &PD) {
202  PD.Emit(DB);
203  return DB;
204 }
205 
206 /// A partial diagnostic along with the source location where this
207 /// diagnostic occurs.
208 using PartialDiagnosticAt = std::pair<SourceLocation, PartialDiagnostic>;
209 
210 } // namespace clang
211 
212 #endif // LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
clang::Diagnostic::getNumFixItHints
unsigned getNumFixItHints() const
Definition: Diagnostic.h:1642
clang::PartialDiagnostic::operator=
PartialDiagnostic & operator=(PartialDiagnostic &&Other)
Definition: PartialDiagnostic.h:127
clang::PartialDiagnostic::hasStorage
bool hasStorage() const
Definition: PartialDiagnostic.h:188
clang::DiagnosticBuilder
A little helper class used to produce diagnostics.
Definition: Diagnostic.h:1264
type
clang::Diagnostic::getArgStdStr
const std::string & getArgStdStr(unsigned Idx) const
Return the provided argument string specified by Idx.
Definition: Diagnostic.h:1578
clang::PartialDiagnostic::NullDiagnostic
Definition: PartialDiagnostic.h:43
clang::DiagnosticStorage::DiagArgumentsKind
unsigned char DiagArgumentsKind[MaxArguments]
Specifies for each argument whether it is in DiagArgumentsStr or in DiagArguments.
Definition: Diagnostic.h:162
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:191
clang::Diagnostic::getRawArg
uint64_t getRawArg(unsigned Idx) const
Return the specified non-string argument in an opaque form.
Definition: Diagnostic.h:1620
clang::PartialDiagnostic::operator=
PartialDiagnostic & operator=(const PartialDiagnostic &Other)
Definition: PartialDiagnostic.h:113
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:47
clang::StreamingDiagnostic::AddTaggedVal
void AddTaggedVal(uint64_t V, DiagnosticsEngine::ArgumentKind Kind) const
Definition: Diagnostic.h:1182
clang::DiagnosticStorage
Definition: Diagnostic.h:147
clang::DiagnosticStorage::DiagRanges
SmallVector< CharSourceRange, 8 > DiagRanges
The list of ranges added to this diagnostic.
Definition: Diagnostic.h:176
clang::FixItHint
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:70
clang::Diagnostic
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1547
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:183
clang::StreamingDiagnostic::Allocator
DiagStorageAllocator * Allocator
Allocator used to allocate storage for this diagnostic.
Definition: Diagnostic.h:1149
clang::DiagnosticStorage::DiagArgumentsStr
std::string DiagArgumentsStr[MaxArguments]
The values for the various substitution positions that have string arguments.
Definition: Diagnostic.h:173
clang::DiagnosticsEngine::ArgumentKind
ArgumentKind
Definition: Diagnostic.h:203
V
#define V(N, I)
Definition: ASTContext.h:3127
clang::PartialDiagnosticAt
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
Definition: PartialDiagnostic.h:208
clang::DiagnosticBuilder::Clear
void Clear() const
Clear out the current diagnostic.
Definition: Diagnostic.h:1296
clang::StreamingDiagnostic::DiagStorage
DiagnosticStorage * DiagStorage
Definition: Diagnostic.h:1146
clang::StreamingDiagnostic
The streaming interface shared between DiagnosticBuilder and PartialDiagnostic.
Definition: Diagnostic.h:1108
clang::DiagnosticsEngine::Clear
void Clear()
Clear out the current diagnostic.
Definition: Diagnostic.h:975
Diagnostic.h
clang::Diagnostic::getNumArgs
unsigned getNumArgs() const
Definition: Diagnostic.h:1562
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:124
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(unsigned DiagID, DiagStorageAllocator &Allocator_)
Definition: PartialDiagnostic.h:49
clang::operator<<
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
Definition: ASTContext.cpp:11823
clang::PartialDiagnostic::operator<<
const PartialDiagnostic & operator<<(const T &V) const
Definition: PartialDiagnostic.h:61
SourceLocation.h
clang::PartialDiagnostic::EmitToString
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
Definition: PartialDiagnostic.h:170
clang::PartialDiagnostic::Emit
void Emit(const DiagnosticBuilder &DB) const
Definition: PartialDiagnostic.h:147
clang::PartialDiagnostic::operator<<
const PartialDiagnostic & operator<<(T &&V) const
Definition: PartialDiagnostic.h:72
clang::Diagnostic::getFixItHint
const FixItHint & getFixItHint(unsigned Idx) const
Definition: Diagnostic.h:1646
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(const Diagnostic &Other, DiagStorageAllocator &Allocator_)
Definition: PartialDiagnostic.h:93
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(PartialDiagnostic &&Other)
Definition: PartialDiagnostic.h:78
clang::StreamingDiagnostic::AddString
void AddString(StringRef V) const
Definition: Diagnostic.h:1192
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:1153
clang::StreamingDiagnostic::freeStorage
void freeStorage()
Definition: Diagnostic.h:1162
clang::Diagnostic::getArgKind
DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const
Return the kind of the specified index.
Definition: Diagnostic.h:1570
clang::PartialDiagnostic::setDiagID
void setDiagID(unsigned ID)
Definition: PartialDiagnostic.h:145
clang::PartialDiagnostic::getDiagID
unsigned getDiagID() const
Definition: PartialDiagnostic.h:144
clang::PartialDiagnostic
Definition: PartialDiagnostic.h:34
clang::PartialDiagnostic::swap
void swap(PartialDiagnostic &PD)
Definition: PartialDiagnostic.h:138
clang::Builtin::ID
ID
Definition: Builtins.h:48
clang
Definition: CalledOnceCheck.h:17
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(const PartialDiagnostic &Other)
Definition: PartialDiagnostic.h:52
clang::DiagnosticStorage::NumDiagArgs
unsigned char NumDiagArgs
The number of entries in Arguments.
Definition: Diagnostic.h:158
clang::Diagnostic::getRange
const CharSourceRange & getRange(unsigned Idx) const
Definition: Diagnostic.h:1632
clang::StreamingDiagnostic::AddFixItHint
void AddFixItHint(const FixItHint &Hint) const
Definition: Diagnostic.h:1210
clang::DiagnosticStorage::DiagArgumentsVal
uint64_t DiagArgumentsVal[MaxArguments]
The values for the various substitution positions.
Definition: Diagnostic.h:169
llvm::SmallVectorImpl< char >
clang::PartialDiagnostic::PartialDiagnostic
PartialDiagnostic(const PartialDiagnostic &Other, DiagnosticStorage *DiagStorage_)
Definition: PartialDiagnostic.h:84
clang::PartialDiagnostic::getStringArg
StringRef getStringArg(unsigned I)
Retrieve the string argument at the given index.
Definition: PartialDiagnostic.h:191
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:786
clang::DiagnosticsEngine::ak_std_string
@ ak_std_string
std::string
Definition: Diagnostic.h:205
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:180
clang::StreamingDiagnostic::DiagStorageAllocator
An allocator for DiagnosticStorage objects, which uses a small cache to objects, used to reduce mallo...
Definition: Diagnostic.h:1112
clang::StreamingDiagnostic::AddSourceRange
void AddSourceRange(const CharSourceRange &R) const
Definition: Diagnostic.h:1203
clang::Diagnostic::getNumRanges
unsigned getNumRanges() const
Return the number of source ranges associated with this diagnostic.
Definition: Diagnostic.h:1627
clang::DiagnosticsEngine::Report
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1523