clang 17.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
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
29namespace clang {
30
32private:
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;
39public:
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.
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.
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");
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.
205using PartialDiagnosticAt = std::pair<SourceLocation, PartialDiagnostic>;
206
207} // namespace clang
208
209#endif // LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
#define V(N, I)
Definition: ASTContext.h:3230
Defines the Diagnostic-related interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
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:1266
void Clear() const
Clear out the current diagnostic.
Definition: Diagnostic.h:1298
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1566
void FormatDiagnostic(SmallVectorImpl< char > &OutStr) const
Format this diagnostic into a string, substituting the formal arguments into the %0 slots.
Definition: Diagnostic.cpp:779
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1542
void Clear()
Clear out the current diagnostic.
Definition: Diagnostic.h:977
@ ak_std_string
std::string
Definition: Diagnostic.h:206
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:71
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
PartialDiagnostic(const PartialDiagnostic &Other, DiagnosticStorage *DiagStorage_)
PartialDiagnostic(const PartialDiagnostic &Other)
const PartialDiagnostic & operator<<(T &&V) const
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_)
PartialDiagnostic & operator=(const PartialDiagnostic &Other)
const PartialDiagnostic & operator<<(const T &V) const
void Reset(unsigned DiagID=0)
Clear out this partial diagnostic, giving it a new diagnostic ID and removing all of its arguments,...
PartialDiagnostic & operator=(PartialDiagnostic &&Other)
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:1114
The streaming interface shared between DiagnosticBuilder and PartialDiagnostic.
Definition: Diagnostic.h:1110
DiagStorageAllocator * Allocator
Allocator used to allocate storage for this diagnostic.
Definition: Diagnostic.h:1151
DiagnosticStorage * DiagStorage
Definition: Diagnostic.h:1148
void AddString(StringRef V) const
Definition: Diagnostic.h:1194
void AddTaggedVal(uint64_t V, DiagnosticsEngine::ArgumentKind Kind) const
Definition: Diagnostic.h:1184
void AddSourceRange(const CharSourceRange &R) const
Definition: Diagnostic.h:1205
DiagnosticStorage * getStorage() const
Retrieve storage for this particular diagnostic.
Definition: Diagnostic.h:1155
void AddFixItHint(const FixItHint &Hint) const
Definition: Diagnostic.h:1212
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
__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:163
SmallVector< CharSourceRange, 8 > DiagRanges
The list of ranges added to this diagnostic.
Definition: Diagnostic.h:177
unsigned char NumDiagArgs
The number of entries in Arguments.
Definition: Diagnostic.h:159
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
std::string DiagArgumentsStr[MaxArguments]
The values for the various substitution positions that have string arguments.
Definition: Diagnostic.h:174
uint64_t DiagArgumentsVal[MaxArguments]
The values for the various substitution positions.
Definition: Diagnostic.h:170