File indexing completed on 2026-05-10 08:36:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
0015 #define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
0016
0017 #include "clang/ExtractAPI/API.h"
0018
0019 namespace clang {
0020 namespace extractapi {
0021
0022
0023
0024
0025
0026 #define TRY_TO(CALL_EXPR) \
0027 do { \
0028 if (!getDerived()->CALL_EXPR) \
0029 return false; \
0030 } while (false)
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 template <typename Derived> class APISetVisitor {
0077 public:
0078 bool traverseAPISet() {
0079 for (const APIRecord *TLR : API.getTopLevelRecords()) {
0080 TRY_TO(traverseAPIRecord(TLR));
0081 }
0082 return true;
0083 }
0084
0085 bool traverseAPIRecord(const APIRecord *Record);
0086 bool walkUpFromAPIRecord(const APIRecord *Record) {
0087 TRY_TO(visitAPIRecord(Record));
0088 return true;
0089 }
0090 bool visitAPIRecord(const APIRecord *Record) { return true; }
0091
0092 #define GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
0093 bool traverse##CLASS(const CLASS *Record) { \
0094 TRY_TO(walkUpFrom##CLASS(Record)); \
0095 TRY_TO(traverseRecordContext(dyn_cast<RecordContext>(Record))); \
0096 return true; \
0097 }
0098
0099 #define GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE) \
0100 bool walkUpFrom##CLASS(const CLASS *Record) { \
0101 TRY_TO(walkUpFrom##BASE(Record)); \
0102 TRY_TO(visit##CLASS(Record)); \
0103 return true; \
0104 } \
0105 bool visit##CLASS(const CLASS *Record) { return true; }
0106
0107 #define CONCRETE_RECORD(CLASS, BASE, KIND) \
0108 GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
0109 GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
0110
0111 #define ABSTRACT_RECORD(CLASS, BASE) \
0112 GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
0113
0114 #include "../APIRecords.inc"
0115
0116 #undef GENERATE_WALKUP_AND_VISIT_METHODS
0117 #undef GENERATE_TRAVERSE_METHOD
0118
0119 bool traverseRecordContext(const RecordContext *);
0120
0121 protected:
0122 const APISet &API;
0123
0124 public:
0125 APISetVisitor() = delete;
0126 APISetVisitor(const APISetVisitor &) = delete;
0127 APISetVisitor(APISetVisitor &&) = delete;
0128 APISetVisitor &operator=(const APISetVisitor &) = delete;
0129 APISetVisitor &operator=(APISetVisitor &&) = delete;
0130
0131 protected:
0132 APISetVisitor(const APISet &API) : API(API) {}
0133 ~APISetVisitor() = default;
0134
0135 Derived *getDerived() { return static_cast<Derived *>(this); };
0136 };
0137
0138 template <typename Derived>
0139 bool APISetVisitor<Derived>::traverseRecordContext(
0140 const RecordContext *Context) {
0141 if (!Context)
0142 return true;
0143
0144 for (auto *Child : Context->records())
0145 TRY_TO(traverseAPIRecord(Child));
0146
0147 return true;
0148 }
0149
0150 template <typename Derived>
0151 bool APISetVisitor<Derived>::traverseAPIRecord(const APIRecord *Record) {
0152 switch (Record->getKind()) {
0153 #define CONCRETE_RECORD(CLASS, BASE, KIND) \
0154 case APIRecord::KIND: { \
0155 TRY_TO(traverse##CLASS(static_cast<const CLASS *>(Record))); \
0156 break; \
0157 }
0158 #include "../APIRecords.inc"
0159 case APIRecord::RK_Unknown: {
0160 TRY_TO(walkUpFromAPIRecord(static_cast<const APIRecord *>(Record)));
0161 break;
0162 }
0163 default:
0164 llvm_unreachable("API Record with uninstantiable kind");
0165 }
0166 return true;
0167 }
0168
0169 }
0170 }
0171
0172 #endif