1 // Copyright (C) 2016 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "ast_processing.h" 16 #include "abi_wrappers.h" 17 18 #include <clang/Lex/Token.h> 19 #include <clang/Tooling/Core/QualTypeNames.h> 20 #include <clang/Index/CodegenNameGenerator.h> 21 22 #include <fstream> 23 #include <iostream> 24 #include <string> 25 26 using abi_wrapper::ABIWrapper; 27 using abi_wrapper::FunctionDeclWrapper; 28 using abi_wrapper::RecordDeclWrapper; 29 using abi_wrapper::EnumDeclWrapper; 30 using abi_wrapper::GlobalVarDeclWrapper; 31 32 HeaderASTVisitor::HeaderASTVisitor( 33 clang::MangleContext *mangle_contextp, 34 clang::ASTContext *ast_contextp, 35 const clang::CompilerInstance *compiler_instance_p, 36 const std::set<std::string> &exported_headers, 37 const clang::Decl *tu_decl, 38 abi_util::IRDumper *ir_dumper, 39 ast_util::ASTCaches *ast_caches) 40 : mangle_contextp_(mangle_contextp), 41 ast_contextp_(ast_contextp), 42 cip_(compiler_instance_p), 43 exported_headers_(exported_headers), 44 tu_decl_(tu_decl), 45 ir_dumper_(ir_dumper), 46 ast_caches_(ast_caches) { } 47 48 bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) { 49 // Skip forward declarations, dependent records. Also skip anonymous records 50 // as they will be traversed through record fields. 51 if (!decl->isThisDeclarationADefinition() || 52 decl->getTypeForDecl()->isDependentType() || 53 decl->isAnonymousStructOrUnion() || 54 !decl->hasNameForLinkage() || 55 !decl->isExternallyVisible()) { 56 return true; 57 } 58 RecordDeclWrapper record_decl_wrapper( 59 mangle_contextp_, ast_contextp_, cip_, decl, ir_dumper_, ast_caches_); 60 return record_decl_wrapper.GetRecordDecl(); 61 } 62 63 bool HeaderASTVisitor::VisitEnumDecl(const clang::EnumDecl *decl) { 64 if (!decl->isThisDeclarationADefinition() || 65 decl->getTypeForDecl()->isDependentType() || 66 !decl->hasNameForLinkage()) { 67 return true; 68 } 69 EnumDeclWrapper enum_decl_wrapper( 70 mangle_contextp_, ast_contextp_, cip_, decl, ir_dumper_, ast_caches_); 71 return enum_decl_wrapper.GetEnumDecl(); 72 } 73 74 static bool MutateFunctionWithLinkageName(const abi_util::FunctionIR *function, 75 abi_util::IRDumper *ir_dumper, 76 std::string &linkage_name) { 77 auto added_function = std::make_unique<abi_util::FunctionIR>(); 78 *added_function = *function; 79 added_function->SetLinkerSetKey(linkage_name); 80 return ir_dumper->AddLinkableMessageIR(added_function.get()); 81 } 82 83 static bool AddMangledFunctions(const abi_util::FunctionIR *function, 84 abi_util:: IRDumper *ir_dumper, 85 std::vector<std::string> &manglings) { 86 for (auto &&mangling : manglings) { 87 if (!MutateFunctionWithLinkageName(function, ir_dumper, mangling)) { 88 return false; 89 } 90 } 91 return true; 92 } 93 94 static bool ShouldSkipFunctionDecl(const clang::FunctionDecl *decl) { 95 if (!decl->getDefinition()) { 96 return true; 97 } 98 if (decl->getLinkageAndVisibility().getLinkage() != 99 clang::Linkage::ExternalLinkage) { 100 return true; 101 } 102 if (const clang::CXXMethodDecl *method_decl = 103 llvm::dyn_cast<clang::CXXMethodDecl>(decl)) { 104 if (method_decl->getParent()->getTypeForDecl()->isDependentType()) { 105 return true; 106 } 107 } 108 clang::FunctionDecl::TemplatedKind tkind = decl->getTemplatedKind(); 109 switch (tkind) { 110 case clang::FunctionDecl::TK_NonTemplate: 111 case clang::FunctionDecl::TK_FunctionTemplateSpecialization: 112 case clang::FunctionDecl::TK_MemberSpecialization: 113 return false; 114 default: 115 return true; 116 } 117 } 118 119 bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) { 120 if (ShouldSkipFunctionDecl(decl)) { 121 return true; 122 } 123 FunctionDeclWrapper function_decl_wrapper(mangle_contextp_, ast_contextp_, 124 cip_, decl, ir_dumper_, 125 ast_caches_); 126 auto function_wrapper = function_decl_wrapper.GetFunctionDecl(); 127 // Destructors and Constructors can have more than 1 symbol generated from the 128 // same Decl. 129 clang::index::CodegenNameGenerator cg(*ast_contextp_); 130 std::vector<std::string> manglings = cg.getAllManglings(decl); 131 if (!manglings.empty()) { 132 return AddMangledFunctions(function_wrapper.get(), ir_dumper_, manglings); 133 } 134 std::string linkage_name = 135 ABIWrapper::GetMangledNameDecl(decl, mangle_contextp_); 136 return MutateFunctionWithLinkageName(function_wrapper.get(), ir_dumper_, 137 linkage_name); 138 } 139 140 bool HeaderASTVisitor::VisitVarDecl(const clang::VarDecl *decl) { 141 if(!decl->hasGlobalStorage()|| 142 decl->getType().getTypePtr()->isDependentType()) { 143 // Non global / static variable declarations don't need to be dumped. 144 return true; 145 } 146 GlobalVarDeclWrapper global_var_decl_wrapper(mangle_contextp_, ast_contextp_, 147 cip_, decl, ir_dumper_, 148 ast_caches_); 149 return global_var_decl_wrapper.GetGlobalVarDecl(); 150 } 151 152 static bool AreHeadersExported(const std::set<std::string> &exported_headers) { 153 return !exported_headers.empty(); 154 } 155 156 // We don't need to recurse into Declarations which are not exported. 157 bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) { 158 if (!decl) { 159 return true; 160 } 161 std::string source_file = ABIWrapper::GetDeclSourceFile(decl, cip_); 162 ast_caches_->decl_to_source_file_cache_.insert( 163 std::make_pair(decl, source_file)); 164 // If no exported headers are specified we assume the whole AST is exported. 165 if ((decl != tu_decl_) && AreHeadersExported(exported_headers_) && 166 (exported_headers_.find(source_file) == exported_headers_.end())) { 167 return true; 168 } 169 // If at all we're looking at the source file's AST decl node, it should be a 170 // function decl node. 171 if ((decl != tu_decl_) && 172 (source_file == ast_caches_->translation_unit_source_) && 173 !decl->isFunctionOrFunctionTemplate()) { 174 return true; 175 } 176 return RecursiveASTVisitor<HeaderASTVisitor>::TraverseDecl(decl); 177 } 178 179 HeaderASTConsumer::HeaderASTConsumer( 180 clang::CompilerInstance *compiler_instancep, 181 const std::string &out_dump_name, 182 std::set<std::string> &exported_headers, 183 abi_util::TextFormatIR text_format) 184 : cip_(compiler_instancep), 185 out_dump_name_(out_dump_name), 186 exported_headers_(exported_headers), 187 text_format_(text_format){ } 188 189 void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) { 190 clang::PrintingPolicy policy(ctx.getPrintingPolicy()); 191 // Suppress 'struct' keyword for C source files while getting QualType string 192 // names to avoid inconsistency between C and C++ (for C++ files, this is true 193 // by default) 194 policy.SuppressTagKeyword = true; 195 ctx.setPrintingPolicy(policy); 196 clang::TranslationUnitDecl *translation_unit = ctx.getTranslationUnitDecl(); 197 std::unique_ptr<clang::MangleContext> mangle_contextp( 198 ctx.createMangleContext()); 199 const std::string &translation_unit_source = 200 ABIWrapper::GetDeclSourceFile(translation_unit, cip_); 201 ast_util::ASTCaches ast_caches(translation_unit_source); 202 if (!exported_headers_.empty()) { 203 exported_headers_.insert(translation_unit_source); 204 } 205 std::unique_ptr<abi_util::IRDumper> ir_dumper = 206 abi_util::IRDumper::CreateIRDumper(text_format_, out_dump_name_); 207 HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_, exported_headers_, 208 translation_unit, ir_dumper.get(), &ast_caches); 209 210 if (!v.TraverseDecl(translation_unit) || !ir_dumper->Dump()) { 211 llvm::errs() << "Serialization to ostream failed\n"; 212 ::exit(1); 213 } 214 } 215