• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "dumper/ast_processing.h"
16 
17 #include "dumper/abi_wrappers.h"
18 #include "repr/ir_dumper.h"
19 
20 #include <clang/Lex/Token.h>
21 #include <clang/AST/QualTypeNames.h>
22 #include <clang/Index/CodegenNameGenerator.h>
23 
24 #include <fstream>
25 #include <iostream>
26 #include <string>
27 
28 
29 namespace header_checker {
30 namespace dumper {
31 
32 
HeaderASTVisitor(const HeaderCheckerOptions & options,clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const clang::Decl * tu_decl,repr::ModuleIR * module,ASTCaches * ast_caches)33 HeaderASTVisitor::HeaderASTVisitor(
34     const HeaderCheckerOptions &options, clang::MangleContext *mangle_contextp,
35     clang::ASTContext *ast_contextp,
36     const clang::CompilerInstance *compiler_instance_p,
37     const clang::Decl *tu_decl, repr::ModuleIR *module,
38     ASTCaches *ast_caches)
39     : options_(options), mangle_contextp_(mangle_contextp),
40       ast_contextp_(ast_contextp), cip_(compiler_instance_p), tu_decl_(tu_decl),
41       module_(module), ast_caches_(ast_caches) {}
42 
VisitRecordDecl(const clang::RecordDecl * decl)43 bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
44   // Avoid segmentation fault in getASTRecordLayout.
45   if (decl->isInvalidDecl()) {
46     return true;
47   }
48   // Skip forward declarations, dependent records. Also skip anonymous records
49   // as they will be traversed through record fields.
50   if (!decl->isThisDeclarationADefinition() ||
51       decl->getTypeForDecl()->isDependentType() ||
52       decl->isAnonymousStructOrUnion() ||
53       !decl->hasNameForLinkage() ||
54       !decl->isExternallyVisible()) {
55     return true;
56   }
57   RecordDeclWrapper record_decl_wrapper(
58       mangle_contextp_, ast_contextp_, cip_, decl, module_, ast_caches_);
59   return record_decl_wrapper.GetRecordDecl();
60 }
61 
VisitEnumDecl(const clang::EnumDecl * decl)62 bool HeaderASTVisitor::VisitEnumDecl(const clang::EnumDecl *decl) {
63   if (!decl->isThisDeclarationADefinition() ||
64       decl->getTypeForDecl()->isDependentType() ||
65       !decl->hasNameForLinkage()) {
66     return true;
67   }
68   EnumDeclWrapper enum_decl_wrapper(
69       mangle_contextp_, ast_contextp_, cip_, decl, module_, ast_caches_);
70   return enum_decl_wrapper.GetEnumDecl();
71 }
72 
MutateFunctionWithLinkageName(const repr::FunctionIR * function,repr::ModuleIR * module,std::string & linkage_name)73 static bool MutateFunctionWithLinkageName(const repr::FunctionIR *function,
74                                           repr::ModuleIR *module,
75                                           std::string &linkage_name) {
76   auto added_function = std::make_unique<repr::FunctionIR>();
77   *added_function = *function;
78   added_function->SetLinkerSetKey(linkage_name);
79   return module->AddLinkableMessage(*added_function);
80 }
81 
AddMangledFunctions(const repr::FunctionIR * function,repr::ModuleIR * module,std::vector<std::string> & manglings)82 static bool AddMangledFunctions(const repr::FunctionIR *function,
83                                 repr:: ModuleIR *module,
84                                 std::vector<std::string> &manglings) {
85   for (auto &&mangling : manglings) {
86     if (!MutateFunctionWithLinkageName(function, module, mangling)) {
87       return false;
88     }
89   }
90   return true;
91 }
92 
ShouldSkipFunctionDecl(const clang::FunctionDecl * decl)93 bool HeaderASTVisitor::ShouldSkipFunctionDecl(const clang::FunctionDecl *decl) {
94   if (!decl->getDefinition()) {
95     if (!options_.dump_function_declarations_ ||
96         options_.source_file_ != ABIWrapper::GetDeclSourceFile(decl, cip_)) {
97       return true;
98     }
99   }
100   // Skip explicitly deleted functions such as `Foo operator=(Foo) = delete;`.
101   if (decl->isDeleted()) {
102     return true;
103   }
104   if (decl->getLinkageAndVisibility().getLinkage() !=
105       clang::Linkage::ExternalLinkage) {
106     return true;
107   }
108   if (const clang::CXXMethodDecl *method_decl =
109       llvm::dyn_cast<clang::CXXMethodDecl>(decl)) {
110     const clang::CXXRecordDecl *record_decl = method_decl->getParent();
111     // Avoid segmentation fault in getThunkInfo in getAllManglings.
112     if (method_decl->isVirtual() && record_decl->isInvalidDecl()) {
113       return true;
114     }
115     if (record_decl->getTypeForDecl()->isDependentType()) {
116       return true;
117     }
118   }
119   clang::FunctionDecl::TemplatedKind tkind = decl->getTemplatedKind();
120   switch (tkind) {
121     case clang::FunctionDecl::TK_NonTemplate:
122     case clang::FunctionDecl::TK_FunctionTemplateSpecialization:
123     case clang::FunctionDecl::TK_MemberSpecialization:
124       return false;
125     default:
126       return true;
127   }
128 }
129 
VisitFunctionDecl(const clang::FunctionDecl * decl)130 bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) {
131   if (ShouldSkipFunctionDecl(decl)) {
132     return true;
133   }
134   FunctionDeclWrapper function_decl_wrapper(
135       mangle_contextp_, ast_contextp_, cip_, decl, module_, ast_caches_);
136   auto function_wrapper = function_decl_wrapper.GetFunctionDecl();
137   // Destructors and Constructors can have more than 1 symbol generated from the
138   // same Decl.
139   clang::index::CodegenNameGenerator cg(*ast_contextp_);
140   std::vector<std::string> manglings = cg.getAllManglings(decl);
141   if (!manglings.empty()) {
142     return AddMangledFunctions(function_wrapper.get(), module_, manglings);
143   }
144   std::string linkage_name =
145       ABIWrapper::GetMangledNameDecl(decl, mangle_contextp_);
146   return MutateFunctionWithLinkageName(function_wrapper.get(), module_,
147                                        linkage_name);
148 }
149 
VisitVarDecl(const clang::VarDecl * decl)150 bool HeaderASTVisitor::VisitVarDecl(const clang::VarDecl *decl) {
151   if (!decl->hasGlobalStorage() ||
152       decl->getType().getTypePtr()->isDependentType()) {
153     // Non global / static variable declarations don't need to be dumped.
154     return true;
155   }
156   GlobalVarDeclWrapper global_var_decl_wrapper(
157       mangle_contextp_, ast_contextp_, cip_, decl, module_, ast_caches_);
158   return global_var_decl_wrapper.GetGlobalVarDecl();
159 }
160 
AreHeadersExported(const std::set<std::string> & exported_headers)161 static bool AreHeadersExported(const std::set<std::string> &exported_headers) {
162   return !exported_headers.empty();
163 }
164 
165 // We don't need to recurse into Declarations which are not exported.
TraverseDecl(clang::Decl * decl)166 bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) {
167   if (!decl) {
168     return true;
169   }
170   std::string source_file = ABIWrapper::GetDeclSourceFile(decl, cip_);
171   ast_caches_->decl_to_source_file_cache_.insert(
172       std::make_pair(decl, source_file));
173   // If no exported headers are specified we assume the whole AST is exported.
174   const auto &exported_headers = options_.exported_headers_;
175   if ((decl != tu_decl_) && AreHeadersExported(exported_headers) &&
176       (exported_headers.find(source_file) == exported_headers.end())) {
177     return true;
178   }
179   // If at all we're looking at the source file's AST decl node, it should be a
180   // function decl node.
181   if ((decl != tu_decl_) &&
182       (source_file == ast_caches_->translation_unit_source_) &&
183       !decl->isFunctionOrFunctionTemplate()) {
184     return true;
185   }
186   return RecursiveASTVisitor<HeaderASTVisitor>::TraverseDecl(decl);
187 }
188 
HeaderASTConsumer(clang::CompilerInstance * compiler_instancep,HeaderCheckerOptions & options)189 HeaderASTConsumer::HeaderASTConsumer(
190     clang::CompilerInstance *compiler_instancep, HeaderCheckerOptions &options)
191     : cip_(compiler_instancep), options_(options) {}
192 
HandleTranslationUnit(clang::ASTContext & ctx)193 void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
194   clang::PrintingPolicy policy(ctx.getPrintingPolicy());
195   // Suppress 'struct' keyword for C source files while getting QualType string
196   // names to avoid inconsistency between C and C++ (for C++ files, this is true
197   // by default)
198   policy.SuppressTagKeyword = true;
199   ctx.setPrintingPolicy(policy);
200   clang::TranslationUnitDecl *translation_unit = ctx.getTranslationUnitDecl();
201   std::unique_ptr<clang::MangleContext> mangle_contextp(
202       ctx.createMangleContext());
203   const std::string &translation_unit_source =
204       ABIWrapper::GetDeclSourceFile(translation_unit, cip_);
205   ASTCaches ast_caches(translation_unit_source);
206   if (!options_.exported_headers_.empty()) {
207     options_.exported_headers_.insert(translation_unit_source);
208   }
209 
210   std::unique_ptr<repr::ModuleIR> module(
211       new repr::ModuleIR(nullptr /*FIXME*/));
212 
213   HeaderASTVisitor v(options_, mangle_contextp.get(), &ctx, cip_,
214                      translation_unit, module.get(), &ast_caches);
215   if (!v.TraverseDecl(translation_unit)) {
216     llvm::errs() << "ABI extraction failed\n";
217     ::exit(1);
218   }
219 
220   std::unique_ptr<repr::IRDumper> ir_dumper =
221       repr::IRDumper::CreateIRDumper(options_.text_format_,
222                                      options_.dump_name_);
223   if (!ir_dumper->Dump(*module)) {
224     llvm::errs() << "Serialization failed\n";
225     ::exit(1);
226   }
227 }
228 
229 
230 }  // dumper
231 }  // header_checker
232