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