• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Google LLC
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 //     https://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 #ifndef SANDBOXED_API_TOOLS_CLANG_GENERATOR_GENERATOR_H_
16 #define SANDBOXED_API_TOOLS_CLANG_GENERATOR_GENERATOR_H_
17 
18 #include <memory>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "absl/container/flat_hash_set.h"
24 #include "absl/strings/string_view.h"
25 #include "clang/AST/ASTConsumer.h"
26 #include "clang/AST/Decl.h"
27 #include "clang/AST/RecursiveASTVisitor.h"
28 #include "clang/Frontend/CompilerInstance.h"
29 #include "clang/Frontend/CompilerInvocation.h"
30 #include "clang/Frontend/FrontendAction.h"
31 #include "clang/Lex/Preprocessor.h"
32 #include "clang/Serialization/PCHContainerOperations.h"
33 #include "clang/Tooling/Tooling.h"
34 #include "llvm/ADT/StringRef.h"
35 #include "llvm/Config/llvm-config.h"
36 #include "sandboxed_api/tools/clang_generator/emitter.h"
37 #include "sandboxed_api/tools/clang_generator/emitter_base.h"
38 #include "sandboxed_api/tools/clang_generator/types.h"
39 
40 namespace sapi {
41 
42 struct GeneratorOptions {
43   template <typename ContainerT>
set_function_namesGeneratorOptions44   GeneratorOptions& set_function_names(const ContainerT& value) {
45     function_names.clear();
46     function_names.insert(std::begin(value), std::end(value));
47     return *this;
48   }
49 
50   template <typename ContainerT>
set_in_filesGeneratorOptions51   GeneratorOptions& set_in_files(const ContainerT& value) {
52     in_files.clear();
53     in_files.insert(std::begin(value), std::end(value));
54     return *this;
55   }
56 
set_limit_scan_depthGeneratorOptions57   GeneratorOptions& set_limit_scan_depth(bool value) {
58     limit_scan_depth = value;
59     return *this;
60   }
61 
has_namespaceGeneratorOptions62   bool has_namespace() const { return !namespace_name.empty(); }
63 
64   absl::flat_hash_set<std::string> function_names;
65   absl::flat_hash_set<std::string> in_files;
66   bool limit_scan_depth = false;
67 
68   // Output options
69   std::string work_dir;
70   std::string name;            // Name of the Sandboxed API
71   std::string namespace_name;  // Namespace to wrap the SAPI in
72   // Output path of the generated header. Used to build the header include
73   // guard.
74   std::string out_file = "out_file.cc";
75   std::string embed_dir;   // Directory with embedded includes
76   std::string embed_name;  // Identifier of the embed object
77 };
78 
79 class GeneratorASTVisitor
80     : public clang::RecursiveASTVisitor<GeneratorASTVisitor> {
81  public:
GeneratorASTVisitor(const GeneratorOptions & options)82   explicit GeneratorASTVisitor(const GeneratorOptions& options)
83       : options_(options) {}
84 
85   bool VisitTypeDecl(clang::TypeDecl* decl);
86   bool VisitFunctionDecl(clang::FunctionDecl* decl);
87 
collector()88   TypeCollector& collector() { return collector_; }
89 
functions()90   const std::vector<clang::FunctionDecl*>& functions() const {
91     return functions_;
92   }
93 
94  private:
95   TypeCollector collector_;
96   std::vector<clang::FunctionDecl*> functions_;
97   const GeneratorOptions& options_;
98 };
99 
100 class GeneratorASTConsumer : public clang::ASTConsumer {
101  public:
GeneratorASTConsumer(std::string in_file,EmitterBase & emitter,const GeneratorOptions & options)102   GeneratorASTConsumer(std::string in_file, EmitterBase& emitter,
103                        const GeneratorOptions& options)
104       : in_file_(std::move(in_file)), visitor_(options), emitter_(emitter) {}
105 
106  private:
107   void HandleTranslationUnit(clang::ASTContext& context) override;
108 
109   std::string in_file_;
110   GeneratorASTVisitor visitor_;
111   EmitterBase& emitter_;
112 };
113 
114 class GeneratorAction : public clang::ASTFrontendAction {
115  public:
GeneratorAction(EmitterBase & emitter,const GeneratorOptions & options)116   GeneratorAction(EmitterBase& emitter, const GeneratorOptions& options)
117       : emitter_(emitter), options_(options) {}
118 
119  private:
CreateASTConsumer(clang::CompilerInstance &,llvm::StringRef in_file)120   std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
121       clang::CompilerInstance&, llvm::StringRef in_file) override {
122     return std::make_unique<GeneratorASTConsumer>(std::string(in_file),
123                                                   emitter_, options_);
124   }
125 
BeginSourceFileAction(clang::CompilerInstance & ci)126   bool BeginSourceFileAction(clang::CompilerInstance& ci) override {
127     ci.getPreprocessor().enableIncrementalProcessing();
128     return true;
129   }
130 
hasCodeCompletionSupport()131   bool hasCodeCompletionSupport() const override { return false; }
132 
133   EmitterBase& emitter_;
134   const GeneratorOptions& options_;
135 };
136 
137 class GeneratorFactory : public clang::tooling::FrontendActionFactory {
138  public:
139   // Does not take ownership
GeneratorFactory(EmitterBase & emitter,const GeneratorOptions & options)140   GeneratorFactory(EmitterBase& emitter, const GeneratorOptions& options)
141       : emitter_(emitter), options_(options) {}
142 
143  private:
144 #if LLVM_VERSION_MAJOR >= 10
create()145   std::unique_ptr<clang::FrontendAction> create() override {
146     return std::make_unique<GeneratorAction>(emitter_, options_);
147   }
148 #else
149   clang::FrontendAction* create() override {
150     return new GeneratorAction(emitter_, options_);
151   }
152 #endif
153 
154   bool runInvocation(
155       std::shared_ptr<clang::CompilerInvocation> invocation,
156       clang::FileManager* files,
157       std::shared_ptr<clang::PCHContainerOperations> pch_container_ops,
158       clang::DiagnosticConsumer* diag_consumer) override;
159 
160   EmitterBase& emitter_;
161   const GeneratorOptions& options_;
162 };
163 
164 // Returns the output filename for the given source file ending in .sapi.h.
165 std::string GetOutputFilename(absl::string_view source_file);
166 
ToStringView(llvm::StringRef ref)167 inline absl::string_view ToStringView(llvm::StringRef ref) {
168   return absl::string_view(ref.data(), ref.size());
169 }
170 
171 }  // namespace sapi
172 
173 #endif  // SANDBOXED_API_TOOLS_CLANG_GENERATOR_GENERATOR_H_
174