1 | //===-- ASTResultSynthesizer.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 | #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTRESULTSYNTHESIZER_H |
10 | #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTRESULTSYNTHESIZER_H |
11 | |
12 | #include "lldb/Target/Target.h" |
13 | #include "clang/Sema/SemaConsumer.h" |
14 | |
15 | namespace clang { |
16 | class CompoundStmt; |
17 | class DeclContext; |
18 | class NamedDecl; |
19 | class ObjCMethodDecl; |
20 | class TypeDecl; |
21 | } // namespace clang |
22 | |
23 | namespace lldb_private { |
24 | |
25 | /// \class ASTResultSynthesizer ASTResultSynthesizer.h |
26 | /// "lldb/Expression/ASTResultSynthesizer.h" Adds a result variable |
27 | /// declaration to the ASTs for an expression. |
28 | /// |
29 | /// Users expect the expression "i + 3" to return a result, even if a result |
30 | /// variable wasn't specifically declared. To fulfil this requirement, LLDB |
31 | /// adds a result variable to the expression, transforming it to "int |
32 | /// $__lldb_expr_result = i + 3." The IR transformers ensure that the |
33 | /// resulting variable is mapped to the right piece of memory. |
34 | /// ASTResultSynthesizer's job is to add the variable and its initialization |
35 | /// to the ASTs for the expression, and it does so by acting as a SemaConsumer |
36 | /// for Clang. |
37 | class ASTResultSynthesizer : public clang::SemaConsumer { |
38 | public: |
39 | /// Constructor |
40 | /// |
41 | /// \param[in] passthrough |
42 | /// Since the ASTs must typically go through to the Clang code generator |
43 | /// in order to produce LLVM IR, this SemaConsumer must allow them to |
44 | /// pass to the next step in the chain after processing. Passthrough is |
45 | /// the next ASTConsumer, or NULL if none is required. |
46 | /// |
47 | /// \param[in] top_level |
48 | /// If true, register all top-level Decls and don't try to handle the |
49 | /// main function. |
50 | /// |
51 | /// \param[in] target |
52 | /// The target, which contains the persistent variable store and the |
53 | /// AST importer. |
54 | ASTResultSynthesizer(clang::ASTConsumer *passthrough, bool top_level, |
55 | Target &target); |
56 | |
57 | /// Destructor |
58 | ~ASTResultSynthesizer() override; |
59 | |
60 | /// Link this consumer with a particular AST context |
61 | /// |
62 | /// \param[in] Context |
63 | /// This AST context will be used for types and identifiers, and also |
64 | /// forwarded to the passthrough consumer, if one exists. |
65 | void Initialize(clang::ASTContext &Context) override; |
66 | |
67 | /// Examine a list of Decls to find the function $__lldb_expr and transform |
68 | /// its code |
69 | /// |
70 | /// \param[in] D |
71 | /// The list of Decls to search. These may contain LinkageSpecDecls, |
72 | /// which need to be searched recursively. That job falls to |
73 | /// TransformTopLevelDecl. |
74 | bool HandleTopLevelDecl(clang::DeclGroupRef D) override; |
75 | |
76 | /// Passthrough stub |
77 | void HandleTranslationUnit(clang::ASTContext &Ctx) override; |
78 | |
79 | /// Passthrough stub |
80 | void HandleTagDeclDefinition(clang::TagDecl *D) override; |
81 | |
82 | /// Passthrough stub |
83 | void CompleteTentativeDefinition(clang::VarDecl *D) override; |
84 | |
85 | /// Passthrough stub |
86 | void HandleVTable(clang::CXXRecordDecl *RD) override; |
87 | |
88 | /// Passthrough stub |
89 | void PrintStats() override; |
90 | |
91 | /// Set the Sema object to use when performing transforms, and pass it on |
92 | /// |
93 | /// \param[in] S |
94 | /// The Sema to use. Because Sema isn't externally visible, this class |
95 | /// casts it to an Action for actual use. |
96 | void InitializeSema(clang::Sema &S) override; |
97 | |
98 | /// Reset the Sema to NULL now that transformations are done |
99 | void ForgetSema() override; |
100 | |
101 | /// The parse has succeeded, so record its persistent decls |
102 | void CommitPersistentDecls(); |
103 | |
104 | private: |
105 | /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing as |
106 | /// necessary through LinkageSpecDecls, and calling SynthesizeResult on |
107 | /// anything that was found |
108 | /// |
109 | /// \param[in] D |
110 | /// The Decl to hunt. |
111 | void TransformTopLevelDecl(clang::Decl *D); |
112 | |
113 | /// Process an Objective-C method and produce the result variable and |
114 | /// initialization |
115 | /// |
116 | /// \param[in] MethodDecl |
117 | /// The method to process. |
118 | bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl); |
119 | |
120 | /// Process a function and produce the result variable and initialization |
121 | /// |
122 | /// \param[in] FunDecl |
123 | /// The function to process. |
124 | bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl); |
125 | |
126 | /// Process a function body and produce the result variable and |
127 | /// initialization |
128 | /// |
129 | /// \param[in] Body |
130 | /// The body of the function. |
131 | /// |
132 | /// \param[in] DC |
133 | /// The DeclContext of the function, into which the result variable |
134 | /// is inserted. |
135 | bool SynthesizeBodyResult(clang::CompoundStmt *Body, clang::DeclContext *DC); |
136 | |
137 | /// Given a DeclContext for a function or method, find all types declared in |
138 | /// the context and record any persistent types found. |
139 | /// |
140 | /// \param[in] FunDeclCtx |
141 | /// The context for the function to process. |
142 | void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); |
143 | |
144 | /// Given a TypeDecl, if it declares a type whose name starts with a dollar |
145 | /// sign, register it as a pointer type in the target's scratch AST context. |
146 | void MaybeRecordPersistentType(clang::TypeDecl *D); |
147 | |
148 | /// Given a NamedDecl, register it as a pointer type in the target's scratch |
149 | /// AST context. |
150 | void RecordPersistentDecl(clang::NamedDecl *D); |
151 | |
152 | clang::ASTContext |
153 | *m_ast_context; ///< The AST context to use for identifiers and types. |
154 | clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for |
155 | ///passthrough. NULL if it's a |
156 | ///SemaConsumer. |
157 | clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, |
158 | ///for passthrough. NULL if it's an |
159 | ///ASTConsumer. |
160 | |
161 | std::vector<clang::NamedDecl *> m_decls; ///< Persistent declarations to |
162 | ///register assuming the expression |
163 | ///succeeds. |
164 | |
165 | Target &m_target; ///< The target, which contains the persistent variable |
166 | ///store and the |
167 | clang::Sema *m_sema; ///< The Sema to use. |
168 | bool m_top_level; |
169 | }; |
170 | |
171 | } // namespace lldb_private |
172 | |
173 | #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTRESULTSYNTHESIZER_H |
174 | |