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