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 
21 #include <google/protobuf/text_format.h>
22 #include <google/protobuf/io/zero_copy_stream_impl.h>
23 
24 #include <fstream>
25 #include <iostream>
26 #include <string>
27 
28 using abi_wrapper::ABIWrapper;
29 using abi_wrapper::FunctionDeclWrapper;
30 using abi_wrapper::RecordDeclWrapper;
31 using abi_wrapper::EnumDeclWrapper;
32 using abi_wrapper::GlobalVarDeclWrapper;
33 
HeaderASTVisitor(abi_dump::TranslationUnit * tu_ptr,clang::MangleContext * mangle_contextp,clang::ASTContext * ast_contextp,const clang::CompilerInstance * compiler_instance_p,const std::string & current_file_name,const std::set<std::string> & exported_headers,const clang::Decl * tu_decl)34 HeaderASTVisitor::HeaderASTVisitor(
35     abi_dump::TranslationUnit *tu_ptr,
36     clang::MangleContext *mangle_contextp,
37     clang::ASTContext *ast_contextp,
38     const clang::CompilerInstance *compiler_instance_p,
39     const std::string &current_file_name,
40     const std::set<std::string> &exported_headers,
41     const clang::Decl *tu_decl)
42   : tu_ptr_(tu_ptr),
43     mangle_contextp_(mangle_contextp),
44     ast_contextp_(ast_contextp),
45     cip_(compiler_instance_p),
46     current_file_name_(current_file_name),
47     exported_headers_(exported_headers),
48     tu_decl_(tu_decl) { }
49 
VisitRecordDecl(const clang::RecordDecl * decl)50 bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
51   // Skip forward declaration.
52   if (!decl->isThisDeclarationADefinition()) {
53     return true;
54   }
55   RecordDeclWrapper record_decl_wrapper(
56       mangle_contextp_, ast_contextp_, cip_, decl);
57   std::unique_ptr<abi_dump::RecordDecl> wrapped_record_decl =
58       record_decl_wrapper.GetRecordDecl();
59   if (!wrapped_record_decl) {
60     llvm::errs() << "Getting Record Decl failed\n";
61     return false;
62   }
63   abi_dump::RecordDecl *added_record_declp = tu_ptr_->add_records();
64   if (!added_record_declp) {
65     return false;
66   }
67   *added_record_declp = *wrapped_record_decl;
68   return true;
69 }
70 
VisitEnumDecl(const clang::EnumDecl * decl)71 bool HeaderASTVisitor::VisitEnumDecl(const clang::EnumDecl *decl) {
72   if (!decl->isThisDeclarationADefinition()) {
73     return true;
74   }
75   EnumDeclWrapper enum_decl_wrapper(
76       mangle_contextp_, ast_contextp_, cip_, decl);
77   std::unique_ptr<abi_dump::EnumDecl> wrapped_enum_decl =
78       enum_decl_wrapper.GetEnumDecl();
79   if (!wrapped_enum_decl) {
80     llvm::errs() << "Getting Enum Decl failed\n";
81     return false;
82   }
83   abi_dump::EnumDecl *added_enum_declp = tu_ptr_->add_enums();
84   if (!added_enum_declp) {
85     return false;
86   }
87   *added_enum_declp = *wrapped_enum_decl;
88   return true;
89 }
90 
VisitFunctionDecl(const clang::FunctionDecl * decl)91 bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) {
92   FunctionDeclWrapper function_decl_wrapper(mangle_contextp_, ast_contextp_,
93                                             cip_, decl);
94   std::unique_ptr<abi_dump::FunctionDecl> wrapped_function_decl =
95       function_decl_wrapper.GetFunctionDecl();
96   if (!wrapped_function_decl) {
97     llvm::errs() << "Getting Function Decl failed\n";
98     return false;
99   }
100   abi_dump::FunctionDecl *added_function_declp = tu_ptr_->add_functions();
101   if (!added_function_declp) {
102     return false;
103   }
104   *added_function_declp = *wrapped_function_decl;
105   return true;
106 }
107 
VisitVarDecl(const clang::VarDecl * decl)108 bool HeaderASTVisitor::VisitVarDecl(const clang::VarDecl *decl) {
109   if(!decl->hasGlobalStorage()) {
110     // Non global / static variable declarations don't need to be dumped.
111     return true;
112   }
113   GlobalVarDeclWrapper global_var_decl_wrapper(mangle_contextp_, ast_contextp_,
114                                                cip_, decl);
115   std::unique_ptr<abi_dump::GlobalVarDecl> wrapped_global_var_decl =
116       global_var_decl_wrapper.GetGlobalVarDecl();
117   if (!wrapped_global_var_decl) {
118     llvm::errs() << "Getting Global Var Decl failed\n";
119     return false;
120   }
121   abi_dump::GlobalVarDecl *added_global_var_declp = tu_ptr_->add_global_vars();
122   if (!added_global_var_declp) {
123     return false;
124   }
125   *added_global_var_declp = *wrapped_global_var_decl;
126   return true;
127 }
128 
AreHeadersExported(const std::set<std::string> & exported_headers)129 static bool AreHeadersExported(const std::set<std::string> &exported_headers) {
130   return !exported_headers.empty();
131 }
132 
133 // We don't need to recurse into Declarations which are not exported.
TraverseDecl(clang::Decl * decl)134 bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) {
135   if (!decl) {
136     return true;
137   }
138   std::string source_file = ABIWrapper::GetDeclSourceFile(decl, cip_);
139   // If no exported headers are specified we assume the whole AST is exported.
140   if ((decl != tu_decl_) && AreHeadersExported(exported_headers_) &&
141       (exported_headers_.find(source_file) == exported_headers_.end())) {
142     return true;
143   }
144   return RecursiveASTVisitor<HeaderASTVisitor>::TraverseDecl(decl);
145 }
146 
HeaderASTConsumer(const std::string & file_name,clang::CompilerInstance * compiler_instancep,const std::string & out_dump_name,const std::set<std::string> & exported_headers)147 HeaderASTConsumer::HeaderASTConsumer(
148     const std::string &file_name,
149     clang::CompilerInstance *compiler_instancep,
150     const std::string &out_dump_name,
151     const std::set<std::string> &exported_headers)
152   : file_name_(file_name),
153     cip_(compiler_instancep),
154     out_dump_name_(out_dump_name),
155     exported_headers_(exported_headers) { }
156 
HandleTranslationUnit(clang::ASTContext & ctx)157 void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
158   GOOGLE_PROTOBUF_VERIFY_VERSION;
159   std::ofstream text_output(out_dump_name_);
160   google::protobuf::io::OstreamOutputStream text_os(&text_output);
161   clang::TranslationUnitDecl *translation_unit = ctx.getTranslationUnitDecl();
162   std::unique_ptr<clang::MangleContext> mangle_contextp(
163       ctx.createMangleContext());
164   abi_dump::TranslationUnit tu;
165   std::string str_out;
166   HeaderASTVisitor v(&tu, mangle_contextp.get(), &ctx, cip_, file_name_,
167                      exported_headers_, translation_unit);
168   if (!v.TraverseDecl(translation_unit) ||
169       !google::protobuf::TextFormat::Print(tu, &text_os)) {
170     llvm::errs() << "Serialization to ostream failed\n";
171     ::exit(1);
172   }
173 }
174