blob: b8b12770ba30717bb9f39e8bac1c4d6464d55ede [file] [log] [blame]
Michael Forsterb3503e02022-04-25 00:24:14 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef CRUBIT_RS_BINDINGS_FROM_CC_DECL_IMPORTER_H_
6#define CRUBIT_RS_BINDINGS_FROM_CC_DECL_IMPORTER_H_
7
Googlera6c60bb2022-12-20 07:32:17 -08008#include <optional>
9
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070010#include "absl/container/flat_hash_map.h"
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -070011#include "absl/log/check.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070012#include "absl/status/statusor.h"
Michael Forsterb3503e02022-04-25 00:24:14 -070013#include "lifetime_annotations/lifetime_annotations.h"
14#include "rs_bindings_from_cc/bazel_types.h"
15#include "rs_bindings_from_cc/ir.h"
16
17namespace crubit {
18
19// Top-level parameters as well as return value of an importer invocation.
20class Invocation {
21 public:
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070022 Invocation(BazelLabel target, absl::Span<const HeaderName> public_headers,
Michael Forsterb3503e02022-04-25 00:24:14 -070023 const absl::flat_hash_map<const HeaderName, const BazelLabel>&
24 header_targets)
25 : target_(target),
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070026 public_headers_(public_headers),
Michael Forsterb3503e02022-04-25 00:24:14 -070027 lifetime_context_(std::make_shared<
28 clang::tidy::lifetimes::LifetimeAnnotationContext>()),
29 header_targets_(header_targets) {
30 // Caller should verify that the inputs are non-empty.
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070031 CHECK(!public_headers_.empty());
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -070032 CHECK(!header_targets_.empty());
Michael Forsterb3503e02022-04-25 00:24:14 -070033
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070034 ir_.public_headers.insert(ir_.public_headers.end(), public_headers_.begin(),
35 public_headers.end());
Michael Forsterb3503e02022-04-25 00:24:14 -070036 ir_.current_target = target_;
37 }
38
39 // Returns the target of a header, if any.
40 std::optional<BazelLabel> header_target(const HeaderName header) const {
41 auto it = header_targets_.find(header);
42 return (it != header_targets_.end()) ? std::optional(it->second)
43 : std::nullopt;
44 }
45
46 // The main target from which we are importing.
47 const BazelLabel target_;
48
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070049 // The headers from which the import starts. See the doc comment of
50 // `IR::public_headers` and `HeaderName` for more details.
51 const absl::Span<const HeaderName> public_headers_;
Michael Forsterb3503e02022-04-25 00:24:14 -070052
53 const std::shared_ptr<clang::tidy::lifetimes::LifetimeAnnotationContext>
54 lifetime_context_;
55
56 // The main output of the import process
57 IR ir_;
58
59 private:
60 const absl::flat_hash_map<const HeaderName, const BazelLabel>&
61 header_targets_;
62};
63
Michael Forsterb3503e02022-04-25 00:24:14 -070064// Explicitly defined interface that defines how `DeclImporter`s are allowed to
65// interface with the global state of the importer.
66class ImportContext {
67 public:
68 ImportContext(Invocation& invocation, clang::ASTContext& ctx,
69 clang::Sema& sema)
Lukasz Anforowiczff16f642022-05-27 16:56:50 -070070 : invocation_(invocation), ctx_(ctx), sema_(sema) {}
Michael Forster974bf152022-05-12 00:40:59 -070071 virtual ~ImportContext() {}
Michael Forsterb3503e02022-04-25 00:24:14 -070072
73 // Imports all decls contained in a `DeclContext`.
74 virtual void ImportDeclsFromDeclContext(
75 const clang::DeclContext* decl_context) = 0;
76
77 // Imports an unsupported item with a single error message.
78 virtual IR::Item ImportUnsupportedItem(const clang::Decl* decl,
79 std::string error) = 0;
80
81 // Imports an unsupported item with multiple error messages.
82 virtual IR::Item ImportUnsupportedItem(const clang::Decl* decl,
83 std::set<std::string> errors) = 0;
84
Michael VanBemmel7a4d4c02022-07-27 13:21:47 -070085 // Imports a decl and creates an IR item (or error messages). This allows
86 // importers to recursively delegate to other importers.
87 // Does not use or update the cache.
88 virtual std::optional<IR::Item> ImportDecl(clang::Decl* decl) = 0;
89
Devin Jeanpierre6af160e2022-09-21 05:30:34 -070090 // Returns the Item of a Decl, importing it first if necessary.
91 // Updates the cache.
92 virtual std::optional<IR::Item> GetDeclItem(clang::Decl* decl) = 0;
93
Kinuko Yasuda6ff59f12022-08-11 08:41:45 -070094 virtual std::optional<IR::Item> GetImportedItem(const clang::Decl* decl) = 0;
95
Lukasz Anforowicz0b3b70c2022-09-02 10:00:40 -070096 // Imports children of `decl`.
97 //
98 // Returns item ids of the children that belong to the current target. This
99 // includes ids of comments within `decl`. The returned ids are ordered by
100 // their source order.
Michael Forsterb3503e02022-04-25 00:24:14 -0700101 virtual std::vector<ItemId> GetItemIdsInSourceOrder(clang::Decl* decl) = 0;
102
103 // Mangles the name of a named decl.
104 virtual std::string GetMangledName(
105 const clang::NamedDecl* named_decl) const = 0;
106
107 // Returs the label of the target that contains a decl.
108 virtual BazelLabel GetOwningTarget(const clang::Decl* decl) const = 0;
109
110 // Checks if the given decl belongs to the current target. Does not look into
111 // other redeclarations of the decl.
112 virtual bool IsFromCurrentTarget(const clang::Decl* decl) const = 0;
113
114 // Gets an IR UnqualifiedIdentifier for the named decl.
115 //
116 // If the decl's name is an identifier, this returns that identifier as-is.
117 //
118 // If the decl is a special member function or operator overload, this returns
119 // a SpecialName.
120 //
121 // If the translated name is not yet implemented, this returns null.
122 virtual std::optional<UnqualifiedIdentifier> GetTranslatedName(
123 const clang::NamedDecl* named_decl) const = 0;
124
125 // GetTranslatedName, but only for identifier names. This is the common case.
126 virtual std::optional<Identifier> GetTranslatedIdentifier(
127 const clang::NamedDecl* named_decl) const = 0;
128
129 // Gets the doc comment of the declaration.
Googlera6c60bb2022-12-20 07:32:17 -0800130 virtual std::optional<std::string> GetComment(
Michael Forsterb3503e02022-04-25 00:24:14 -0700131 const clang::Decl* decl) const = 0;
132
133 // Converts a Clang source location to IR.
134 virtual SourceLoc ConvertSourceLocation(clang::SourceLocation loc) const = 0;
135
Lukasz Anforowicz63559d32022-05-27 16:42:36 -0700136 // Converts the Clang type `qual_type` into an equivalent `MappedType`.
137 // Lifetimes for the type can optionally be specified using `lifetimes`.
138 // If `qual_type` is a pointer type, `nullable` specifies whether the
139 // pointer can be null.
140 // TODO(b/209390498): Currently, we're able to specify nullability only for
141 // top-level pointers. Extend this so that we can specify nullability for
142 // all pointers contained in `qual_type`, in the same way that `lifetimes`
143 // specifies lifetimes for all these pointers. Once this is done, make sure
144 // that all callers pass in the appropriate information, derived from
145 // nullability annotations.
146 virtual absl::StatusOr<MappedType> ConvertQualType(
147 clang::QualType qual_type,
148 std::optional<clang::tidy::lifetimes::ValueLifetimes>& lifetimes,
Lukasz Anforowicz14732b22022-06-02 09:11:08 -0700149 bool nullable = true) = 0;
Lukasz Anforowiczb1ff2e52022-05-16 10:54:23 -0700150
Lukasz Anforowicz0233f982022-05-27 16:38:20 -0700151 // Marks `decl` as successfully imported. Other pieces of code can check
152 // HasBeenAlreadySuccessfullyImported to avoid introducing dangling ItemIds
153 // that refer to an unimportable `decl`.
154 virtual void MarkAsSuccessfullyImported(const clang::TypeDecl* decl) = 0;
155
Lukasz Anforowicz5258f762022-05-27 16:14:46 -0700156 // Returns whether the `decl` has been already successfully imported (maybe
157 // partially - e.g. CXXRecordDeclImporter::Import marks the import as success
Lukasz Anforowicz0233f982022-05-27 16:38:20 -0700158 // before importing the fields, because the latter cannot fail). See also
159 // MarkAsSuccessfullyImported.
Lukasz Anforowicz5258f762022-05-27 16:14:46 -0700160 virtual bool HasBeenAlreadySuccessfullyImported(
161 const clang::TypeDecl* decl) const = 0;
162
Devin Jeanpierre61804f72022-10-04 20:26:13 -0700163 // Returns whether the `decl` will be successfully imported. If it hasn't been
164 // imported yet, attempts to import it now, calling
165 // MarkAsSuccessfullyImported.
166 virtual bool EnsureSuccessfullyImported(clang::TypeDecl* decl) = 0;
167
Michael Forsterb3503e02022-04-25 00:24:14 -0700168 Invocation& invocation_;
169 clang::ASTContext& ctx_;
170 clang::Sema& sema_;
Michael Forsterb3503e02022-04-25 00:24:14 -0700171};
172
173// Interface for components that can import decls of a certain category.
174class DeclImporter {
175 public:
Michael Forster974bf152022-05-12 00:40:59 -0700176 DeclImporter(ImportContext& ictx) : ictx_(ictx) {}
177 virtual ~DeclImporter() {}
Michael Forsterb3503e02022-04-25 00:24:14 -0700178
179 // Determines whether this importer is autoritative for a decl. This does not
180 // imply that the import will be succesful.
181 virtual bool CanImport(clang::Decl*) = 0;
182
183 // Returns an IR item for a decl, or `std::nullopt` if importing failed.
184 // This member function may only be called after `CanImport` returned `true`.
185 virtual std::optional<IR::Item> ImportDecl(clang::Decl*) = 0;
186
187 protected:
188 ImportContext& ictx_;
189};
190
191// Common implementation for defining `DeclImporter`s that determine their
192// applicability by the dynamic type of the decl.
193template <typename D>
194class DeclImporterBase : public DeclImporter {
195 public:
196 DeclImporterBase(ImportContext& context) : DeclImporter(context) {}
197
198 protected:
199 bool CanImport(clang::Decl* decl) { return clang::isa<D>(decl); }
200 std::optional<IR::Item> ImportDecl(clang::Decl* decl) {
201 return Import(clang::cast<D>(decl));
202 }
Googlerf596aec2022-05-05 22:02:24 -0700203 virtual std::optional<IR::Item> Import(D*) = 0;
Michael Forsterb3503e02022-04-25 00:24:14 -0700204};
205
206} // namespace crubit
207
208#endif // CRUBIT_RS_BINDINGS_FROM_CC_DECL_IMPORTER_H_