blob: 29e996b0deb228e6f42c7d1575044950ecd0c345 [file] [log] [blame]
Marcel Hlopkobfd8d322021-08-02 12:28:52 +00001// 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// This file defines an intermediate representation (IR) used between Clang AST
6// and code generators that generate Rust bindings and C++ bindings
7// implementation.
8//
9// All types in this file own their data. This IR is expected to outlive the
10// Clang's AST context, therefore it cannot reference data owned by it.
Dmitri Gribenkoe4e77d02022-03-17 14:09:39 +000011#ifndef CRUBIT_RS_BINDINGS_FROM_CC_IR_H_
12#define CRUBIT_RS_BINDINGS_FROM_CC_IR_H_
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000013
Marcel Hlopko20f4ce42021-11-02 08:20:00 +000014#include <stdint.h>
15
Devin Jeanpierre56777022022-02-03 01:57:15 +000016#include <cstddef>
Googler56183012021-12-01 11:07:05 +000017#include <iomanip>
Marcel Hlopko20f4ce42021-11-02 08:20:00 +000018#include <optional>
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000019#include <string>
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000020#include <utility>
Marcel Hlopko20f4ce42021-11-02 08:20:00 +000021#include <variant>
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000022#include <vector>
23
Marcel Hlopko2ee23912022-05-09 06:13:55 -070024#include "absl/container/flat_hash_map.h"
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -070025#include "absl/log/check.h"
Lukasz Anforowiczfea0db92022-05-17 17:28:04 -070026#include "absl/status/statusor.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070027#include "absl/strings/string_view.h"
Marco Polettic61bcc42022-04-08 12:54:30 -070028#include "common/strong_int.h"
Marcel Hlopko3b254b32022-03-09 14:10:49 +000029#include "rs_bindings_from_cc/bazel_types.h"
Rosica Dejanovskae91d2992022-05-05 05:31:39 -070030#include "clang/AST/Decl.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070031#include "clang/AST/DeclBase.h"
Lukasz Anforowicz38310f32022-09-09 11:17:52 -070032#include "clang/AST/DeclTemplate.h"
Lukasz Anforowiczcec7a8a2022-04-27 10:24:51 -070033#include "clang/AST/RawCommentList.h"
34#include "llvm/ADT/APSInt.h"
35#include "llvm/ADT/Optional.h"
36#include "llvm/Support/FormatVariadic.h"
37#include "llvm/Support/JSON.h"
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000038
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -070039namespace crubit {
Marcel Hlopkobfd8d322021-08-02 12:28:52 +000040
Devin Jeanpierre5c87a722021-09-16 10:35:58 +000041namespace internal {
Devin Jeanpierredeea7892022-03-29 02:13:31 -070042// Pointers and LValue references.
Devin Jeanpierre5c87a722021-09-16 10:35:58 +000043inline constexpr absl::string_view kRustPtrMut = "*mut";
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +000044inline constexpr absl::string_view kRustPtrConst = "*const";
Googler4e1bc132021-12-06 10:10:42 +000045inline constexpr absl::string_view kRustRefMut = "&mut";
46inline constexpr absl::string_view kRustRefConst = "&";
Devin Jeanpierredeea7892022-03-29 02:13:31 -070047
48// RValue References
49inline constexpr absl::string_view kRustRvalueRefMut = "#RvalueReference mut";
50inline constexpr absl::string_view kRustRvalueRefConst =
51 "#RvalueReference const";
52
53// Function pointers.
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +000054inline constexpr absl::string_view kRustFuncPtr = "#funcPtr";
Devin Jeanpierredeea7892022-03-29 02:13:31 -070055
56// C++ types therein.
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +000057inline constexpr absl::string_view kCcPtr = "*";
Googler61dce3b2021-12-02 09:16:32 +000058inline constexpr absl::string_view kCcLValueRef = "&";
Devin Jeanpierredeea7892022-03-29 02:13:31 -070059inline constexpr absl::string_view kCcRValueRef = "&&";
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +000060inline constexpr absl::string_view kCcFuncValue = "#funcValue";
Devin Jeanpierredeea7892022-03-29 02:13:31 -070061
Googler56183012021-12-01 11:07:05 +000062inline constexpr int kJsonIndent = 2;
Devin Jeanpierre5c87a722021-09-16 10:35:58 +000063} // namespace internal
64
Marcel Hlopkof1123c82021-08-19 11:38:52 +000065// A name of a public header of the C++ library.
66class HeaderName {
67 public:
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000068 explicit HeaderName(std::string name) : name_(std::move(name)) {}
Marcel Hlopkof1123c82021-08-19 11:38:52 +000069
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000070 absl::string_view IncludePath() const { return name_; }
Marcel Hlopkof1123c82021-08-19 11:38:52 +000071
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000072 llvm::json::Value ToJson() const;
Marcel Hlopkof1123c82021-08-19 11:38:52 +000073
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000074 template <typename H>
75 friend H AbslHashValue(H h, const HeaderName& header_name) {
76 return H::combine(std::move(h), header_name.name_);
77 }
78
Marcel Hlopkof1123c82021-08-19 11:38:52 +000079 private:
80 // Header pathname in the format suitable for a google3-relative quote
81 // include.
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +000082 std::string name_;
Marcel Hlopkof1123c82021-08-19 11:38:52 +000083};
84
Marcel Hlopko7aa38a72021-11-11 07:39:51 +000085inline bool operator==(const HeaderName& lhs, const HeaderName& rhs) {
86 return lhs.IncludePath() == rhs.IncludePath();
87}
88
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +000089inline std::ostream& operator<<(std::ostream& o, const HeaderName& h) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +000090 return o << std::string(llvm::formatv("{0:2}", h.ToJson()));
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +000091}
92
Rosica Dejanovskad638cf52022-03-23 15:45:01 +000093// An int uniquely representing an Item. Since our IR goes through the JSON
Marcel Hlopko9c150da2021-11-12 10:30:03 +000094// serialization/deserialization at the moment, we need a way to restore graph
95// edges that don't follow the JSON tree structure (for example between types
Rosica Dejanovskad638cf52022-03-23 15:45:01 +000096// and records), as well as location of comments and items we don't yet support.
97// We use ItemIds for this.
98CRUBIT_DEFINE_STRONG_INT_TYPE(ItemId, uintptr_t);
Marcel Hlopko9c150da2021-11-12 10:30:03 +000099
Michael Forsterc0bc9262022-04-25 00:30:26 -0700100inline ItemId GenerateItemId(const clang::Decl* decl) {
Rosica Dejanovska6efd17f2022-05-11 08:09:57 -0700101 if (auto namespace_decl = clang::dyn_cast<clang::NamespaceDecl>(decl)) {
Kinuko Yasuda8dd84642022-08-17 09:19:47 -0700102 return ItemId(reinterpret_cast<uintptr_t>(namespace_decl));
Rosica Dejanovska6efd17f2022-05-11 08:09:57 -0700103 }
Kinuko Yasuda8dd84642022-08-17 09:19:47 -0700104 return ItemId(reinterpret_cast<uintptr_t>(decl->getCanonicalDecl()));
Michael Forsterc0bc9262022-04-25 00:30:26 -0700105}
106
107inline ItemId GenerateItemId(const clang::RawComment* comment) {
108 return ItemId(reinterpret_cast<uintptr_t>(comment));
109}
110
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700111// Returns the ID of the parent namespace, if such exists, and `llvm::None` for
112// top level decls.
113// We use this function to assign a parent namespace to all the IR items.
114// `llvm::Optional` is used because it integrates better with the `llvm::json`
115// library than `std::optional`.
116inline llvm::Optional<ItemId> GetEnclosingNamespaceId(const clang::Decl* decl) {
117 auto enclosing_namespace =
118 decl->getDeclContext()->getEnclosingNamespaceContext();
119 if (enclosing_namespace->isTranslationUnit()) return llvm::None;
Lukasz Anforowicz38310f32022-09-09 11:17:52 -0700120
121 // Class template specializations are always emitted in the top-level
122 // namespace. See also Importer::GetOrderedItemIdsOfTemplateInstantiations.
123 if (clang::isa<clang::ClassTemplateSpecializationDecl>(decl))
124 return llvm::None;
125
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700126 auto namespace_decl = clang::cast<clang::NamespaceDecl>(enclosing_namespace);
127 return GenerateItemId(namespace_decl);
128}
129
Googler64e4edb2021-12-03 12:17:38 +0000130// A numerical ID that uniquely identifies a lifetime.
Lukasz Anforowicze0d6b852022-03-17 15:40:38 +0000131CRUBIT_DEFINE_STRONG_INT_TYPE(LifetimeId, int);
Googler64e4edb2021-12-03 12:17:38 +0000132
133// A lifetime.
Marcel Hlopkoaf682a02022-04-08 07:27:14 -0700134struct LifetimeName {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000135 llvm::json::Value ToJson() const;
Googler64e4edb2021-12-03 12:17:38 +0000136
137 // Lifetime name. Unlike syn::Lifetime, this does not include the apostrophe.
138 //
139 // Note that this is not an identifier; the rules for what is a valid lifetime
140 // name are slightly different than for identifiers, so we simply use a
141 // std::string instead of an Identifier here.
142 std::string name;
143
144 LifetimeId id;
145};
146
Marcel Hlopkoaf682a02022-04-08 07:27:14 -0700147inline std::ostream& operator<<(std::ostream& o, const LifetimeName& l) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000148 return o << std::string(llvm::formatv("{0:2}", l.ToJson()));
Googler64e4edb2021-12-03 12:17:38 +0000149}
150
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000151// A C++ type involved in the bindings. It has the knowledge of how the type
152// is spelled in C++.
153struct CcType {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000154 llvm::json::Value ToJson() const;
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000155
156 // The name of the type. Examples:
157 // - "int32_t", "std::ptrdiff_t", "long long", "bool"
158 // - "void"
159 // - "&" or "*" (pointee stored in `type_args[0]`)
160 // - "#funcValue <callConv>" (compare with "#funcPtr <abi>" in RsType::name
161 // and note that Rust only supports function pointers; note that <callConv>
162 // in CcType doesn't map 1:1 to <abi> in RsType).
Lukasz Anforowicz58f27112022-03-15 17:51:03 +0000163 // - An empty string when `decl_id` is non-empty.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000164 std::string name;
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +0000165
Lukasz Anforowicz58f27112022-03-15 17:51:03 +0000166 // Id of a decl that this type corresponds to. `nullopt` when `name` is
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000167 // non-empty. `llvm::Optional` is used because it integrates better with
168 // `llvm::json` library than `std::optional`.
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000169 llvm::Optional<ItemId> decl_id;
Marcel Hlopko9c150da2021-11-12 10:30:03 +0000170
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +0000171 // The C++ const-qualification for the type.
172 //
Devin Jeanpierrec6c62eb2021-09-29 07:13:35 +0000173 // Note: there are two types for which cv-qualification does not do anything:
174 // references and functions. if `T` is either a function type like `void()`,
175 // or a reference type like `int&`, then `T`, `const T`, and `volatile T` are
176 // all the same type in C++.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000177 bool is_const = false;
Devin Jeanpierre184f9ac2021-09-17 13:47:03 +0000178
Googlerff7fc232021-12-02 09:43:00 +0000179 // Type arguments for a generic type. Examples:
180 // int has no type arguments.
181 // int* has a single type argument, int.
182 // tuple<int, float> has two type arguments, int and float.
183 std::vector<CcType> type_args = {};
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000184};
185
186// A Rust type involved in the bindings. It has the knowledge of how the type
187// is spelled in Rust.
188struct RsType {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000189 llvm::json::Value ToJson() const;
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000190
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000191 // The name of the type. Examples:
192 // - "i32" or "bool"
193 // - "()" (the unit type, equivalent of "void" in CcType)
194 // - "&", "&mut", "*const", "*mut" (pointee stored in `type_args[0]`)
195 // - "Option" (e.g. representing nullable, lifetime-annotated C++ pointer as
196 // `Option<&'a SomeOtherType>` - in this case `type_args[0]` is the generic
197 // argument representing the Rust reference type).
198 // - "#funcPtr <abi>" (function pointer; return type is the last elem in
199 // `type_args`; param types are stored in other `type_args`; <abi> would be
200 // replaced with "cdecl", "stdcall" or other Abi - see
201 // https://doc.rust-lang.org/reference/types/function-pointer.html);
Lukasz Anforowicz58f27112022-03-15 17:51:03 +0000202 // - An empty string when `decl_id` is non-empty.
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000203 std::string name;
204
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000205 // Id of a decl that this type corresponds to. `nullopt` when `name` is
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000206 // non-empty. `llvm::Optional` is used because it integrates better with
207 // `llvm::json` library than `std::optional`.
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000208 llvm::Optional<ItemId> decl_id;
Marcel Hlopko9c150da2021-11-12 10:30:03 +0000209
Googler64e4edb2021-12-03 12:17:38 +0000210 // Lifetime arguments for a generic type. Examples:
211 // *mut i32 has no lifetime arguments
212 // &'a 32 has a single lifetime argument, 'a.
213 // SomeType<'a, 'b> has two lifetime arguments, 'a and 'b.
Marcel Hlopkoaf682a02022-04-08 07:27:14 -0700214 // Lifetimes are identified by their unique ID. The corresponding LifetimeName
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000215 // will be found within the lifetime_params of a Func or Record or TypeAlias
216 // that uses this type underneath (as a parameter type, field type, or aliased
217 // type).
Googler64e4edb2021-12-03 12:17:38 +0000218 std::vector<LifetimeId> lifetime_args = {};
219
Googlerff7fc232021-12-02 09:43:00 +0000220 // Type arguments for a generic type. Examples:
221 // i32 has no type arguments.
222 // *mut i32 has a single type argument, i32.
223 // (i32, f32) has two type arguments, i32 and f32.
224 std::vector<RsType> type_args = {};
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000225};
226
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000227inline std::ostream& operator<<(std::ostream& o, const RsType& type) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000228 return o << std::string(llvm::formatv("{0:2}", type.ToJson()));
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000229}
230
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000231// A type involved in the bindings. The rs_type and cc_type will be treated
232// as interchangeable during bindings, and so should share the same layout.
233//
234// For example: a C++ pointer may be a usize in Rust, rather than a pointer, but
235// should almost certainly not be a u8, because u8 and pointers are sized and
236// aligned differently.
237struct MappedType {
238 static MappedType Void() { return Simple("()", "void"); }
239
240 /// Returns the MappedType for a non-templated/generic, non-cv-qualified type.
241 /// For example, Void() is Simple("()", "void").
242 static MappedType Simple(std::string rs_name, std::string cc_name) {
243 return MappedType{RsType{rs_name}, CcType{cc_name}};
244 }
245
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000246 static MappedType WithDeclId(ItemId decl_id) {
Lukasz Anforowicz58f27112022-03-15 17:51:03 +0000247 return MappedType{RsType{.decl_id = decl_id}, CcType{.decl_id = decl_id}};
Marcel Hlopko9c150da2021-11-12 10:30:03 +0000248 }
249
Googler4e1bc132021-12-06 10:10:42 +0000250 static MappedType PointerTo(MappedType pointee_type,
251 std::optional<LifetimeId> lifetime,
Googler02da3fb2021-12-06 11:59:19 +0000252 bool nullable = true);
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000253
Googler4e1bc132021-12-06 10:10:42 +0000254 static MappedType LValueReferenceTo(MappedType pointee_type,
Googler02da3fb2021-12-06 11:59:19 +0000255 std::optional<LifetimeId> lifetime);
Googler61dce3b2021-12-02 09:16:32 +0000256
Devin Jeanpierredeea7892022-03-29 02:13:31 -0700257 // Creates an Rvalue Reference mapped type.
258 //
259 // Note: we don't currently support rvalue references that do not have a
260 // lifetime. (Such a thing would require an "Rvalue Pointer" type -- probably
261 // spelled `Move<*mut T>` in Rust, although that doesn't work today due to
262 // the `P: DerefMut` bound in `Move<P>`.)
263 static MappedType RValueReferenceTo(MappedType pointee_type,
264 LifetimeId lifetime);
265
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000266 static MappedType FuncPtr(absl::string_view cc_call_conv,
267 absl::string_view rs_abi,
268 std::optional<LifetimeId> lifetime,
269 MappedType return_type,
270 std::vector<MappedType> param_types);
Lukasz Anforowicz92c81c32022-03-04 19:03:56 +0000271 static MappedType FuncRef(absl::string_view cc_call_conv,
272 absl::string_view rs_abi,
273 std::optional<LifetimeId> lifetime,
274 MappedType return_type,
275 std::vector<MappedType> param_types);
Lukasz Anforowiczcf230fd2022-02-18 19:20:39 +0000276
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000277 bool IsVoid() const { return rs_type.name == "()"; }
278
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000279 llvm::json::Value ToJson() const;
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000280
281 RsType rs_type;
282 CcType cc_type;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000283};
284
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000285inline std::ostream& operator<<(std::ostream& o, const MappedType& type) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000286 return o << std::string(llvm::formatv("{0:2}", type.ToJson()));
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000287}
288
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000289// An identifier involved in bindings.
290//
Devin Jeanpierree26437e2022-02-04 23:49:30 +0000291// For example, the identifier for the C++ function `int Add(int a, int b);`
292// is `Identifier("Add")`.
293//
294// This also includes operator names, such as "operator==". Non-symbol tokens in
295// the operator name are separated by a single space. For example:
296//
297// * `Identifier("operator==")`
298// * `Identifier("operator new[]")`
299// * `Identifier("operator co_await")`
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000300//
301// Invariants:
302// `identifier` cannot be empty.
303class Identifier {
304 public:
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +0000305 explicit Identifier(std::string identifier)
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000306 : identifier_(std::move(identifier)) {
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -0700307 CHECK(!identifier_.empty());
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000308 }
309
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +0000310 absl::string_view Ident() const { return identifier_; }
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000311
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000312 llvm::json::Value ToJson() const;
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000313
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000314 private:
Marcel Hlopkoa5f59ae2021-08-24 20:38:04 +0000315 std::string identifier_;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000316};
317
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000318inline std::ostream& operator<<(std::ostream& o, const Identifier& id) {
Googler56183012021-12-01 11:07:05 +0000319 return o << std::setw(internal::kJsonIndent) << id.Ident();
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000320}
321
Teddy Katz76fa42b2022-02-23 01:22:56 +0000322// An integer value in the range [-2**63, 2**64). This is intended to be used
323// to produce integer literals in Rust code while specifying the type
324// out-of-band.
325class IntegerConstant {
326 public:
327 explicit IntegerConstant(const llvm::APSInt& value) {
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -0700328 CHECK_LE(value.getSignificantBits(), 64);
Teddy Katz76fa42b2022-02-23 01:22:56 +0000329 is_negative_ = value < 0;
330 wrapped_value_ = static_cast<uint64_t>(value.getExtValue());
331 }
332 IntegerConstant(const IntegerConstant& other) = default;
333 IntegerConstant& operator=(const IntegerConstant& other) = default;
334
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000335 llvm::json::Value ToJson() const;
Teddy Katz76fa42b2022-02-23 01:22:56 +0000336
337 private:
338 // value < 0
339 bool is_negative_;
340
341 // value (mod 2**64)
342 uint64_t wrapped_value_;
343};
344
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000345class Operator {
346 public:
347 explicit Operator(std::string name) : name_(std::move(name)) {
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -0700348 CHECK(!name_.empty());
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000349 }
350
351 absl::string_view Name() const { return name_; }
352
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000353 llvm::json::Value ToJson() const;
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000354
355 private:
356 std::string name_;
357};
358
359inline std::ostream& operator<<(std::ostream& stream, const Operator& op) {
360 char first_char = op.Name()[0];
361 const char* separator = ('a' <= first_char) && (first_char <= 'z') ? " " : "";
362 return stream << std::setw(internal::kJsonIndent) << "`operator" << separator
363 << op.Name() << "`";
364}
365
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000366// A function parameter.
367//
368// Examples:
369// FuncParam of a C++ function `void Foo(int32_t a);` will be
Devin Jeanpierre29a25f12021-09-15 11:54:32 +0000370// `FuncParam{.type=Type{"i32", "int32_t"}, .identifier=Identifier("foo"))`.
Devin Jeanpierre601f14f2021-09-15 11:53:18 +0000371struct FuncParam {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000372 llvm::json::Value ToJson() const;
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000373
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000374 MappedType type;
Devin Jeanpierre601f14f2021-09-15 11:53:18 +0000375 Identifier identifier;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000376};
377
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000378inline std::ostream& operator<<(std::ostream& o, const FuncParam& param) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000379 return o << std::string(llvm::formatv("{0:2}", param.ToJson()));
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000380}
381
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000382enum SpecialName {
383 kDestructor,
384 kConstructor,
385};
386
387std::ostream& operator<<(std::ostream& o, const SpecialName& special_name);
388
389// A generalized notion of identifier, or an "Unqualified Identifier" in C++
390// jargon: https://en.cppreference.com/w/cpp/language/identifiers
391//
392// Note that constructors are given a separate variant, so that we can treat
393// them differently. After all, they are not invoked or defined like normal
394// functions.
Lukasz Anforowicz9c663ca2022-02-09 01:33:31 +0000395using UnqualifiedIdentifier = std::variant<Identifier, Operator, SpecialName>;
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000396llvm::json::Value toJSON(const UnqualifiedIdentifier& unqualified_identifier);
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000397
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000398struct MemberFuncMetadata {
399 enum ReferenceQualification : char {
400 kLValue, // void Foo() &;
401 kRValue, // void Foo() &&;
402 kUnqualified, // void Foo();
403 };
404
Lukasz Anforowicz71716b72022-01-26 17:05:05 +0000405 // TODO(lukasza): Consider extracting a separate ConstructorMetadata struct to
406 // account for the fact that 1) `is_explicit_ctor` applies only to
407 // constructors and 2) `is_const` and `is_virtual` never applies to
408 // constructors.
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000409 struct InstanceMethodMetadata {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000410 llvm::json::Value ToJson() const;
411
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000412 ReferenceQualification reference = kUnqualified;
413 bool is_const = false;
414 bool is_virtual = false;
Lukasz Anforowicz71716b72022-01-26 17:05:05 +0000415
416 // If the member function was a constructor with an `explicit` specifier.
417 bool is_explicit_ctor = false;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000418 };
419
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000420 llvm::json::Value ToJson() const;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000421
422 // The type that this is a member function for.
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000423 ItemId record_id;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000424
425 // Qualifiers for the instance method.
426 //
427 // If null, this is a static method.
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000428 //
429 // `llvm::Optional` is used because it integrates better with `llvm::json`
430 // library than `std::optional`.
431 llvm::Optional<InstanceMethodMetadata> instance_method_metadata;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000432};
433
Googler95f29a12022-01-07 07:47:26 +0000434// Source code location
435struct SourceLoc {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000436 llvm::json::Value ToJson() const;
Googler95f29a12022-01-07 07:47:26 +0000437
438 std::string filename;
Googlerf596aec2022-05-05 22:02:24 -0700439 uint64_t line;
440 uint64_t column;
Googler95f29a12022-01-07 07:47:26 +0000441};
442
443inline std::ostream& operator<<(std::ostream& o, const SourceLoc& r) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000444 return o << std::string(llvm::formatv("{0:2}", r.ToJson()));
Googler95f29a12022-01-07 07:47:26 +0000445}
446
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000447// A function involved in the bindings.
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000448struct Func {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000449 llvm::json::Value ToJson() const;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000450
Devin Jeanpierref2ec8712021-10-13 20:47:16 +0000451 UnqualifiedIdentifier name;
Googler6c3de122022-03-28 11:40:41 +0000452 BazelLabel owning_target;
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000453 llvm::Optional<std::string> doc_comment;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000454 std::string mangled_name;
Devin Jeanpierre09c6f452021-09-29 07:34:24 +0000455 MappedType return_type;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000456 std::vector<FuncParam> params;
Marcel Hlopkoaf682a02022-04-08 07:27:14 -0700457 std::vector<LifetimeName> lifetime_params;
Devin Jeanpierre4d33b592021-09-15 11:53:32 +0000458 bool is_inline;
Devin Jeanpierrec6877bb2021-10-13 20:47:54 +0000459 // If null, this is not a member function.
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000460 llvm::Optional<MemberFuncMetadata> member_func_metadata;
Lukasz Anforowicz0b6a6ac2022-03-22 22:32:23 +0000461 bool has_c_calling_convention = true;
Lukasz Anforowiczb1ff2e52022-05-16 10:54:23 -0700462 bool is_member_or_descendant_of_class_template = false;
Googler95f29a12022-01-07 07:47:26 +0000463 SourceLoc source_loc;
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000464 ItemId id;
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700465 llvm::Optional<ItemId> enclosing_namespace_id;
Michael VanBemmel7a4d4c02022-07-27 13:21:47 -0700466 // If present, this function should only generate top-level bindings if its
467 // arguments refer to this enclosing record according to the ADL rules.
468 //
469 // This could in principle be resolved while generating the IR, but the richer
470 // Rust type modeling in src_code_gen makes it much easier to do on the
471 // consuming end.
472 llvm::Optional<ItemId> adl_enclosing_record;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000473};
474
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000475inline std::ostream& operator<<(std::ostream& o, const Func& f) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000476 return o << std::string(llvm::formatv("{0:2}", f.ToJson()));
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000477}
478
Googler2e85f342021-09-17 07:04:07 +0000479// Access specifier for a member or base class.
480enum AccessSpecifier {
481 kPublic,
482 kProtected,
483 kPrivate,
484};
485
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000486std::ostream& operator<<(std::ostream& o, const AccessSpecifier& access);
487
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000488// A field (non-static member variable) of a record.
Michael Forster6e95ad32021-09-15 21:01:21 +0000489struct Field {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000490 llvm::json::Value ToJson() const;
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000491
Lukasz Anforowicze200e8a2022-05-18 12:36:33 -0700492 // Name of the field. This may be missing for "unnamed members" - see:
493 // - https://en.cppreference.com/w/c/language/struct
494 // - https://rust-lang.github.io/rfcs/2102-unnamed-fields.html
Michael Forster7a004912022-05-12 07:45:57 -0700495 llvm::Optional<Identifier> identifier;
Lukasz Anforowicze200e8a2022-05-18 12:36:33 -0700496
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000497 llvm::Optional<std::string> doc_comment;
Lukasz Anforowiczfea0db92022-05-17 17:28:04 -0700498 absl::StatusOr<MappedType> type;
Googler2e85f342021-09-17 07:04:07 +0000499 AccessSpecifier access;
Lukasz Anforowicze200e8a2022-05-18 12:36:33 -0700500 uint64_t offset; // Field offset in bits.
501 uint64_t size; // Field size in bits.
502 bool is_no_unique_address; // True if the field is [[no_unique_address]].
Michael Forster82c02d32022-05-20 21:47:33 -0700503 bool is_bitfield; // True if the field is a bitfield.
Kinuko Yasuda6ff59f12022-08-11 08:41:45 -0700504 bool is_inheritable; // True if the field is inheritable.
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000505};
506
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000507inline std::ostream& operator<<(std::ostream& o, const Field& f) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000508 return o << std::string(llvm::formatv("{0:2}", f.ToJson()));
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000509}
510
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000511// Information about special member functions.
512//
513// Nontrivial definitions are divided into two: there are nontrivial definitions
514// which are nontrivial only due to a member variable which defines the special
515// member function, and those which are nontrivial because the operation was
516// user defined for the object itself, or for any base class.
517//
Devin Jeanpierrecd0ba852021-10-21 12:55:47 +0000518// This allows us to sidestep calling C++ implementations of special member
Devin Jeanpierrebe2f33b2021-10-21 12:54:19 +0000519// functions in narrow cases: even for a nontrivial special member function, if
520// it is kNontrivialMembers, we can directly implement it in Rust in terms of
521// the member variables.
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700522enum class SpecialMemberFunc : char {
523 kTrivial,
524 // Nontrivial, but only because of a member variable with a nontrivial
525 // special member function.
526 kNontrivialMembers,
527 // Nontrivial because of a user-defined special member function in this or a
528 // base class. (May *also* be nontrivial due to member variables.)
529 kNontrivialUserDefined,
530 // Deleted or non-public.
531 kUnavailable,
Devin Jeanpierre07931272021-10-05 11:40:13 +0000532};
533
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700534llvm::json::Value toJSON(const SpecialMemberFunc& f);
Devin Jeanpierre07931272021-10-05 11:40:13 +0000535
536inline std::ostream& operator<<(std::ostream& o, const SpecialMemberFunc& f) {
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700537 return o << std::string(llvm::formatv("{0:2}", toJSON(f)));
Devin Jeanpierre07931272021-10-05 11:40:13 +0000538}
539
Devin Jeanpierre56777022022-02-03 01:57:15 +0000540// A base class subobject of a struct or class.
541struct BaseClass {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000542 llvm::json::Value ToJson() const;
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000543 ItemId base_record_id;
Devin Jeanpierre56777022022-02-03 01:57:15 +0000544
545 // The offset the base class subobject is located at. This is always nonempty
546 // for nonvirtual inheritance, and always empty if a virtual base class is
547 // anywhere in the inheritance chain.
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000548 //
549 // `llvm::Optional` is used because it integrates better with `llvm::json`
550 // library than `std::optional`.
551 llvm::Optional<int64_t> offset;
Devin Jeanpierre56777022022-02-03 01:57:15 +0000552};
553
Lukasz Anforowiczd4742ff2022-07-11 17:05:02 -0700554enum RecordType {
555 // `struct` in Rust and C++
556 kStruct,
557
558 // `union` in Rust and C++
559 kUnion,
560
561 // `class` in C++. This is distinct from `kStruct` to avoid generating
562 // `struct SomeClass` in `..._rs_api_impl.cc` and getting `-Wmismatched-tags`
563 // warnings (see also b/238212337).
564 kClass,
565};
566
567std::ostream& operator<<(std::ostream& o, const RecordType& record_type);
568
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000569// A record (struct, class, union).
Googler949b7d92021-09-17 07:46:11 +0000570struct Record {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000571 llvm::json::Value ToJson() const;
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000572
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +0000573 // `rs_name` and `cc_name` are typically equal, but they may be different for
574 // template instantiations (when `cc_name` is similar to `MyStruct<int>` and
575 // `rs_name` is similar to "__CcTemplateInst8MyStructIiE").
576 std::string rs_name;
577 std::string cc_name;
Lukasz Anforowicz3f133972022-09-01 09:01:02 -0700578 std::string mangled_cc_name;
Lukasz Anforowicz4c3a2cc2022-03-11 00:24:49 +0000579
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000580 ItemId id;
Googler6c3de122022-03-28 11:40:41 +0000581 BazelLabel owning_target;
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000582 llvm::Optional<std::string> doc_comment;
Devin Jeanpierre56777022022-02-03 01:57:15 +0000583 std::vector<BaseClass> unambiguous_public_bases;
Googler949b7d92021-09-17 07:46:11 +0000584 std::vector<Field> fields;
Marcel Hlopkoaf682a02022-04-08 07:27:14 -0700585 std::vector<LifetimeName> lifetime_params;
Kinuko Yasuda54b75d72022-08-18 10:09:54 -0700586 // Size and alignment in bytes. `original_cc_size` may be different from
587 // `size` when the size this record tells (i.e. sizeof(record)) is not aligned
588 // by `alignment` but actually occupies the size that is aligned. This usually
589 // only happens when `is_anon_record_with_typedef` is true and alignment is
590 // given for the typedef (but not for the record).
Googler6986c072021-09-17 13:54:56 +0000591 int64_t size;
Kinuko Yasuda54b75d72022-08-18 10:09:54 -0700592 int64_t original_cc_size;
Googler6986c072021-09-17 13:54:56 +0000593 int64_t alignment;
Devin Jeanpierreb2cd0212021-10-01 07:16:23 +0000594
Devin Jeanpierre1221c2a2022-05-05 22:36:22 -0700595 // True if any base classes exist.
596 bool is_derived_class;
Devin Jeanpierrec80e6242022-02-03 01:56:40 +0000597
598 // True if the alignment may differ from what the fields would imply.
599 //
600 // For example, a base class or [[no_unique_address]] of alignment 8 should
601 // cause the record to have alignment at least 8. Since the field cannot be
602 // aligned due to layout issues, the parent struct must instead receive an
603 // alignment adjustment as necessary, via .override_alignment=true.
604 //
Devin Jeanpierrec80e6242022-02-03 01:56:40 +0000605 // More information: docs/struct_layout
606 bool override_alignment = false;
607
Devin Jeanpierre07931272021-10-05 11:40:13 +0000608 // Special member functions.
Lukasz Anforowiczff7df4a2022-06-02 14:27:45 -0700609 SpecialMemberFunc copy_constructor = SpecialMemberFunc::kUnavailable;
610 SpecialMemberFunc move_constructor = SpecialMemberFunc::kUnavailable;
611 SpecialMemberFunc destructor = SpecialMemberFunc::kUnavailable;
Devin Jeanpierre07931272021-10-05 11:40:13 +0000612
Devin Jeanpierreb2cd0212021-10-01 07:16:23 +0000613 // Whether this type is passed by value as if it were a trivial type (the same
614 // as it would be if it were a struct in C).
615 //
616 // This can be either due to language rules (it *is* a trivial type), or due
617 // to the usage of a Clang attribute that forces trivial for calls:
618 //
619 // * https://eel.is/c++draft/class.temporary#3
620 // * https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
621 bool is_trivial_abi = false;
Devin Jeanpierree6e16652021-12-22 15:54:46 +0000622
Teddy Katzd2cd1422022-04-04 09:41:33 -0700623 // Whether this type can be inherited from.
Devin Jeanpierree6e16652021-12-22 15:54:46 +0000624 //
Teddy Katzd2cd1422022-04-04 09:41:33 -0700625 // A type might not be inheritable if:
626 // * The type was explicitly marked final
627 // * A core function like the destructor was marked final
628 // * The type is a C++ union, which does not support inheritance
629 bool is_inheritable = false;
630
Devin Jeanpierreccb67672022-08-17 10:05:47 -0700631 // Whether this type is abstract.
632 bool is_abstract = false;
633
Lukasz Anforowiczd4742ff2022-07-11 17:05:02 -0700634 // Whether this `Record` corresponds to a C++ `union`, `struct`, or `class`.
635 RecordType record_type;
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700636
Devin Jeanpierrea2be2a22022-05-18 18:59:05 -0700637 // Whether this type can be initialized using aggregate initialization syntax.
638 //
639 // For more context, see:
640 // * https://en.cppreference.com/w/cpp/types/is_aggregate
641 // * https://en.cppreference.com/w/cpp/language/aggregate_initialization
642 bool is_aggregate = false;
643
Kinuko Yasuda8dd84642022-08-17 09:19:47 -0700644 // It is an anoymous record with a typedef name.
645 bool is_anon_record_with_typedef = false;
646
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700647 // True when this record is created from an explicit class template
648 // instantiation definition (which is also what cc_template!{} macro results
649 // in).
650 bool is_explicit_class_template_instantiation_definition = false;
651
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700652 std::vector<ItemId> child_item_ids;
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700653 llvm::Optional<ItemId> enclosing_namespace_id;
Marcel Hlopkob4b28742021-09-15 12:45:20 +0000654};
655
Devin Jeanpierrec0543eb2022-04-20 16:00:34 -0700656// A forward-declared record (e.g. `struct Foo;`)
657struct IncompleteRecord {
658 llvm::json::Value ToJson() const;
659 std::string cc_name;
Rosica Dejanovskae12d7172022-06-22 12:20:17 -0700660 std::string rs_name;
Devin Jeanpierrec0543eb2022-04-20 16:00:34 -0700661 ItemId id;
662 BazelLabel owning_target;
Lukasz Anforowicz8dd51792022-08-31 10:11:17 -0700663 RecordType record_type;
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700664 llvm::Optional<ItemId> enclosing_namespace_id;
Devin Jeanpierrec0543eb2022-04-20 16:00:34 -0700665};
666
Teddy Katz76fa42b2022-02-23 01:22:56 +0000667struct Enumerator {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000668 llvm::json::Value ToJson() const;
Teddy Katz76fa42b2022-02-23 01:22:56 +0000669
670 Identifier identifier;
671 IntegerConstant value;
672};
673
674struct Enum {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000675 llvm::json::Value ToJson() const;
Teddy Katz76fa42b2022-02-23 01:22:56 +0000676
677 Identifier identifier;
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000678 ItemId id;
Googler6c3de122022-03-28 11:40:41 +0000679 BazelLabel owning_target;
Teddy Katz76fa42b2022-02-23 01:22:56 +0000680 MappedType underlying_type;
681 std::vector<Enumerator> enumerators;
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700682 llvm::Optional<ItemId> enclosing_namespace_id;
Teddy Katz76fa42b2022-02-23 01:22:56 +0000683};
684
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000685inline std::ostream& operator<<(std::ostream& o, const Record& r) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000686 return o << std::string(llvm::formatv("{0:2}", r.ToJson()));
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000687}
688
Googler098c4582022-01-10 12:29:34 +0000689// A type alias (defined either using `typedef` or `using`).
690struct TypeAlias {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000691 llvm::json::Value ToJson() const;
Googler098c4582022-01-10 12:29:34 +0000692
693 Identifier identifier;
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000694 ItemId id;
Googler6c3de122022-03-28 11:40:41 +0000695 BazelLabel owning_target;
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000696 llvm::Optional<std::string> doc_comment;
Googler098c4582022-01-10 12:29:34 +0000697 MappedType underlying_type;
Devin Jeanpierre5fecde52022-09-14 06:53:39 -0700698 SourceLoc source_loc;
699 llvm::Optional<ItemId> enclosing_record_id;
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700700 llvm::Optional<ItemId> enclosing_namespace_id;
Googler098c4582022-01-10 12:29:34 +0000701};
702
703inline std::ostream& operator<<(std::ostream& o, const TypeAlias& t) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000704 return o << std::string(llvm::formatv("{0:2}", t.ToJson()));
Googler098c4582022-01-10 12:29:34 +0000705}
706
Michael Forster523dbd42021-10-12 11:05:44 +0000707// A placeholder for an item that we can't generate bindings for (yet)
708struct UnsupportedItem {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000709 llvm::json::Value ToJson() const;
Michael Forster523dbd42021-10-12 11:05:44 +0000710
711 // TODO(forster): We could show the original declaration in the generated
712 // message (potentially also for successfully imported items).
713
714 // Qualified name of the item for which we couldn't generate bindings
715 std::string name;
716
717 // Explanation of why we couldn't generate bindings
718 // TODO(forster): We should support multiple reasons per unsupported item.
719 std::string message;
Michael Forster6a184ad2021-10-12 13:04:05 +0000720 SourceLoc source_loc;
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000721 ItemId id;
Michael Forster523dbd42021-10-12 11:05:44 +0000722};
723
724inline std::ostream& operator<<(std::ostream& o, const UnsupportedItem& r) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000725 return o << std::string(llvm::formatv("{0:2}", r.ToJson()));
Michael Forster523dbd42021-10-12 11:05:44 +0000726}
727
Michael Forsterf1dce422021-10-13 09:50:16 +0000728struct Comment {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000729 llvm::json::Value ToJson() const;
Michael Forsterf1dce422021-10-13 09:50:16 +0000730
731 std::string text;
Rosica Dejanovskad638cf52022-03-23 15:45:01 +0000732 ItemId id;
Michael Forsterf1dce422021-10-13 09:50:16 +0000733};
734
735inline std::ostream& operator<<(std::ostream& o, const Comment& r) {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000736 return o << std::string(llvm::formatv("{0:2}", r.ToJson()));
Michael Forsterf1dce422021-10-13 09:50:16 +0000737}
738
Rosica Dejanovskadd9a9032022-04-12 07:34:41 -0700739struct Namespace {
740 llvm::json::Value ToJson() const;
741
742 Identifier name;
743 ItemId id;
Rosica Dejanovska6efd17f2022-05-11 08:09:57 -0700744 ItemId canonical_namespace_id;
Rosica Dejanovskadd9a9032022-04-12 07:34:41 -0700745 BazelLabel owning_target;
746 std::vector<ItemId> child_item_ids;
Rosica Dejanovskae91d2992022-05-05 05:31:39 -0700747 llvm::Optional<ItemId> enclosing_namespace_id;
Devin Jeanpierrefe6aaea2022-09-09 12:33:50 -0700748 bool is_inline = false;
Rosica Dejanovskadd9a9032022-04-12 07:34:41 -0700749};
750
751inline std::ostream& operator<<(std::ostream& o, const Namespace& n) {
752 return o << std::string(llvm::formatv("{0:2}", n.ToJson()));
753}
754
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000755// A complete intermediate representation of bindings for publicly accessible
756// declarations of a single C++ library.
Devin Jeanpierre0d5d0d42021-09-16 10:37:21 +0000757struct IR {
Lukasz Anforowicz3b4be122022-03-16 00:09:35 +0000758 llvm::json::Value ToJson() const;
Marcel Hlopko42abfc82021-08-09 07:03:17 +0000759
Michael Forster523dbd42021-10-12 11:05:44 +0000760 template <typename T>
Googler1661eee2021-12-01 12:36:19 +0000761 std::vector<const T*> get_items_if() const {
762 std::vector<const T*> filtered_items;
763 for (const auto& item : items) {
Michael Forster523dbd42021-10-12 11:05:44 +0000764 if (auto* filtered_item = std::get_if<T>(&item)) {
765 filtered_items.push_back(filtered_item);
766 }
767 }
768 return filtered_items;
769 }
770
Marcel Hlopkof1123c82021-08-19 11:38:52 +0000771 // Collection of public headers that were used to construct the AST this `IR`
772 // is generated from.
Devin Jeanpierre0d5d0d42021-09-16 10:37:21 +0000773 std::vector<HeaderName> used_headers;
Googler6c3de122022-03-28 11:40:41 +0000774 BazelLabel current_target;
Michael Forster365bba12022-01-24 16:56:06 +0000775
Devin Jeanpierrec0543eb2022-04-20 16:00:34 -0700776 using Item = std::variant<Func, Record, IncompleteRecord, Enum, TypeAlias,
777 UnsupportedItem, Comment, Namespace>;
Michael Forster365bba12022-01-24 16:56:06 +0000778 std::vector<Item> items;
Rosica Dejanovskab2bd59e2022-04-11 09:02:03 -0700779 std::vector<ItemId> top_level_item_ids;
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000780};
781
Marcel Hlopko3f771a92022-05-09 06:09:59 -0700782inline std::string IrToJson(const IR& ir) {
783 return std::string(llvm::formatv("{0:2}", ir.ToJson()));
784}
785
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000786inline std::ostream& operator<<(std::ostream& o, const IR& ir) {
Marcel Hlopko3f771a92022-05-09 06:09:59 -0700787 return o << IrToJson(ir);
Devin Jeanpierre2d5718a2021-10-05 11:39:34 +0000788}
Kinuko Yasuda8dd84642022-08-17 09:19:47 -0700789
Devin Jeanpierre1bcd7262022-10-04 20:07:59 -0700790// Utility function to convert items to string.
791std::string ItemToString(const IR::Item& item);
792inline std::string ItemToString(const std::optional<IR::Item>& item) {
793 if (item.has_value()) return ItemToString(*item);
794 return "null";
795}
796
Marcel Hlopkof15e8ce2022-04-08 08:46:09 -0700797} // namespace crubit
Marcel Hlopkobfd8d322021-08-02 12:28:52 +0000798
Dmitri Gribenkoe4e77d02022-03-17 14:09:39 +0000799#endif // CRUBIT_RS_BINDINGS_FROM_CC_IR_H_