clang 20.0.0git
APISetVisitor.h
Go to the documentation of this file.
1//===- ExtractAPI/Serialization/APISetVisitor.h ----------------*- 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/// This file defines the ExtractAPI APISetVisitor interface.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
15#define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
16
18
19namespace clang {
20namespace extractapi {
21
22// A helper macro to implement short-circuiting when recursing. It
23// invokes CALL_EXPR, which must be a method call, on the derived
24// object (s.t. a user of RecursiveASTVisitor can override the method
25// in CALL_EXPR).
26#define TRY_TO(CALL_EXPR) \
27 do { \
28 if (!getDerived()->CALL_EXPR) \
29 return false; \
30 } while (false)
31
32/// The base interface of visitors for API information, the interface and usage
33/// is almost identical to RecurisveASTVistor. This class performs three
34/// distinct tasks:
35/// 1. traverse the APISet (i.e. go to every record);
36/// 2. at a given record, walk up the class hierarchy starting from the record's
37/// dynamic type until APIRecord is reached.
38/// 3. given a (record, class) combination where 'class' is some base class of
39/// the dynamic type of 'record', call a user-overridable function to actually
40/// visit the record.
41///
42/// These tasks are done by three groups of methods, respectively:
43/// 1. traverseRecord(APIRecord *x) does task #1, it is the entry point for
44/// traversing the records starting from x. This method simply forwards to
45/// traverseFoo(Foo *x) where Foo is the dynamic type of *x, which calls
46/// walkUpFromFoo(x) and then recursively visits the child records of x.
47/// 2. walkUpFromFoo(Foo *x) does task #2. It doesn't visit children records of
48/// x, instead it first calls walkUpFromBar(x) where Bar is the direct parent
49/// class of Foo (unless Foo has no parent) and then calls visitFoo(x).
50/// 3. visitFoo(Foo *x) does task #3.
51///
52/// These three method groups are tiered (traverse* > walkUpFrom* >
53/// visit*). A method (e.g. traverse*) may call methods from the same
54/// tier (e.g. other traverse*) or one tier lower (e.g. walkUpFrom*).
55/// It may not call methods from a higher tier.
56///
57/// Note that since walkUpFromFoo() calls walkUpFromBar() (where Bar
58/// is Foo's super class) before calling visitFoo(), the result is
59/// that the visit*() methods for a given record are called in the
60/// top-down order (e.g. for a record of type ObjCInstancePropertyRecord, the
61/// order will be visitRecord(), visitObjCPropertyRecord(), and then
62/// visitObjCInstancePropertyRecord()).
63///
64/// This scheme guarantees that all visit*() calls for the same record
65/// are grouped together. In other words, visit*() methods for different
66/// records are never interleaved.
67///
68/// Clients of this visitor should subclass the visitor (providing
69/// themselves as the template argument, using the curiously recurring
70/// template pattern) and override any of the traverse*, walkUpFrom*,
71/// and visit* methods for records where the visitor should customize
72/// behavior. Most users only need to override visit*. Advanced
73/// users may override traverse* and walkUpFrom* to implement custom
74/// traversal strategies. Returning false from one of these overridden
75/// functions will abort the entire traversal.
76template <typename Derived> class APISetVisitor {
77public:
79 for (const APIRecord *TLR : API.getTopLevelRecords()) {
81 }
82 return true;
83 }
84
88 return true;
89 }
90 bool visitAPIRecord(const APIRecord *Record) { return true; }
91
92#define GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
93 bool traverse##CLASS(const CLASS *Record) { \
94 TRY_TO(walkUpFrom##CLASS(Record)); \
95 TRY_TO(traverseRecordContext(dyn_cast<RecordContext>(Record))); \
96 return true; \
97 }
98
99#define GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE) \
100 bool walkUpFrom##CLASS(const CLASS *Record) { \
101 TRY_TO(walkUpFrom##BASE(Record)); \
102 TRY_TO(visit##CLASS(Record)); \
103 return true; \
104 } \
105 bool visit##CLASS(const CLASS *Record) { return true; }
106
107#define CONCRETE_RECORD(CLASS, BASE, KIND) \
108 GENERATE_TRAVERSE_METHOD(CLASS, BASE) \
109 GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
110
111#define ABSTRACT_RECORD(CLASS, BASE) \
112 GENERATE_WALKUP_AND_VISIT_METHODS(CLASS, BASE)
113
114#include "../APIRecords.inc"
115
116#undef GENERATE_WALKUP_AND_VISIT_METHODS
117#undef GENERATE_TRAVERSE_METHOD
118
120
121protected:
122 const APISet &API;
123
124public:
125 APISetVisitor() = delete;
126 APISetVisitor(const APISetVisitor &) = delete;
130
131protected:
133 ~APISetVisitor() = default;
134
135 Derived *getDerived() { return static_cast<Derived *>(this); };
136};
137
138template <typename Derived>
140 const RecordContext *Context) {
141 if (!Context)
142 return true;
143
144 for (auto *Child : Context->records())
145 TRY_TO(traverseAPIRecord(Child));
146
147 return true;
148}
149
150template <typename Derived>
152 switch (Record->getKind()) {
153#define CONCRETE_RECORD(CLASS, BASE, KIND) \
154 case APIRecord::KIND: { \
155 TRY_TO(traverse##CLASS(static_cast<const CLASS *>(Record))); \
156 break; \
157 }
158#include "../APIRecords.inc"
160 TRY_TO(walkUpFromAPIRecord(static_cast<const APIRecord *>(Record)));
161 break;
162 }
163 default:
164 llvm_unreachable("API Record with uninstantiable kind");
165 }
166 return true;
167}
168
169} // namespace extractapi
170} // namespace clang
171
172#endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H
This file defines the APIRecord-based structs and the APISet class.
llvm::MachO::Record Record
Definition: MachO.h:31
#define TRY_TO(CALL_EXPR)
The base interface of visitors for API information, the interface and usage is almost identical to Re...
Definition: APISetVisitor.h:76
bool visitAPIRecord(const APIRecord *Record)
Definition: APISetVisitor.h:90
APISetVisitor & operator=(APISetVisitor &&)=delete
bool traverseRecordContext(const RecordContext *)
APISetVisitor(const APISetVisitor &)=delete
bool walkUpFromAPIRecord(const APIRecord *Record)
Definition: APISetVisitor.h:86
APISetVisitor(const APISet &API)
bool traverseAPIRecord(const APIRecord *Record)
APISetVisitor & operator=(const APISetVisitor &)=delete
APISetVisitor(APISetVisitor &&)=delete
APISet holds the set of API records collected from given inputs.
Definition: API.h:1394
auto getTopLevelRecords() const
Definition: API.h:1423
Base class used for specific record types that have children records this is analogous to the DeclCon...
Definition: API.h:305
The JSON file list parser is used to communicate input to InstallAPI.
The base representation of an API record. Holds common symbol information.
Definition: API.h:184