1 //===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "stdlib.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/AST/Decl.h" 13 #include "clang/AST/DeclCXX.h" 14 #include "clang/AST/DeclGroup.h" 15 #include "clang/AST/Expr.h" 16 #include "clang/AST/RecordLayout.h" 17 #include "clang/AST/Stmt.h" 18 #include "clang/Parse/Parser.h" 19 #include "clang/Sema/Sema.h" 20 #include "llvm/Support/Casting.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include "lldb/Core/Log.h" 23 #include "lldb/Expression/ASTStructExtractor.h" 24 25 using namespace llvm; 26 using namespace clang; 27 using namespace lldb_private; 28 29 ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, 30 const char *struct_name, 31 ClangFunction &function) : 32 m_ast_context (NULL), 33 m_passthrough (passthrough), 34 m_passthrough_sema (NULL), 35 m_sema (NULL), 36 m_action (NULL), 37 m_function (function), 38 m_struct_name (struct_name) 39 { 40 if (!m_passthrough) 41 return; 42 43 m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); 44 } 45 46 ASTStructExtractor::~ASTStructExtractor() 47 { 48 } 49 50 void 51 ASTStructExtractor::Initialize(ASTContext &Context) 52 { 53 m_ast_context = &Context; 54 55 if (m_passthrough) 56 m_passthrough->Initialize(Context); 57 } 58 59 void 60 ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) 61 { 62 if (!F->hasBody()) 63 return; 64 65 Stmt *body_stmt = F->getBody(); 66 CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); 67 68 if (!body_compound_stmt) 69 return; // do we have to handle this? 70 71 RecordDecl *struct_decl = NULL; 72 73 StringRef desired_name(m_struct_name.c_str()); 74 75 for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end(); 76 bi != be; 77 ++bi) 78 { 79 Stmt *curr_stmt = *bi; 80 DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); 81 if (!curr_decl_stmt) 82 continue; 83 DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); 84 for (Decl *candidate_decl : decl_group) 85 { 86 RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); 87 if (!candidate_record_decl) 88 continue; 89 if (candidate_record_decl->getName() == desired_name) 90 { 91 struct_decl = candidate_record_decl; 92 break; 93 } 94 } 95 if (struct_decl) 96 break; 97 } 98 99 if (!struct_decl) 100 return; 101 102 const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl)); 103 104 if (!struct_layout) 105 return; 106 107 m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits 108 m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; 109 m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; 110 111 for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); 112 field_index < num_fields; 113 ++field_index) 114 { 115 m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8); 116 } 117 118 m_function.m_struct_valid = true; 119 } 120 121 void 122 ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) 123 { 124 LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); 125 126 if (linkage_spec_decl) 127 { 128 RecordDecl::decl_iterator decl_iterator; 129 130 for (decl_iterator = linkage_spec_decl->decls_begin(); 131 decl_iterator != linkage_spec_decl->decls_end(); 132 ++decl_iterator) 133 { 134 ExtractFromTopLevelDecl(*decl_iterator); 135 } 136 } 137 138 FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); 139 140 if (m_ast_context && 141 function_decl && 142 !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str())) 143 { 144 ExtractFromFunctionDecl(function_decl); 145 } 146 } 147 148 bool 149 ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) 150 { 151 DeclGroupRef::iterator decl_iterator; 152 153 for (decl_iterator = D.begin(); 154 decl_iterator != D.end(); 155 ++decl_iterator) 156 { 157 Decl *decl = *decl_iterator; 158 159 ExtractFromTopLevelDecl(decl); 160 } 161 162 if (m_passthrough) 163 return m_passthrough->HandleTopLevelDecl(D); 164 return true; 165 } 166 167 void 168 ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) 169 { 170 if (m_passthrough) 171 m_passthrough->HandleTranslationUnit(Ctx); 172 } 173 174 void 175 ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) 176 { 177 if (m_passthrough) 178 m_passthrough->HandleTagDeclDefinition(D); 179 } 180 181 void 182 ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) 183 { 184 if (m_passthrough) 185 m_passthrough->CompleteTentativeDefinition(D); 186 } 187 188 void 189 ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) 190 { 191 if (m_passthrough) 192 m_passthrough->HandleVTable(RD, DefinitionRequired); 193 } 194 195 void 196 ASTStructExtractor::PrintStats() 197 { 198 if (m_passthrough) 199 m_passthrough->PrintStats(); 200 } 201 202 void 203 ASTStructExtractor::InitializeSema(Sema &S) 204 { 205 m_sema = &S; 206 m_action = reinterpret_cast<Action*>(m_sema); 207 208 if (m_passthrough_sema) 209 m_passthrough_sema->InitializeSema(S); 210 } 211 212 void 213 ASTStructExtractor::ForgetSema() 214 { 215 m_sema = NULL; 216 m_action = NULL; 217 218 if (m_passthrough_sema) 219 m_passthrough_sema->ForgetSema(); 220 } 221