File indexing completed on 2026-05-10 08:36:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
0016 #define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
0017
0018 #include "clang/Basic/Diagnostic.h"
0019 #include "clang/Basic/LLVM.h"
0020 #include "clang/Basic/SourceLocation.h"
0021 #include "llvm/ADT/SmallVector.h"
0022 #include "llvm/ADT/StringRef.h"
0023 #include <cassert>
0024 #include <cstdint>
0025 #include <string>
0026 #include <type_traits>
0027 #include <utility>
0028
0029 namespace clang {
0030
0031 class PartialDiagnostic : public StreamingDiagnostic {
0032 private:
0033
0034
0035
0036
0037
0038 mutable unsigned DiagID = 0;
0039 public:
0040 struct NullDiagnostic {};
0041
0042
0043
0044 PartialDiagnostic(NullDiagnostic) {}
0045
0046 PartialDiagnostic(unsigned DiagID, DiagStorageAllocator &Allocator_)
0047 : StreamingDiagnostic(Allocator_), DiagID(DiagID) {}
0048
0049 PartialDiagnostic(const PartialDiagnostic &Other)
0050 : StreamingDiagnostic(), DiagID(Other.DiagID) {
0051 Allocator = Other.Allocator;
0052 if (Other.DiagStorage) {
0053 DiagStorage = getStorage();
0054 *DiagStorage = *Other.DiagStorage;
0055 }
0056 }
0057
0058 template <typename T> const PartialDiagnostic &operator<<(const T &V) const {
0059 const StreamingDiagnostic &DB = *this;
0060 DB << V;
0061 return *this;
0062 }
0063
0064
0065
0066
0067 template <typename T,
0068 typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>>
0069 const PartialDiagnostic &operator<<(T &&V) const {
0070 const StreamingDiagnostic &DB = *this;
0071 DB << std::move(V);
0072 return *this;
0073 }
0074
0075 PartialDiagnostic(PartialDiagnostic &&Other) : DiagID(Other.DiagID) {
0076 Allocator = Other.Allocator;
0077 DiagStorage = Other.DiagStorage;
0078 Other.DiagStorage = nullptr;
0079 }
0080
0081 PartialDiagnostic(const PartialDiagnostic &Other,
0082 DiagnosticStorage *DiagStorage_)
0083 : DiagID(Other.DiagID) {
0084 Allocator = reinterpret_cast<DiagStorageAllocator *>(~uintptr_t(0));
0085 DiagStorage = DiagStorage_;
0086 if (Other.DiagStorage)
0087 *this->DiagStorage = *Other.DiagStorage;
0088 }
0089
0090 PartialDiagnostic(const Diagnostic &Other, DiagStorageAllocator &Allocator_)
0091 : DiagID(Other.getID()) {
0092 Allocator = &Allocator_;
0093
0094 for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
0095 if (Other.getArgKind(I) == DiagnosticsEngine::ak_std_string)
0096 AddString(Other.getArgStdStr(I));
0097 else
0098 AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I));
0099 }
0100
0101
0102 for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I)
0103 AddSourceRange(Other.getRange(I));
0104
0105
0106 for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I)
0107 AddFixItHint(Other.getFixItHint(I));
0108 }
0109
0110 PartialDiagnostic &operator=(const PartialDiagnostic &Other) {
0111 DiagID = Other.DiagID;
0112 if (Other.DiagStorage) {
0113 if (!DiagStorage)
0114 DiagStorage = getStorage();
0115
0116 *DiagStorage = *Other.DiagStorage;
0117 } else {
0118 freeStorage();
0119 }
0120
0121 return *this;
0122 }
0123
0124 PartialDiagnostic &operator=(PartialDiagnostic &&Other) {
0125 freeStorage();
0126
0127 DiagID = Other.DiagID;
0128 DiagStorage = Other.DiagStorage;
0129 Allocator = Other.Allocator;
0130
0131 Other.DiagStorage = nullptr;
0132 return *this;
0133 }
0134
0135 void swap(PartialDiagnostic &PD) {
0136 std::swap(DiagID, PD.DiagID);
0137 std::swap(DiagStorage, PD.DiagStorage);
0138 std::swap(Allocator, PD.Allocator);
0139 }
0140
0141 unsigned getDiagID() const { return DiagID; }
0142 void setDiagID(unsigned ID) { DiagID = ID; }
0143
0144 void Emit(const DiagnosticBuilder &DB) const {
0145 if (!DiagStorage)
0146 return;
0147
0148
0149 for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
0150 if ((DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]
0151 == DiagnosticsEngine::ak_std_string)
0152 DB.AddString(DiagStorage->DiagArgumentsStr[i]);
0153 else
0154 DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
0155 (DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
0156 }
0157
0158
0159 for (const CharSourceRange &Range : DiagStorage->DiagRanges)
0160 DB.AddSourceRange(Range);
0161
0162
0163 for (const FixItHint &Fix : DiagStorage->FixItHints)
0164 DB.AddFixItHint(Fix);
0165 }
0166
0167 void EmitToString(DiagnosticsEngine &Diags,
0168 SmallVectorImpl<char> &Buf) const {
0169 DiagnosticBuilder DB(Diags.Report(getDiagID()));
0170 Emit(DB);
0171 Diagnostic(&Diags, DB).FormatDiagnostic(Buf);
0172 DB.Clear();
0173 }
0174
0175
0176
0177 void Reset(unsigned DiagID = 0) {
0178 this->DiagID = DiagID;
0179 freeStorage();
0180 }
0181
0182 bool hasStorage() const { return DiagStorage != nullptr; }
0183
0184
0185 StringRef getStringArg(unsigned I) {
0186 assert(DiagStorage && "No diagnostic storage?");
0187 assert(I < DiagStorage->NumDiagArgs && "Not enough diagnostic args");
0188 assert(DiagStorage->DiagArgumentsKind[I]
0189 == DiagnosticsEngine::ak_std_string && "Not a string arg");
0190 return DiagStorage->DiagArgumentsStr[I];
0191 }
0192 };
0193
0194 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
0195 const PartialDiagnostic &PD) {
0196 PD.Emit(DB);
0197 return DB;
0198 }
0199
0200
0201
0202 using PartialDiagnosticAt = std::pair<SourceLocation, PartialDiagnostic>;
0203
0204 }
0205
0206 #endif