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