File indexing completed on 2026-05-10 08:36:27
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_CLANG_AST_ABSTRACTBASICWRITER_H
0010 #define LLVM_CLANG_AST_ABSTRACTBASICWRITER_H
0011
0012 #include "clang/AST/ASTContext.h"
0013 #include "clang/AST/DeclTemplate.h"
0014 #include <optional>
0015
0016 namespace clang {
0017 namespace serialization {
0018
0019 template <class T>
0020 inline std::optional<T> makeOptionalFromNullable(const T &value) {
0021 return (value.isNull() ? std::optional<T>() : std::optional<T>(value));
0022 }
0023
0024 template <class T> inline std::optional<T *> makeOptionalFromPointer(T *value) {
0025 return (value ? std::optional<T *>(value) : std::optional<T *>());
0026 }
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 #include "clang/AST/AbstractBasicWriter.inc"
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119 template <class Impl>
0120 class DataStreamBasicWriter : public BasicWriterBase<Impl> {
0121 protected:
0122 using BasicWriterBase<Impl>::asImpl;
0123 DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase<Impl>(ctx) {}
0124
0125 public:
0126
0127
0128 Impl &find(const char *propertyName) {
0129 return asImpl();
0130 }
0131
0132
0133
0134 Impl &writeObject() { return asImpl(); }
0135
0136 template <class T>
0137 void writeEnum(T value) {
0138 asImpl().writeUInt32(uint32_t(value));
0139 }
0140
0141 template <class T>
0142 void writeArray(llvm::ArrayRef<T> array) {
0143 asImpl().writeUInt32(array.size());
0144 for (const T &elt : array) {
0145 WriteDispatcher<T>::write(asImpl(), elt);
0146 }
0147 }
0148
0149 template <class T> void writeOptional(std::optional<T> value) {
0150 WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
0151 }
0152
0153 void writeAPSInt(const llvm::APSInt &value) {
0154 asImpl().writeBool(value.isUnsigned());
0155 asImpl().writeAPInt(value);
0156 }
0157
0158 void writeAPInt(const llvm::APInt &value) {
0159 asImpl().writeUInt32(value.getBitWidth());
0160 const uint64_t *words = value.getRawData();
0161 for (size_t i = 0, e = value.getNumWords(); i != e; ++i)
0162 asImpl().writeUInt64(words[i]);
0163 }
0164
0165 void writeFixedPointSemantics(const llvm::FixedPointSemantics &sema) {
0166 asImpl().writeUInt32(sema.getWidth());
0167 asImpl().writeUInt32(sema.getScale());
0168 asImpl().writeUInt32(sema.isSigned() | sema.isSaturated() << 1 |
0169 sema.hasUnsignedPadding() << 2);
0170 }
0171
0172 void writeLValuePathSerializationHelper(
0173 APValue::LValuePathSerializationHelper lvaluePath) {
0174 ArrayRef<APValue::LValuePathEntry> path = lvaluePath.Path;
0175 QualType elemTy = lvaluePath.getType();
0176 asImpl().writeQualType(elemTy);
0177 asImpl().writeUInt32(path.size());
0178 auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
0179 for (auto elem : path) {
0180 if (elemTy->getAs<RecordType>()) {
0181 asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
0182 const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
0183 if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
0184 asImpl().writeDeclRef(recordDecl);
0185 elemTy = ctx.getRecordType(recordDecl);
0186 } else {
0187 const auto *valueDecl = cast<ValueDecl>(baseOrMember);
0188 asImpl().writeDeclRef(valueDecl);
0189 elemTy = valueDecl->getType();
0190 }
0191 } else {
0192 asImpl().writeUInt32(elem.getAsArrayIndex());
0193 elemTy = ctx.getAsArrayType(elemTy)->getElementType();
0194 }
0195 }
0196 }
0197
0198 void writeQualifiers(Qualifiers value) {
0199 static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t),
0200 "update this if the value size changes");
0201 asImpl().writeUInt64(value.getAsOpaqueValue());
0202 }
0203
0204 void writeExceptionSpecInfo(
0205 const FunctionProtoType::ExceptionSpecInfo &esi) {
0206 asImpl().writeUInt32(uint32_t(esi.Type));
0207 if (esi.Type == EST_Dynamic) {
0208 asImpl().writeArray(esi.Exceptions);
0209 } else if (isComputedNoexcept(esi.Type)) {
0210 asImpl().writeExprRef(esi.NoexceptExpr);
0211 } else if (esi.Type == EST_Uninstantiated) {
0212 asImpl().writeDeclRef(esi.SourceDecl);
0213 asImpl().writeDeclRef(esi.SourceTemplate);
0214 } else if (esi.Type == EST_Unevaluated) {
0215 asImpl().writeDeclRef(esi.SourceDecl);
0216 }
0217 }
0218
0219 void writeExtParameterInfo(FunctionProtoType::ExtParameterInfo epi) {
0220 static_assert(sizeof(epi.getOpaqueValue()) <= sizeof(uint32_t),
0221 "opaque value doesn't fit into uint32_t");
0222 asImpl().writeUInt32(epi.getOpaqueValue());
0223 }
0224
0225 void writeFunctionEffect(FunctionEffect E) {
0226 asImpl().writeUInt32(E.toOpaqueInt32());
0227 }
0228
0229 void writeEffectConditionExpr(EffectConditionExpr CE) {
0230 asImpl().writeExprRef(CE.getCondition());
0231 }
0232
0233 void writeNestedNameSpecifier(NestedNameSpecifier *NNS) {
0234
0235
0236 SmallVector<NestedNameSpecifier *, 8> nestedNames;
0237
0238
0239 while (NNS) {
0240 nestedNames.push_back(NNS);
0241 NNS = NNS->getPrefix();
0242 }
0243
0244 asImpl().writeUInt32(nestedNames.size());
0245 while (!nestedNames.empty()) {
0246 NNS = nestedNames.pop_back_val();
0247 NestedNameSpecifier::SpecifierKind kind = NNS->getKind();
0248 asImpl().writeNestedNameSpecifierKind(kind);
0249 switch (kind) {
0250 case NestedNameSpecifier::Identifier:
0251 asImpl().writeIdentifier(NNS->getAsIdentifier());
0252 continue;
0253
0254 case NestedNameSpecifier::Namespace:
0255 asImpl().writeNamespaceDeclRef(NNS->getAsNamespace());
0256 continue;
0257
0258 case NestedNameSpecifier::NamespaceAlias:
0259 asImpl().writeNamespaceAliasDeclRef(NNS->getAsNamespaceAlias());
0260 continue;
0261
0262 case NestedNameSpecifier::TypeSpec:
0263 case NestedNameSpecifier::TypeSpecWithTemplate:
0264 asImpl().writeQualType(QualType(NNS->getAsType(), 0));
0265 continue;
0266
0267 case NestedNameSpecifier::Global:
0268
0269 continue;
0270
0271 case NestedNameSpecifier::Super:
0272 asImpl().writeDeclRef(NNS->getAsRecordDecl());
0273 continue;
0274 }
0275 llvm_unreachable("bad nested name specifier kind");
0276 }
0277 }
0278 };
0279
0280 }
0281 }
0282
0283 #endif