blob: af82aa6ae5e7a6b5b5f055e93887b183f4ab2189 [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
Devin Jeanpierre257f0f62023-05-08 11:52:01 -07008#include <memory>
Googlera6c60bb2022-12-20 07:32:17 -08009#include <optional>
Devin Jeanpierre257f0f62023-05-08 11:52:01 -070010#include <set>
11#include <string>
12#include <vector>
Googlera6c60bb2022-12-20 07:32:17 -080013
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070014#include "absl/container/flat_hash_map.h"
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -070015#include "absl/log/check.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070016#include "absl/status/statusor.h"
Dmitri Gribenko785831e2023-07-14 06:47:36 -070017#include "absl/types/span.h"
Michael Forsterb3503e02022-04-25 00:24:14 -070018#include "lifetime_annotations/lifetime_annotations.h"
Martin Brænne390ffa22023-07-10 12:26:53 -070019#include "lifetime_annotations/type_lifetimes.h"
Michael Forsterb3503e02022-04-25 00:24:14 -070020#include "rs_bindings_from_cc/bazel_types.h"
21#include "rs_bindings_from_cc/ir.h"
Dmitri Gribenko785831e2023-07-14 06:47:36 -070022#include "clang/AST/DeclBase.h"
Googler1bff6372023-03-24 10:06:29 -070023#include "clang/AST/Type.h"
Dmitri Gribenko785831e2023-07-14 06:47:36 -070024#include "clang/Basic/SourceLocation.h"
25#include "clang/Sema/Sema.h"
Michael Forsterb3503e02022-04-25 00:24:14 -070026
27namespace crubit {
28
29// Top-level parameters as well as return value of an importer invocation.
30class Invocation {
31 public:
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070032 Invocation(BazelLabel target, absl::Span<const HeaderName> public_headers,
Devin Jeanpierre7571ece2023-01-13 11:39:26 -080033 const absl::flat_hash_map<HeaderName, BazelLabel>& header_targets)
Michael Forsterb3503e02022-04-25 00:24:14 -070034 : target_(target),
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070035 public_headers_(public_headers),
Michael Forsterb3503e02022-04-25 00:24:14 -070036 lifetime_context_(std::make_shared<
37 clang::tidy::lifetimes::LifetimeAnnotationContext>()),
38 header_targets_(header_targets) {
39 // Caller should verify that the inputs are non-empty.
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070040 CHECK(!public_headers_.empty());
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -070041 CHECK(!header_targets_.empty());
Michael Forsterb3503e02022-04-25 00:24:14 -070042
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070043 ir_.public_headers.insert(ir_.public_headers.end(), public_headers_.begin(),
44 public_headers.end());
Michael Forsterb3503e02022-04-25 00:24:14 -070045 ir_.current_target = target_;
46 }
47
48 // Returns the target of a header, if any.
49 std::optional<BazelLabel> header_target(const HeaderName header) const {
50 auto it = header_targets_.find(header);
51 return (it != header_targets_.end()) ? std::optional(it->second)
52 : std::nullopt;
53 }
54
55 // The main target from which we are importing.
56 const BazelLabel target_;
57
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070058 // The headers from which the import starts. See the doc comment of
59 // `IR::public_headers` and `HeaderName` for more details.
60 const absl::Span<const HeaderName> public_headers_;
Michael Forsterb3503e02022-04-25 00:24:14 -070061
62 const std::shared_ptr<clang::tidy::lifetimes::LifetimeAnnotationContext>
63 lifetime_context_;
64
65 // The main output of the import process
66 IR ir_;
67
68 private:
Devin Jeanpierre7571ece2023-01-13 11:39:26 -080069 const absl::flat_hash_map<HeaderName, BazelLabel>& header_targets_;
Michael Forsterb3503e02022-04-25 00:24:14 -070070};
71
Michael Forsterb3503e02022-04-25 00:24:14 -070072// Explicitly defined interface that defines how `DeclImporter`s are allowed to
73// interface with the global state of the importer.
74class ImportContext {
75 public:
76 ImportContext(Invocation& invocation, clang::ASTContext& ctx,
77 clang::Sema& sema)
Lukasz Anforowiczff16f642022-05-27 16:56:50 -070078 : invocation_(invocation), ctx_(ctx), sema_(sema) {}
Devin Jeanpierre257f0f62023-05-08 11:52:01 -070079 virtual ~ImportContext() = default;
Michael Forsterb3503e02022-04-25 00:24:14 -070080
81 // Imports all decls contained in a `DeclContext`.
82 virtual void ImportDeclsFromDeclContext(
83 const clang::DeclContext* decl_context) = 0;
84
85 // Imports an unsupported item with a single error message.
86 virtual IR::Item ImportUnsupportedItem(const clang::Decl* decl,
87 std::string error) = 0;
88
89 // Imports an unsupported item with multiple error messages.
90 virtual IR::Item ImportUnsupportedItem(const clang::Decl* decl,
91 std::set<std::string> errors) = 0;
92
Michael VanBemmel7a4d4c02022-07-27 13:21:47 -070093 // Imports a decl and creates an IR item (or error messages). This allows
94 // importers to recursively delegate to other importers.
95 // Does not use or update the cache.
96 virtual std::optional<IR::Item> ImportDecl(clang::Decl* decl) = 0;
97
Devin Jeanpierre6af160e2022-09-21 05:30:34 -070098 // Returns the Item of a Decl, importing it first if necessary.
99 // Updates the cache.
100 virtual std::optional<IR::Item> GetDeclItem(clang::Decl* decl) = 0;
101
Kinuko Yasuda6ff59f12022-08-11 08:41:45 -0700102 virtual std::optional<IR::Item> GetImportedItem(const clang::Decl* decl) = 0;
103
Lukasz Anforowicz0b3b70c2022-09-02 10:00:40 -0700104 // Imports children of `decl`.
105 //
106 // Returns item ids of the children that belong to the current target. This
107 // includes ids of comments within `decl`. The returned ids are ordered by
108 // their source order.
Michael Forsterb3503e02022-04-25 00:24:14 -0700109 virtual std::vector<ItemId> GetItemIdsInSourceOrder(clang::Decl* decl) = 0;
110
111 // Mangles the name of a named decl.
112 virtual std::string GetMangledName(
113 const clang::NamedDecl* named_decl) const = 0;
114
115 // Returs the label of the target that contains a decl.
116 virtual BazelLabel GetOwningTarget(const clang::Decl* decl) const = 0;
117
118 // Checks if the given decl belongs to the current target. Does not look into
119 // other redeclarations of the decl.
120 virtual bool IsFromCurrentTarget(const clang::Decl* decl) const = 0;
121
122 // Gets an IR UnqualifiedIdentifier for the named decl.
123 //
124 // If the decl's name is an identifier, this returns that identifier as-is.
125 //
126 // If the decl is a special member function or operator overload, this returns
127 // a SpecialName.
128 //
Lukasz Anforowicz5837b7d2023-02-23 16:39:02 -0800129 // If the name can't be translated (or is empty), this returns an error.
130 virtual absl::StatusOr<UnqualifiedIdentifier> GetTranslatedName(
Michael Forsterb3503e02022-04-25 00:24:14 -0700131 const clang::NamedDecl* named_decl) const = 0;
132
133 // GetTranslatedName, but only for identifier names. This is the common case.
Lukasz Anforowicz5837b7d2023-02-23 16:39:02 -0800134 // If the name can't be translated (or is empty), this returns an error.
135 virtual absl::StatusOr<Identifier> GetTranslatedIdentifier(
Michael Forsterb3503e02022-04-25 00:24:14 -0700136 const clang::NamedDecl* named_decl) const = 0;
137
138 // Gets the doc comment of the declaration.
Googlera6c60bb2022-12-20 07:32:17 -0800139 virtual std::optional<std::string> GetComment(
Michael Forsterb3503e02022-04-25 00:24:14 -0700140 const clang::Decl* decl) const = 0;
141
142 // Converts a Clang source location to IR.
Googler442733c2023-01-23 01:05:35 -0800143 virtual std::string ConvertSourceLocation(
144 clang::SourceLocation loc) const = 0;
Michael Forsterb3503e02022-04-25 00:24:14 -0700145
Lukasz Anforowicz63559d32022-05-27 16:42:36 -0700146 // Converts the Clang type `qual_type` into an equivalent `MappedType`.
Martin Brænne390ffa22023-07-10 12:26:53 -0700147 // Lifetimes for the type can optionally be specified using `lifetimes` (pass
148 // null otherwise).
Lukasz Anforowicz63559d32022-05-27 16:42:36 -0700149 // If `qual_type` is a pointer type, `nullable` specifies whether the
150 // pointer can be null.
151 // TODO(b/209390498): Currently, we're able to specify nullability only for
152 // top-level pointers. Extend this so that we can specify nullability for
153 // all pointers contained in `qual_type`, in the same way that `lifetimes`
154 // specifies lifetimes for all these pointers. Once this is done, make sure
155 // that all callers pass in the appropriate information, derived from
156 // nullability annotations.
157 virtual absl::StatusOr<MappedType> ConvertQualType(
158 clang::QualType qual_type,
Martin Brænne390ffa22023-07-10 12:26:53 -0700159 const clang::tidy::lifetimes::ValueLifetimes* lifetimes,
Googler1bff6372023-03-24 10:06:29 -0700160 std::optional<clang::RefQualifierKind> ref_qualifier_kind,
Lukasz Anforowicz14732b22022-06-02 09:11:08 -0700161 bool nullable = true) = 0;
Lukasz Anforowiczb1ff2e52022-05-16 10:54:23 -0700162
Lukasz Anforowicz0233f982022-05-27 16:38:20 -0700163 // Marks `decl` as successfully imported. Other pieces of code can check
164 // HasBeenAlreadySuccessfullyImported to avoid introducing dangling ItemIds
165 // that refer to an unimportable `decl`.
Devin Jeanpierre3c4354b2023-05-26 16:01:49 -0700166 virtual void MarkAsSuccessfullyImported(const clang::NamedDecl* decl) = 0;
Lukasz Anforowicz0233f982022-05-27 16:38:20 -0700167
Lukasz Anforowicz5258f762022-05-27 16:14:46 -0700168 // Returns whether the `decl` has been already successfully imported (maybe
169 // partially - e.g. CXXRecordDeclImporter::Import marks the import as success
Lukasz Anforowicz0233f982022-05-27 16:38:20 -0700170 // before importing the fields, because the latter cannot fail). See also
171 // MarkAsSuccessfullyImported.
Lukasz Anforowicz5258f762022-05-27 16:14:46 -0700172 virtual bool HasBeenAlreadySuccessfullyImported(
Devin Jeanpierre3c4354b2023-05-26 16:01:49 -0700173 const clang::NamedDecl* decl) const = 0;
Lukasz Anforowicz5258f762022-05-27 16:14:46 -0700174
Devin Jeanpierre61804f72022-10-04 20:26:13 -0700175 // Returns whether the `decl` will be successfully imported. If it hasn't been
176 // imported yet, attempts to import it now, calling
177 // MarkAsSuccessfullyImported.
Devin Jeanpierre3c4354b2023-05-26 16:01:49 -0700178 virtual bool EnsureSuccessfullyImported(clang::NamedDecl* decl) = 0;
Devin Jeanpierre61804f72022-10-04 20:26:13 -0700179
Michael Forsterb3503e02022-04-25 00:24:14 -0700180 Invocation& invocation_;
181 clang::ASTContext& ctx_;
182 clang::Sema& sema_;
Michael Forsterb3503e02022-04-25 00:24:14 -0700183};
184
185// Interface for components that can import decls of a certain category.
186class DeclImporter {
187 public:
Devin Jeanpierre257f0f62023-05-08 11:52:01 -0700188 explicit DeclImporter(ImportContext& ictx) : ictx_(ictx) {}
189 virtual ~DeclImporter() = default;
Michael Forsterb3503e02022-04-25 00:24:14 -0700190
Devin Jeanpierrec2c39ff2023-05-08 11:42:21 -0700191 // Returns an IR item for a decl, or `std::nullopt` if it could not be
192 // imported.
193 // If it can't be imported, other DeclImporters may be attempted.
194 // To indicate that an item can't be imported, and no other importers should
195 // be attempted, return UnsupportedItem.
Michael Forsterb3503e02022-04-25 00:24:14 -0700196 virtual std::optional<IR::Item> ImportDecl(clang::Decl*) = 0;
197
198 protected:
199 ImportContext& ictx_;
200};
201
202// Common implementation for defining `DeclImporter`s that determine their
203// applicability by the dynamic type of the decl.
204template <typename D>
205class DeclImporterBase : public DeclImporter {
206 public:
Devin Jeanpierre257f0f62023-05-08 11:52:01 -0700207 explicit DeclImporterBase(ImportContext& context) : DeclImporter(context) {}
Michael Forsterb3503e02022-04-25 00:24:14 -0700208
209 protected:
Devin Jeanpierre257f0f62023-05-08 11:52:01 -0700210 std::optional<IR::Item> ImportDecl(clang::Decl* decl) override {
Devin Jeanpierrec2c39ff2023-05-08 11:42:21 -0700211 auto* typed_decl = clang::dyn_cast<D>(decl);
212 if (typed_decl == nullptr) return std::nullopt;
213 return Import(typed_decl);
Michael Forsterb3503e02022-04-25 00:24:14 -0700214 }
Googlerf596aec2022-05-05 22:02:24 -0700215 virtual std::optional<IR::Item> Import(D*) = 0;
Michael Forsterb3503e02022-04-25 00:24:14 -0700216};
217
218} // namespace crubit
219
220#endif // CRUBIT_RS_BINDINGS_FROM_CC_DECL_IMPORTER_H_