Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 1 | // 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 | #include "rs_bindings_from_cc/ast_visitor.h" |
| 6 | |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame] | 7 | #include <stdint.h> |
| 8 | |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 9 | #include <algorithm> |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 10 | #include <memory> |
Marcel Hlopko | 20f4ce4 | 2021-11-02 08:20:00 +0000 | [diff] [blame] | 11 | #include <optional> |
Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 12 | #include <string> |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 13 | #include <tuple> |
Marcel Hlopko | 20f4ce4 | 2021-11-02 08:20:00 +0000 | [diff] [blame] | 14 | #include <utility> |
| 15 | #include <variant> |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 16 | #include <vector> |
Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 17 | |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 18 | #include "base/logging.h" |
Devin Jeanpierre | d3f959f | 2021-10-27 18:47:50 +0000 | [diff] [blame] | 19 | #include "rs_bindings_from_cc/ast_convert.h" |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 20 | #include "rs_bindings_from_cc/bazel_types.h" |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 21 | #include "rs_bindings_from_cc/ir.h" |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 22 | #include "third_party/absl/container/flat_hash_map.h" |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 23 | #include "third_party/absl/container/flat_hash_set.h" |
Marcel Hlopko | 20f4ce4 | 2021-11-02 08:20:00 +0000 | [diff] [blame] | 24 | #include "third_party/absl/status/status.h" |
| 25 | #include "third_party/absl/status/statusor.h" |
| 26 | #include "third_party/absl/strings/cord.h" |
Lukasz Anforowicz | 0c816f1 | 2021-12-15 17:41:49 +0000 | [diff] [blame] | 27 | #include "third_party/absl/strings/str_cat.h" |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 28 | #include "third_party/absl/strings/string_view.h" |
Michael Forster | 1de27b8 | 2021-09-17 07:22:22 +0000 | [diff] [blame] | 29 | #include "third_party/absl/strings/substitute.h" |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 30 | #include "third_party/llvm/llvm-project/clang/include/clang/AST/ASTContext.h" |
Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 31 | #include "third_party/llvm/llvm-project/clang/include/clang/AST/Decl.h" |
Googler | 2e85f34 | 2021-09-17 07:04:07 +0000 | [diff] [blame] | 32 | #include "third_party/llvm/llvm-project/clang/include/clang/AST/DeclCXX.h" |
Googler | 846e1fc | 2022-01-10 13:14:57 +0000 | [diff] [blame] | 33 | #include "third_party/llvm/llvm-project/clang/include/clang/AST/DeclTemplate.h" |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 34 | #include "third_party/llvm/llvm-project/clang/include/clang/AST/Mangle.h" |
Michael Forster | 028800b | 2021-10-05 12:39:59 +0000 | [diff] [blame] | 35 | #include "third_party/llvm/llvm-project/clang/include/clang/AST/RawCommentList.h" |
Googler | 6986c07 | 2021-09-17 13:54:56 +0000 | [diff] [blame] | 36 | #include "third_party/llvm/llvm-project/clang/include/clang/AST/RecordLayout.h" |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 37 | #include "third_party/llvm/llvm-project/clang/include/clang/AST/Type.h" |
Michael Forster | 6a184ad | 2021-10-12 13:04:05 +0000 | [diff] [blame] | 38 | #include "third_party/llvm/llvm-project/clang/include/clang/Basic/SourceLocation.h" |
Michael Forster | 028800b | 2021-10-05 12:39:59 +0000 | [diff] [blame] | 39 | #include "third_party/llvm/llvm-project/clang/include/clang/Basic/SourceManager.h" |
Googler | 2e85f34 | 2021-09-17 07:04:07 +0000 | [diff] [blame] | 40 | #include "third_party/llvm/llvm-project/clang/include/clang/Basic/Specifiers.h" |
Marcel Hlopko | 20f4ce4 | 2021-11-02 08:20:00 +0000 | [diff] [blame] | 41 | #include "third_party/llvm/llvm-project/clang/include/clang/Sema/Sema.h" |
Rosica Dejanovska | d0fc294 | 2022-01-21 11:26:00 +0000 | [diff] [blame] | 42 | #include "third_party/llvm/llvm-project/llvm/include/llvm/ADT/Optional.h" |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 43 | #include "third_party/llvm/llvm-project/llvm/include/llvm/Support/Casting.h" |
Googler | 06f2c9a | 2022-01-05 12:00:47 +0000 | [diff] [blame] | 44 | #include "util/gtl/flat_map.h" |
Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 45 | |
| 46 | namespace rs_bindings_from_cc { |
| 47 | |
Michael Forster | b836c58 | 2022-01-21 11:20:22 +0000 | [diff] [blame] | 48 | constexpr absl::string_view kTypeStatusPayloadUrl = |
Michael Forster | dc683af | 2021-09-17 08:51:28 +0000 | [diff] [blame] | 49 | "type.googleapis.com/devtools.rust.cc_interop.rs_binding_from_cc.type"; |
| 50 | |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 51 | // A mapping of C++ standard types to their equivalent Rust types. |
| 52 | // To produce more idiomatic results, these types receive special handling |
| 53 | // instead of using the generic type mapping mechanism. |
| 54 | static constexpr auto kWellKnownTypes = |
| 55 | gtl::fixed_flat_map_of<absl::string_view, absl::string_view>({ |
| 56 | {"ptrdiff_t", "isize"}, |
| 57 | {"intptr_t", "isize"}, |
| 58 | {"size_t", "usize"}, |
| 59 | {"uintptr_t", "usize"}, |
Googler | 4e50488 | 2022-01-13 10:03:19 +0000 | [diff] [blame] | 60 | {"std::ptrdiff_t", "isize"}, |
| 61 | {"std::intptr_t", "isize"}, |
| 62 | {"std::size_t", "usize"}, |
| 63 | {"std::uintptr_t", "usize"}, |
| 64 | |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 65 | {"int8_t", "i8"}, |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 66 | {"int16_t", "i16"}, |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 67 | {"int32_t", "i32"}, |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 68 | {"int64_t", "i64"}, |
Googler | 4e50488 | 2022-01-13 10:03:19 +0000 | [diff] [blame] | 69 | {"std::int8_t", "i8"}, |
| 70 | {"std::int16_t", "i16"}, |
| 71 | {"std::int32_t", "i32"}, |
| 72 | {"std::int64_t", "i64"}, |
| 73 | |
| 74 | {"uint8_t", "u8"}, |
| 75 | {"uint16_t", "u16"}, |
| 76 | {"uint32_t", "u32"}, |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 77 | {"uint64_t", "u64"}, |
Googler | 4e50488 | 2022-01-13 10:03:19 +0000 | [diff] [blame] | 78 | {"std::uint8_t", "u8"}, |
| 79 | {"std::uint16_t", "u16"}, |
| 80 | {"std::uint32_t", "u32"}, |
| 81 | {"std::uint64_t", "u64"}, |
| 82 | |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 83 | {"char16_t", "u16"}, |
| 84 | {"char32_t", "u32"}, |
| 85 | {"wchar_t", "i32"}, |
| 86 | }); |
| 87 | |
Marcel Hlopko | 264b9ad | 2021-12-02 21:06:44 +0000 | [diff] [blame] | 88 | static DeclId GenerateDeclId(const clang::Decl* decl) { |
Marcel Hlopko | 9c150da | 2021-11-12 10:30:03 +0000 | [diff] [blame] | 89 | return DeclId(reinterpret_cast<uintptr_t>(decl->getCanonicalDecl())); |
| 90 | } |
| 91 | |
Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 92 | bool AstVisitor::TraverseDecl(clang::Decl* decl) { |
Googler | acea5b9 | 2022-01-04 14:00:31 +0000 | [diff] [blame] | 93 | // TODO(mboehme): I'm not sure if TraverseDecl() is supposed to be called with |
| 94 | // null pointers or whether this is a bug in RecursiveASTVisitor, but I've |
| 95 | // seen null pointers occur here in practice. In the case where this occurred, |
| 96 | // TraverseDecl was being called from TraverseTemplateTemplateParmDecl(). |
| 97 | if (!decl) { |
| 98 | return true; |
| 99 | } |
| 100 | |
Googler | e0a9478 | 2022-01-04 14:06:02 +0000 | [diff] [blame] | 101 | // Skip declarations that we've already seen, except for namespaces, which |
| 102 | // can and typically will contain new declarations when they are "reopened". |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 103 | if (seen_decls_.contains(decl->getCanonicalDecl()) && |
Googler | e0a9478 | 2022-01-04 14:06:02 +0000 | [diff] [blame] | 104 | !clang::isa<clang::NamespaceDecl>(decl)) { |
Googler | c8a8e73 | 2021-10-19 07:49:24 +0000 | [diff] [blame] | 105 | return true; |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 106 | } |
Googler | c8a8e73 | 2021-10-19 07:49:24 +0000 | [diff] [blame] | 107 | |
Googler | c68cd5a | 2021-10-19 09:02:56 +0000 | [diff] [blame] | 108 | const clang::DeclContext* decl_context = decl->getDeclContext(); |
| 109 | if (decl_context && decl_context->isNamespace()) { |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 110 | PushUnsupportedItem(decl, |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 111 | "Items contained in namespaces are not supported yet", |
| 112 | decl->getBeginLoc()); |
| 113 | |
Googler | c8a8e73 | 2021-10-19 07:49:24 +0000 | [diff] [blame] | 114 | return true; |
| 115 | } |
| 116 | |
| 117 | // Emit all comments in the current file before the decl |
| 118 | comment_manager_.TraverseDecl(decl); |
| 119 | |
| 120 | return Base::TraverseDecl(decl); |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 121 | } |
| 122 | |
| 123 | bool AstVisitor::TraverseTranslationUnitDecl( |
| 124 | clang::TranslationUnitDecl* translation_unit_decl) { |
Michael Forster | d3ef1e9 | 2021-10-12 16:15:31 +0000 | [diff] [blame] | 125 | ctx_ = &translation_unit_decl->getASTContext(); |
| 126 | mangler_.reset(ctx_->createMangleContext()); |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 127 | |
Marcel Hlopko | 7aa38a7 | 2021-11-11 07:39:51 +0000 | [diff] [blame] | 128 | for (const HeaderName& header_name : public_header_names_) { |
| 129 | ir_.used_headers.push_back(header_name); |
Marcel Hlopko | f1123c8 | 2021-08-19 11:38:52 +0000 | [diff] [blame] | 130 | } |
| 131 | |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 132 | ir_.current_target = current_target_; |
| 133 | |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 134 | bool result = Base::TraverseTranslationUnitDecl(translation_unit_decl); |
| 135 | |
| 136 | // Emit comments after the last decl |
| 137 | comment_manager_.FlushComments(); |
| 138 | |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 139 | EmitIRItems(); |
| 140 | |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 141 | return result; |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 142 | } |
| 143 | |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 144 | void AstVisitor::EmitIRItems() { |
Lukasz Anforowicz | bdf70d3 | 2022-01-26 19:06:21 +0000 | [diff] [blame] | 145 | using OrderedItem = std::tuple<clang::SourceRange, int, IR::Item>; |
| 146 | clang::SourceManager& sm = ctx_->getSourceManager(); |
| 147 | auto is_less_than = [&sm](const OrderedItem& a, const OrderedItem& b) { |
| 148 | auto a_range = std::get<0>(a); |
| 149 | auto b_range = std::get<0>(b); |
| 150 | |
| 151 | if (!a_range.isValid() || !b_range.isValid()) { |
| 152 | if (a_range.isValid() != b_range.isValid()) |
| 153 | return !a_range.isValid() && b_range.isValid(); |
| 154 | } else { |
| 155 | if (a_range.getBegin() != b_range.getBegin()) { |
| 156 | return sm.isBeforeInTranslationUnit(a_range.getBegin(), |
| 157 | b_range.getBegin()); |
| 158 | } |
| 159 | if (a_range.getEnd() != b_range.getEnd()) { |
| 160 | return sm.isBeforeInTranslationUnit(a_range.getEnd(), b_range.getEnd()); |
| 161 | } |
| 162 | } |
| 163 | return std::get<1>(a) < std::get<1>(b); |
| 164 | }; |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 165 | |
| 166 | // We emit IR items in the order of the decls they were generated for. |
| 167 | // For decls that emit multiple items we use a stable, but arbitrary order. |
Lukasz Anforowicz | bdf70d3 | 2022-01-26 19:06:21 +0000 | [diff] [blame] | 168 | std::vector<OrderedItem> items; |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 169 | for (const auto& [decl, decl_items] : seen_decls_) { |
| 170 | for (const auto& decl_item : decl_items) { |
| 171 | int local_order; |
| 172 | |
| 173 | if (clang::isa<clang::RecordDecl>(decl)) { |
| 174 | local_order = decl->getDeclContext()->isRecord() ? 1 : 0; |
| 175 | } else if (auto ctor = clang::dyn_cast<clang::CXXConstructorDecl>(decl)) { |
| 176 | local_order = ctor->isDefaultConstructor() ? 2 |
| 177 | : ctor->isCopyConstructor() ? 3 |
| 178 | : ctor->isMoveConstructor() ? 4 |
| 179 | : 5; |
| 180 | } else if (clang::isa<clang::CXXDestructorDecl>(decl)) { |
| 181 | local_order = 6; |
| 182 | } else { |
| 183 | local_order = 7; |
| 184 | } |
| 185 | |
| 186 | items.push_back( |
Lukasz Anforowicz | bdf70d3 | 2022-01-26 19:06:21 +0000 | [diff] [blame] | 187 | std::make_tuple(decl->getSourceRange(), local_order, decl_item)); |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 188 | } |
| 189 | } |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 190 | for (auto comment : comment_manager_.comments()) { |
| 191 | items.push_back(std::make_tuple( |
Lukasz Anforowicz | bdf70d3 | 2022-01-26 19:06:21 +0000 | [diff] [blame] | 192 | comment->getSourceRange(), 0 /* local_order */, |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 193 | Comment{.text = comment->getFormattedText(sm, sm.getDiagnostics())})); |
| 194 | } |
Lukasz Anforowicz | bdf70d3 | 2022-01-26 19:06:21 +0000 | [diff] [blame] | 195 | std::stable_sort(items.begin(), items.end(), is_less_than); |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 196 | |
| 197 | for (const auto& item : items) { |
| 198 | ir_.items.push_back(std::get<2>(item)); |
| 199 | } |
| 200 | } |
| 201 | |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 202 | bool AstVisitor::VisitFunctionDecl(clang::FunctionDecl* function_decl) { |
Marcel Hlopko | 36ced2d | 2021-12-02 10:47:37 +0000 | [diff] [blame] | 203 | if (!IsFromCurrentTarget(function_decl)) return true; |
Lukasz Anforowicz | 0a1b480 | 2021-12-22 15:30:56 +0000 | [diff] [blame] | 204 | if (function_decl->isDeleted()) return true; |
Marcel Hlopko | 3df195b | 2022-01-26 14:15:03 +0000 | [diff] [blame] | 205 | if (function_decl->isTemplated()) { |
| 206 | PushUnsupportedItem(function_decl, |
| 207 | "Function templates are not supported yet", |
| 208 | function_decl->getBeginLoc()); |
| 209 | } |
Marcel Hlopko | 36ced2d | 2021-12-02 10:47:37 +0000 | [diff] [blame] | 210 | |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 211 | devtools_rust::LifetimeSymbolTable lifetime_symbol_table; |
| 212 | llvm::Expected<devtools_rust::FunctionLifetimes> lifetimes = |
| 213 | devtools_rust::GetLifetimeAnnotations(function_decl, lifetime_context_, |
| 214 | &lifetime_symbol_table); |
| 215 | llvm::DenseSet<devtools_rust::Lifetime> all_lifetimes; |
| 216 | |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 217 | std::vector<FuncParam> params; |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 218 | bool success = true; |
Devin Jeanpierre | d4dde0e | 2021-10-13 20:48:25 +0000 | [diff] [blame] | 219 | // non-static member functions receive an implicit `this` parameter. |
| 220 | if (auto* method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(function_decl)) { |
| 221 | if (method_decl->isInstance()) { |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 222 | std::optional<devtools_rust::TypeLifetimes> this_lifetimes; |
| 223 | if (lifetimes) { |
| 224 | this_lifetimes = lifetimes->this_lifetimes; |
| 225 | all_lifetimes.insert(this_lifetimes->begin(), this_lifetimes->end()); |
| 226 | } |
| 227 | auto param_type = ConvertType(method_decl->getThisType(), this_lifetimes, |
| 228 | /*nullable=*/false); |
Devin Jeanpierre | d4dde0e | 2021-10-13 20:48:25 +0000 | [diff] [blame] | 229 | if (!param_type.ok()) { |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 230 | PushUnsupportedItem(function_decl, param_type.status().ToString(), |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 231 | method_decl->getBeginLoc()); |
| 232 | |
Devin Jeanpierre | d4dde0e | 2021-10-13 20:48:25 +0000 | [diff] [blame] | 233 | success = false; |
Devin Jeanpierre | fecf547 | 2021-10-27 10:52:30 +0000 | [diff] [blame] | 234 | } else { |
| 235 | params.push_back({*std::move(param_type), Identifier("__this")}); |
Devin Jeanpierre | d4dde0e | 2021-10-13 20:48:25 +0000 | [diff] [blame] | 236 | } |
Devin Jeanpierre | d4dde0e | 2021-10-13 20:48:25 +0000 | [diff] [blame] | 237 | } |
| 238 | } |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 239 | |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 240 | if (lifetimes) { |
| 241 | CHECK_EQ(lifetimes->param_lifetimes.size(), function_decl->getNumParams()); |
| 242 | } |
| 243 | for (unsigned i = 0; i < function_decl->getNumParams(); ++i) { |
| 244 | const clang::ParmVarDecl* param = function_decl->getParamDecl(i); |
| 245 | std::optional<devtools_rust::TypeLifetimes> param_lifetimes; |
| 246 | if (lifetimes) { |
| 247 | param_lifetimes = lifetimes->param_lifetimes[i]; |
| 248 | all_lifetimes.insert(param_lifetimes->begin(), param_lifetimes->end()); |
| 249 | } |
| 250 | auto param_type = ConvertType(param->getType(), param_lifetimes); |
Michael Forster | dc683af | 2021-09-17 08:51:28 +0000 | [diff] [blame] | 251 | if (!param_type.ok()) { |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 252 | PushUnsupportedItem( |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 253 | function_decl, |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 254 | absl::Substitute("Parameter type '$0' is not supported", |
| 255 | param->getType().getAsString()), |
| 256 | param->getBeginLoc()); |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 257 | success = false; |
| 258 | continue; |
Michael Forster | 1de27b8 | 2021-09-17 07:22:22 +0000 | [diff] [blame] | 259 | } |
Devin Jeanpierre | bf0d560 | 2021-10-13 20:47:39 +0000 | [diff] [blame] | 260 | |
| 261 | if (const clang::RecordType* record_type = |
| 262 | llvm::dyn_cast<clang::RecordType>(param->getType())) { |
| 263 | if (clang::RecordDecl* record_decl = |
| 264 | llvm::dyn_cast<clang::RecordDecl>(record_type->getDecl())) { |
| 265 | // TODO(b/200067242): non-trivial_abi structs, when passed by value, |
| 266 | // have a different representation which needs special support. We |
| 267 | // currently do not support it. |
| 268 | if (!record_decl->canPassInRegisters()) { |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 269 | PushUnsupportedItem( |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 270 | function_decl, |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 271 | absl::Substitute("Non-trivial_abi type '$0' is not " |
| 272 | "supported by value as a parameter", |
| 273 | param->getType().getAsString()), |
| 274 | param->getBeginLoc()); |
Devin Jeanpierre | bf0d560 | 2021-10-13 20:47:39 +0000 | [diff] [blame] | 275 | success = false; |
| 276 | } |
| 277 | } |
| 278 | } |
| 279 | |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 280 | std::optional<Identifier> param_name = GetTranslatedIdentifier(param); |
Lukasz Anforowicz | 0c816f1 | 2021-12-15 17:41:49 +0000 | [diff] [blame] | 281 | CHECK(param_name.has_value()); // No known cases where the above can fail. |
Devin Jeanpierre | e78b2fb | 2021-10-05 11:40:33 +0000 | [diff] [blame] | 282 | params.push_back({*param_type, *std::move(param_name)}); |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 283 | } |
| 284 | |
Devin Jeanpierre | bf0d560 | 2021-10-13 20:47:39 +0000 | [diff] [blame] | 285 | if (const clang::RecordType* record_return_type = |
| 286 | llvm::dyn_cast<clang::RecordType>(function_decl->getReturnType())) { |
| 287 | if (clang::RecordDecl* record_decl = |
| 288 | llvm::dyn_cast<clang::RecordDecl>(record_return_type->getDecl())) { |
| 289 | // TODO(b/200067242): non-trivial_abi structs, when passed by value, |
| 290 | // have a different representation which needs special support. We |
| 291 | // currently do not support it. |
| 292 | if (!record_decl->canPassInRegisters()) { |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 293 | PushUnsupportedItem( |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 294 | function_decl, |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 295 | absl::Substitute("Non-trivial_abi type '$0' is not supported " |
| 296 | "by value as a return type", |
| 297 | function_decl->getReturnType().getAsString()), |
| 298 | function_decl->getReturnTypeSourceRange()); |
Devin Jeanpierre | bf0d560 | 2021-10-13 20:47:39 +0000 | [diff] [blame] | 299 | success = false; |
| 300 | } |
| 301 | } |
| 302 | } |
| 303 | |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 304 | std::optional<devtools_rust::TypeLifetimes> return_lifetimes; |
| 305 | if (lifetimes) { |
| 306 | return_lifetimes = lifetimes->return_lifetimes; |
| 307 | all_lifetimes.insert(return_lifetimes->begin(), return_lifetimes->end()); |
| 308 | } |
| 309 | auto return_type = |
| 310 | ConvertType(function_decl->getReturnType(), return_lifetimes); |
Michael Forster | dc683af | 2021-09-17 08:51:28 +0000 | [diff] [blame] | 311 | if (!return_type.ok()) { |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 312 | PushUnsupportedItem( |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 313 | function_decl, |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 314 | absl::Substitute("Return type '$0' is not supported", |
| 315 | function_decl->getReturnType().getAsString()), |
| 316 | function_decl->getReturnTypeSourceRange()); |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 317 | success = false; |
Michael Forster | 1de27b8 | 2021-09-17 07:22:22 +0000 | [diff] [blame] | 318 | } |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 319 | |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 320 | std::vector<Lifetime> lifetime_params; |
| 321 | for (devtools_rust::Lifetime lifetime : all_lifetimes) { |
| 322 | std::optional<llvm::StringRef> name = |
| 323 | lifetime_symbol_table.LookupLifetime(lifetime); |
| 324 | CHECK(name.has_value()); |
| 325 | lifetime_params.push_back( |
| 326 | {.name = name->str(), .id = LifetimeId(lifetime.Id())}); |
| 327 | } |
| 328 | std::sort( |
| 329 | lifetime_params.begin(), lifetime_params.end(), |
| 330 | [](const Lifetime& l1, const Lifetime& l2) { return l1.name < l2.name; }); |
| 331 | |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 332 | std::optional<MemberFuncMetadata> member_func_metadata; |
| 333 | if (auto* method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(function_decl)) { |
Lukasz Anforowicz | 57331cf | 2021-12-16 02:57:19 +0000 | [diff] [blame] | 334 | switch (method_decl->getAccess()) { |
| 335 | case clang::AS_public: |
| 336 | break; |
| 337 | case clang::AS_protected: |
| 338 | case clang::AS_private: |
| 339 | case clang::AS_none: |
| 340 | // No need for IR to include Func representing private methods. |
| 341 | // TODO(lukasza): Revisit this for protected methods. |
| 342 | return true; |
| 343 | } |
Devin Jeanpierre | 96839c1 | 2021-12-14 00:27:38 +0000 | [diff] [blame] | 344 | std::optional<MemberFuncMetadata::InstanceMethodMetadata> instance_metadata; |
| 345 | if (method_decl->isInstance()) { |
| 346 | MemberFuncMetadata::ReferenceQualification reference; |
| 347 | switch (method_decl->getRefQualifier()) { |
| 348 | case clang::RQ_LValue: |
| 349 | reference = MemberFuncMetadata::kLValue; |
| 350 | break; |
| 351 | case clang::RQ_RValue: |
| 352 | reference = MemberFuncMetadata::kRValue; |
| 353 | break; |
| 354 | case clang::RQ_None: |
| 355 | reference = MemberFuncMetadata::kUnqualified; |
| 356 | break; |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 357 | } |
Devin Jeanpierre | 96839c1 | 2021-12-14 00:27:38 +0000 | [diff] [blame] | 358 | instance_metadata = MemberFuncMetadata::InstanceMethodMetadata{ |
| 359 | .reference = reference, |
| 360 | .is_const = method_decl->isConst(), |
| 361 | .is_virtual = method_decl->isVirtual(), |
Lukasz Anforowicz | 71716b7 | 2022-01-26 17:05:05 +0000 | [diff] [blame] | 362 | .is_explicit_ctor = false, |
Devin Jeanpierre | 96839c1 | 2021-12-14 00:27:38 +0000 | [diff] [blame] | 363 | }; |
Lukasz Anforowicz | 71716b7 | 2022-01-26 17:05:05 +0000 | [diff] [blame] | 364 | if (auto* ctor_decl = |
| 365 | llvm::dyn_cast<clang::CXXConstructorDecl>(function_decl)) { |
| 366 | instance_metadata->is_explicit_ctor = ctor_decl->isExplicit(); |
| 367 | } |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 368 | } |
Devin Jeanpierre | 96839c1 | 2021-12-14 00:27:38 +0000 | [diff] [blame] | 369 | |
| 370 | member_func_metadata = MemberFuncMetadata{ |
| 371 | .record_id = GenerateDeclId(method_decl->getParent()), |
| 372 | .instance_method_metadata = instance_metadata}; |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 373 | } |
| 374 | |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 375 | std::optional<UnqualifiedIdentifier> translated_name = |
| 376 | GetTranslatedName(function_decl); |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 377 | if (success && translated_name.has_value()) { |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 378 | seen_decls_[function_decl->getCanonicalDecl()].push_back(Func{ |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 379 | .name = *translated_name, |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 380 | .owning_target = GetOwningTarget(function_decl), |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 381 | .doc_comment = GetComment(function_decl), |
| 382 | .mangled_name = GetMangledName(function_decl), |
| 383 | .return_type = *return_type, |
| 384 | .params = std::move(params), |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 385 | .lifetime_params = std::move(lifetime_params), |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 386 | .is_inline = function_decl->isInlined(), |
Devin Jeanpierre | c6877bb | 2021-10-13 20:47:54 +0000 | [diff] [blame] | 387 | .member_func_metadata = std::move(member_func_metadata), |
Googler | 95f29a1 | 2022-01-07 07:47:26 +0000 | [diff] [blame] | 388 | .source_loc = ConvertSourceLocation(function_decl->getBeginLoc()), |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 389 | }); |
Devin Jeanpierre | e78b2fb | 2021-10-05 11:40:33 +0000 | [diff] [blame] | 390 | } |
Michael Forster | 523dbd4 | 2021-10-12 11:05:44 +0000 | [diff] [blame] | 391 | |
Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 392 | return true; |
| 393 | } |
| 394 | |
Googler | e05154d | 2022-01-10 08:39:03 +0000 | [diff] [blame] | 395 | BlazeLabel AstVisitor::GetOwningTarget(const clang::Decl* decl) const { |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 396 | clang::SourceManager& source_manager = ctx_->getSourceManager(); |
Rosica Dejanovska | d0fc294 | 2022-01-21 11:26:00 +0000 | [diff] [blame] | 397 | auto source_location = decl->getLocation(); |
| 398 | auto id = source_manager.getFileID(source_location); |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 399 | |
Rosica Dejanovska | d0fc294 | 2022-01-21 11:26:00 +0000 | [diff] [blame] | 400 | // If the header this decl comes from is not associated with a target we |
| 401 | // consider it a textual header. In that case we go up the include stack |
| 402 | // until we find a header that has an owning target. |
| 403 | |
| 404 | // TODO(b/208377928): We currently don't have a target for the headers in |
| 405 | // Clang's resource directory, so for the time being we return a fictional |
| 406 | // "//:virtual_clang_resource_dir_target" for system headers. |
| 407 | while (source_location.isValid() && |
| 408 | !source_manager.isInSystemHeader(source_location)) { |
| 409 | llvm::Optional<llvm::StringRef> filename = |
| 410 | source_manager.getNonBuiltinFilenameForID(id); |
| 411 | if (!filename) { |
| 412 | return BlazeLabel("//:builtin"); |
| 413 | } |
| 414 | if (filename->startswith("./")) { |
| 415 | filename = filename->substr(2); |
| 416 | } |
| 417 | auto target_iterator = |
| 418 | headers_to_targets_.find(HeaderName(filename->str())); |
| 419 | if (target_iterator != headers_to_targets_.end()) { |
| 420 | return target_iterator->second; |
| 421 | } |
| 422 | source_location = source_manager.getIncludeLoc(id); |
| 423 | id = source_manager.getFileID(source_location); |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 424 | } |
Rosica Dejanovska | d0fc294 | 2022-01-21 11:26:00 +0000 | [diff] [blame] | 425 | |
| 426 | return BlazeLabel("//:virtual_clang_resource_dir_target"); |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 427 | } |
| 428 | |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 429 | bool AstVisitor::IsFromCurrentTarget(const clang::Decl* decl) const { |
| 430 | return current_target_ == GetOwningTarget(decl); |
| 431 | } |
| 432 | |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 433 | bool AstVisitor::VisitRecordDecl(clang::RecordDecl* record_decl) { |
Googler | 21351fc | 2021-10-19 08:58:04 +0000 | [diff] [blame] | 434 | const clang::DeclContext* decl_context = record_decl->getDeclContext(); |
Googler | 648adff | 2022-01-10 13:14:06 +0000 | [diff] [blame] | 435 | if (decl_context) { |
| 436 | if (decl_context->isFunctionOrMethod()) { |
| 437 | return true; |
| 438 | } |
Marcel Hlopko | d7f76ff | 2022-01-26 14:08:19 +0000 | [diff] [blame] | 439 | if (record_decl->isInjectedClassName()) { |
| 440 | return true; |
| 441 | } |
Googler | 648adff | 2022-01-10 13:14:06 +0000 | [diff] [blame] | 442 | if (decl_context->isRecord()) { |
| 443 | PushUnsupportedItem(record_decl, "Nested classes are not supported yet", |
| 444 | record_decl->getBeginLoc()); |
| 445 | return true; |
| 446 | } |
Googler | 21351fc | 2021-10-19 08:58:04 +0000 | [diff] [blame] | 447 | } |
| 448 | |
Marcel Hlopko | 872df5e | 2022-01-25 21:18:55 +0000 | [diff] [blame] | 449 | if (record_decl->isUnion()) { |
| 450 | PushUnsupportedItem(record_decl, "Unions are not supported yet", |
| 451 | record_decl->getBeginLoc()); |
| 452 | return true; |
| 453 | } |
| 454 | |
Googler | 8173f59 | 2022-01-04 13:57:32 +0000 | [diff] [blame] | 455 | // Make sure the record has a definition that we'll be able to call |
| 456 | // ASTContext::getASTRecordLayout() on. |
| 457 | record_decl = record_decl->getDefinition(); |
| 458 | if (!record_decl || record_decl->isInvalidDecl() || |
| 459 | !record_decl->isCompleteDefinition()) { |
| 460 | return true; |
| 461 | } |
| 462 | |
Googler | 2e85f34 | 2021-09-17 07:04:07 +0000 | [diff] [blame] | 463 | clang::AccessSpecifier default_access = clang::AS_public; |
Devin Jeanpierre | 1ad7d55 | 2021-10-27 18:45:49 +0000 | [diff] [blame] | 464 | |
Devin Jeanpierre | e6e1665 | 2021-12-22 15:54:46 +0000 | [diff] [blame] | 465 | bool is_final = true; |
Devin Jeanpierre | 296c607 | 2021-10-27 10:53:05 +0000 | [diff] [blame] | 466 | if (auto* cxx_record_decl = |
Googler | 2e85f34 | 2021-09-17 07:04:07 +0000 | [diff] [blame] | 467 | clang::dyn_cast<clang::CXXRecordDecl>(record_decl)) { |
Googler | 846e1fc | 2022-01-10 13:14:57 +0000 | [diff] [blame] | 468 | if (cxx_record_decl->getDescribedClassTemplate() || |
| 469 | clang::isa<clang::ClassTemplateSpecializationDecl>(record_decl)) { |
| 470 | PushUnsupportedItem(record_decl, "Class templates are not supported yet", |
| 471 | record_decl->getBeginLoc()); |
| 472 | return true; |
| 473 | } |
| 474 | |
Devin Jeanpierre | 296c607 | 2021-10-27 10:53:05 +0000 | [diff] [blame] | 475 | sema_.ForceDeclarationOfImplicitMembers(cxx_record_decl); |
Googler | 2e85f34 | 2021-09-17 07:04:07 +0000 | [diff] [blame] | 476 | if (cxx_record_decl->isClass()) { |
| 477 | default_access = clang::AS_private; |
| 478 | } |
Devin Jeanpierre | e6e1665 | 2021-12-22 15:54:46 +0000 | [diff] [blame] | 479 | is_final = cxx_record_decl->isEffectivelyFinal(); |
Googler | 2e85f34 | 2021-09-17 07:04:07 +0000 | [diff] [blame] | 480 | } |
Googler | 279eca3 | 2022-01-04 14:03:44 +0000 | [diff] [blame] | 481 | std::optional<Identifier> record_name = GetTranslatedIdentifier(record_decl); |
| 482 | if (!record_name.has_value()) { |
| 483 | return true; |
| 484 | } |
| 485 | // Provisionally assume that we know this RecordDecl so that we'll be able |
| 486 | // to import fields whose type contains the record itself. |
Googler | dcca7f7 | 2022-01-10 12:30:43 +0000 | [diff] [blame] | 487 | known_type_decls_.insert(record_decl); |
Googler | e3434c3 | 2021-10-19 10:28:35 +0000 | [diff] [blame] | 488 | std::optional<std::vector<Field>> fields = |
| 489 | ImportFields(record_decl, default_access); |
| 490 | if (!fields.has_value()) { |
Googler | 279eca3 | 2022-01-04 14:03:44 +0000 | [diff] [blame] | 491 | // Importing a field failed, so note that we didn't import this RecordDecl |
| 492 | // after all. |
Googler | dcca7f7 | 2022-01-10 12:30:43 +0000 | [diff] [blame] | 493 | known_type_decls_.erase(record_decl); |
Devin Jeanpierre | e78b2fb | 2021-10-05 11:40:33 +0000 | [diff] [blame] | 494 | return true; |
| 495 | } |
Googler | e3434c3 | 2021-10-19 10:28:35 +0000 | [diff] [blame] | 496 | const clang::ASTRecordLayout& layout = ctx_->getASTRecordLayout(record_decl); |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 497 | seen_decls_[record_decl->getCanonicalDecl()].push_back( |
Devin Jeanpierre | e78b2fb | 2021-10-05 11:40:33 +0000 | [diff] [blame] | 498 | Record{.identifier = *record_name, |
Marcel Hlopko | 264b9ad | 2021-12-02 21:06:44 +0000 | [diff] [blame] | 499 | .id = GenerateDeclId(record_decl), |
Marcel Hlopko | 80441c1 | 2021-11-12 10:43:18 +0000 | [diff] [blame] | 500 | .owning_target = GetOwningTarget(record_decl), |
Michael Forster | cc5941a | 2021-10-07 07:12:24 +0000 | [diff] [blame] | 501 | .doc_comment = GetComment(record_decl), |
Googler | e3434c3 | 2021-10-19 10:28:35 +0000 | [diff] [blame] | 502 | .fields = *std::move(fields), |
Michael Forster | 7ef8073 | 2021-10-01 18:12:19 +0000 | [diff] [blame] | 503 | .size = layout.getSize().getQuantity(), |
| 504 | .alignment = layout.getAlignment().getQuantity(), |
Devin Jeanpierre | 1ad7d55 | 2021-10-27 18:45:49 +0000 | [diff] [blame] | 505 | .copy_constructor = GetCopyCtorSpecialMemberFunc(*record_decl), |
| 506 | .move_constructor = GetMoveCtorSpecialMemberFunc(*record_decl), |
| 507 | .destructor = GetDestructorSpecialMemberFunc(*record_decl), |
Devin Jeanpierre | e6e1665 | 2021-12-22 15:54:46 +0000 | [diff] [blame] | 508 | .is_trivial_abi = record_decl->canPassInRegisters(), |
| 509 | .is_final = is_final}); |
Marcel Hlopko | b4b2874 | 2021-09-15 12:45:20 +0000 | [diff] [blame] | 510 | return true; |
| 511 | } |
| 512 | |
Googler | 6834699 | 2022-01-05 06:11:31 +0000 | [diff] [blame] | 513 | bool AstVisitor::VisitTypedefNameDecl( |
| 514 | clang::TypedefNameDecl* typedef_name_decl) { |
Googler | dcca7f7 | 2022-01-10 12:30:43 +0000 | [diff] [blame] | 515 | const clang::DeclContext* decl_context = typedef_name_decl->getDeclContext(); |
| 516 | if (decl_context) { |
| 517 | if (decl_context->isFunctionOrMethod()) { |
| 518 | return true; |
| 519 | } |
| 520 | if (decl_context->isRecord()) { |
| 521 | PushUnsupportedItem(typedef_name_decl, |
| 522 | "Typedefs nested in classes are not supported yet", |
| 523 | typedef_name_decl->getBeginLoc()); |
| 524 | return true; |
| 525 | } |
| 526 | } |
| 527 | |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 528 | clang::QualType type = |
| 529 | typedef_name_decl->getASTContext().getTypedefType(typedef_name_decl); |
| 530 | if (kWellKnownTypes.contains(type.getAsString())) { |
| 531 | return true; |
| 532 | } |
| 533 | |
Googler | dcca7f7 | 2022-01-10 12:30:43 +0000 | [diff] [blame] | 534 | std::optional<Identifier> identifier = |
| 535 | GetTranslatedIdentifier(typedef_name_decl); |
| 536 | if (!identifier.has_value()) { |
| 537 | // This should never happen. |
| 538 | LOG(FATAL) << "Couldn't get identifier for TypedefNameDecl"; |
| 539 | return true; |
| 540 | } |
| 541 | absl::StatusOr<MappedType> underlying_type = |
| 542 | ConvertType(typedef_name_decl->getUnderlyingType()); |
| 543 | if (underlying_type.ok()) { |
| 544 | known_type_decls_.insert(typedef_name_decl); |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 545 | seen_decls_[typedef_name_decl->getCanonicalDecl()].push_back( |
Googler | dcca7f7 | 2022-01-10 12:30:43 +0000 | [diff] [blame] | 546 | TypeAlias{.identifier = *identifier, |
| 547 | .id = GenerateDeclId(typedef_name_decl), |
| 548 | .owning_target = GetOwningTarget(typedef_name_decl), |
| 549 | .underlying_type = *underlying_type}); |
| 550 | } else { |
| 551 | PushUnsupportedItem(typedef_name_decl, underlying_type.status().ToString(), |
| 552 | typedef_name_decl->getBeginLoc()); |
| 553 | } |
Googler | 6834699 | 2022-01-05 06:11:31 +0000 | [diff] [blame] | 554 | return true; |
| 555 | } |
| 556 | |
Michael Forster | cc5941a | 2021-10-07 07:12:24 +0000 | [diff] [blame] | 557 | std::optional<std::string> AstVisitor::GetComment( |
| 558 | const clang::Decl* decl) const { |
Michael Forster | 409d941 | 2021-10-07 08:35:29 +0000 | [diff] [blame] | 559 | // This does currently not distinguish between different types of comments. |
| 560 | // In general it is not possible in C++ to reliably only extract doc comments. |
| 561 | // This is going to be a heuristic that needs to be tuned over time. |
| 562 | |
Michael Forster | d3ef1e9 | 2021-10-12 16:15:31 +0000 | [diff] [blame] | 563 | clang::SourceManager& sm = ctx_->getSourceManager(); |
| 564 | clang::RawComment* raw_comment = ctx_->getRawCommentForDeclNoCache(decl); |
Michael Forster | cc5941a | 2021-10-07 07:12:24 +0000 | [diff] [blame] | 565 | |
| 566 | if (raw_comment == nullptr) { |
| 567 | return {}; |
| 568 | } else { |
| 569 | return raw_comment->getFormattedText(sm, sm.getDiagnostics()); |
| 570 | } |
| 571 | } |
| 572 | |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 573 | void AstVisitor::PushUnsupportedItem(const clang::Decl* decl, |
| 574 | std::string message, |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 575 | clang::SourceLocation source_location) { |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 576 | if (!IsFromCurrentTarget(decl)) return; |
| 577 | |
| 578 | std::string name = "unnamed"; |
| 579 | if (const auto* named_decl = llvm::dyn_cast<clang::NamedDecl>(decl)) { |
| 580 | name = named_decl->getQualifiedNameAsString(); |
| 581 | } |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 582 | seen_decls_[decl->getCanonicalDecl()].push_back(UnsupportedItem{ |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 583 | .name = std::move(name), |
| 584 | .message = std::move(message), |
| 585 | .source_loc = ConvertSourceLocation(std::move(source_location))}); |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 586 | } |
| 587 | |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 588 | void AstVisitor::PushUnsupportedItem(const clang::Decl* decl, |
| 589 | std::string message, |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 590 | clang::SourceRange source_range) { |
Marcel Hlopko | 4c660dd | 2021-12-02 09:52:47 +0000 | [diff] [blame] | 591 | PushUnsupportedItem(decl, message, source_range.getBegin()); |
Marcel Hlopko | 3df7254 | 2021-11-30 09:38:36 +0000 | [diff] [blame] | 592 | } |
| 593 | |
| 594 | SourceLoc AstVisitor::ConvertSourceLocation(clang::SourceLocation loc) const { |
Michael Forster | d3ef1e9 | 2021-10-12 16:15:31 +0000 | [diff] [blame] | 595 | auto& sm = ctx_->getSourceManager(); |
| 596 | |
Googler | c8a8e73 | 2021-10-19 07:49:24 +0000 | [diff] [blame] | 597 | clang::StringRef filename = sm.getFilename(loc); |
Michael Forster | d3ef1e9 | 2021-10-12 16:15:31 +0000 | [diff] [blame] | 598 | if (filename.startswith("./")) { |
| 599 | filename = filename.substr(2); |
| 600 | } |
| 601 | |
| 602 | return SourceLoc{.filename = filename.str(), |
| 603 | .line = sm.getSpellingLineNumber(loc), |
| 604 | .column = sm.getSpellingColumnNumber(loc)}; |
| 605 | } |
| 606 | |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 607 | absl::StatusOr<MappedType> AstVisitor::ConvertType( |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 608 | clang::QualType qual_type, |
| 609 | std::optional<devtools_rust::TypeLifetimes> lifetimes, |
| 610 | bool nullable) const { |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 611 | std::optional<MappedType> type = std::nullopt; |
Googler | db11153 | 2022-01-05 06:12:13 +0000 | [diff] [blame] | 612 | // When converting the type to a string, don't include qualifiers -- we handle |
| 613 | // these separately. |
| 614 | std::string type_string = qual_type.getUnqualifiedType().getAsString(); |
Michael Forster | dc683af | 2021-09-17 08:51:28 +0000 | [diff] [blame] | 615 | |
Googler | 44e3fbc | 2022-01-11 10:19:26 +0000 | [diff] [blame] | 616 | if (auto iter = kWellKnownTypes.find(type_string); |
| 617 | iter != kWellKnownTypes.end()) { |
Googler | 06f2c9a | 2022-01-05 12:00:47 +0000 | [diff] [blame] | 618 | type = MappedType::Simple(std::string(iter->second), type_string); |
| 619 | } else if (const auto* pointer_type = |
| 620 | qual_type->getAs<clang::PointerType>()) { |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 621 | std::optional<LifetimeId> lifetime; |
| 622 | if (lifetimes.has_value()) { |
| 623 | CHECK(!lifetimes->empty()); |
| 624 | lifetime = LifetimeId(lifetimes->back().Id()); |
| 625 | lifetimes->pop_back(); |
| 626 | } |
| 627 | auto pointee_type = ConvertType(pointer_type->getPointeeType(), lifetimes); |
Michael Forster | dc683af | 2021-09-17 08:51:28 +0000 | [diff] [blame] | 628 | if (pointee_type.ok()) { |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 629 | type = MappedType::PointerTo(*pointee_type, lifetime, nullable); |
Michael Forster | 1de27b8 | 2021-09-17 07:22:22 +0000 | [diff] [blame] | 630 | } |
Googler | 61dce3b | 2021-12-02 09:16:32 +0000 | [diff] [blame] | 631 | } else if (const auto* lvalue_ref_type = |
| 632 | qual_type->getAs<clang::LValueReferenceType>()) { |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 633 | std::optional<LifetimeId> lifetime; |
| 634 | if (lifetimes.has_value()) { |
| 635 | CHECK(!lifetimes->empty()); |
| 636 | lifetime = LifetimeId(lifetimes->back().Id()); |
| 637 | lifetimes->pop_back(); |
| 638 | } |
| 639 | auto pointee_type = |
| 640 | ConvertType(lvalue_ref_type->getPointeeType(), lifetimes); |
Googler | 61dce3b | 2021-12-02 09:16:32 +0000 | [diff] [blame] | 641 | if (pointee_type.ok()) { |
Googler | 4e1bc13 | 2021-12-06 10:10:42 +0000 | [diff] [blame] | 642 | type = MappedType::LValueReferenceTo(*pointee_type, lifetime); |
Googler | 61dce3b | 2021-12-02 09:16:32 +0000 | [diff] [blame] | 643 | } |
Googler | b6c0fe0 | 2021-12-01 10:55:31 +0000 | [diff] [blame] | 644 | } else if (const auto* builtin_type = |
Googler | 06f2c9a | 2022-01-05 12:00:47 +0000 | [diff] [blame] | 645 | // Use getAsAdjusted instead of getAs so we don't desugar |
| 646 | // typedefs. |
| 647 | qual_type->getAsAdjusted<clang::BuiltinType>()) { |
Michael Forster | 51da81a | 2021-09-20 07:14:23 +0000 | [diff] [blame] | 648 | switch (builtin_type->getKind()) { |
| 649 | case clang::BuiltinType::Bool: |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 650 | type = MappedType::Simple("bool", "bool"); |
Michael Forster | 51da81a | 2021-09-20 07:14:23 +0000 | [diff] [blame] | 651 | break; |
| 652 | case clang::BuiltinType::Float: |
Michael Forster | c7976ec | 2021-10-01 10:05:16 +0000 | [diff] [blame] | 653 | type = MappedType::Simple("f32", "float"); |
Michael Forster | 51da81a | 2021-09-20 07:14:23 +0000 | [diff] [blame] | 654 | break; |
| 655 | case clang::BuiltinType::Double: |
Michael Forster | c7976ec | 2021-10-01 10:05:16 +0000 | [diff] [blame] | 656 | type = MappedType::Simple("f64", "double"); |
Michael Forster | 51da81a | 2021-09-20 07:14:23 +0000 | [diff] [blame] | 657 | break; |
| 658 | case clang::BuiltinType::Void: |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 659 | type = MappedType::Void(); |
Michael Forster | 51da81a | 2021-09-20 07:14:23 +0000 | [diff] [blame] | 660 | break; |
| 661 | default: |
| 662 | if (builtin_type->isIntegerType()) { |
Michael Forster | d3ef1e9 | 2021-10-12 16:15:31 +0000 | [diff] [blame] | 663 | auto size = ctx_->getTypeSize(builtin_type); |
Googler | 06f2c9a | 2022-01-05 12:00:47 +0000 | [diff] [blame] | 664 | if (size == 8 || size == 16 || size == 32 || size == 64) { |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 665 | type = MappedType::Simple( |
Michael Forster | 51da81a | 2021-09-20 07:14:23 +0000 | [diff] [blame] | 666 | absl::Substitute( |
| 667 | "$0$1", builtin_type->isSignedInteger() ? 'i' : 'u', size), |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 668 | type_string); |
Michael Forster | 51da81a | 2021-09-20 07:14:23 +0000 | [diff] [blame] | 669 | } |
| 670 | } |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 671 | } |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 672 | } else if (const auto* tag_type = |
Googler | 6a0a525 | 2022-01-11 14:08:09 +0000 | [diff] [blame] | 673 | qual_type->getAsAdjusted<clang::TagType>()) { |
Devin Jeanpierre | bf0d560 | 2021-10-13 20:47:39 +0000 | [diff] [blame] | 674 | clang::TagDecl* tag_decl = tag_type->getDecl(); |
| 675 | |
Googler | dcca7f7 | 2022-01-10 12:30:43 +0000 | [diff] [blame] | 676 | if (known_type_decls_.contains(tag_decl)) { |
Googler | 279eca3 | 2022-01-04 14:03:44 +0000 | [diff] [blame] | 677 | if (std::optional<Identifier> id = GetTranslatedIdentifier(tag_decl)) { |
| 678 | std::string ident(id->Ident()); |
| 679 | DeclId decl_id = GenerateDeclId(tag_decl); |
| 680 | type = MappedType::WithDeclIds(ident, decl_id, ident, decl_id); |
| 681 | } |
Devin Jeanpierre | bf0d560 | 2021-10-13 20:47:39 +0000 | [diff] [blame] | 682 | } |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 683 | } else if (const auto* typedef_type = |
Googler | 6a0a525 | 2022-01-11 14:08:09 +0000 | [diff] [blame] | 684 | qual_type->getAsAdjusted<clang::TypedefType>()) { |
Googler | dcca7f7 | 2022-01-10 12:30:43 +0000 | [diff] [blame] | 685 | clang::TypedefNameDecl* typedef_name_decl = typedef_type->getDecl(); |
| 686 | |
| 687 | if (known_type_decls_.contains(typedef_name_decl)) { |
| 688 | if (std::optional<Identifier> id = |
| 689 | GetTranslatedIdentifier(typedef_name_decl)) { |
| 690 | std::string ident(id->Ident()); |
| 691 | DeclId decl_id = GenerateDeclId(typedef_name_decl); |
| 692 | type = MappedType::WithDeclIds(ident, decl_id, ident, decl_id); |
| 693 | } |
| 694 | } |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 695 | } |
Devin Jeanpierre | 184f9ac | 2021-09-17 13:47:03 +0000 | [diff] [blame] | 696 | |
| 697 | if (!type.has_value()) { |
| 698 | absl::Status error = absl::UnimplementedError( |
| 699 | absl::Substitute("Unsupported type '$0'", type_string)); |
| 700 | error.SetPayload(kTypeStatusPayloadUrl, absl::Cord(type_string)); |
| 701 | return error; |
| 702 | } |
| 703 | |
| 704 | // Add cv-qualification. |
Devin Jeanpierre | 09c6f45 | 2021-09-29 07:34:24 +0000 | [diff] [blame] | 705 | type->cc_type.is_const = qual_type.isConstQualified(); |
Devin Jeanpierre | 184f9ac | 2021-09-17 13:47:03 +0000 | [diff] [blame] | 706 | // Not doing volatile for now -- note that volatile pointers do not exist in |
| 707 | // Rust, though volatile reads/writes still do. |
| 708 | |
| 709 | return *std::move(type); |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 710 | } |
| 711 | |
Googler | e3434c3 | 2021-10-19 10:28:35 +0000 | [diff] [blame] | 712 | std::optional<std::vector<Field>> AstVisitor::ImportFields( |
| 713 | clang::RecordDecl* record_decl, clang::AccessSpecifier default_access) { |
| 714 | std::vector<Field> fields; |
| 715 | const clang::ASTRecordLayout& layout = ctx_->getASTRecordLayout(record_decl); |
| 716 | for (const clang::FieldDecl* field_decl : record_decl->fields()) { |
| 717 | auto type = ConvertType(field_decl->getType()); |
| 718 | if (!type.ok()) { |
Googler | 279eca3 | 2022-01-04 14:03:44 +0000 | [diff] [blame] | 719 | PushUnsupportedItem(record_decl, |
| 720 | absl::Substitute("Field type '$0' is not supported", |
| 721 | field_decl->getType().getAsString()), |
| 722 | field_decl->getBeginLoc()); |
Googler | e3434c3 | 2021-10-19 10:28:35 +0000 | [diff] [blame] | 723 | return std::nullopt; |
| 724 | } |
| 725 | clang::AccessSpecifier access = field_decl->getAccess(); |
| 726 | if (access == clang::AS_none) { |
| 727 | access = default_access; |
| 728 | } |
| 729 | |
| 730 | std::optional<Identifier> field_name = GetTranslatedIdentifier(field_decl); |
| 731 | if (!field_name.has_value()) { |
Googler | 279eca3 | 2022-01-04 14:03:44 +0000 | [diff] [blame] | 732 | PushUnsupportedItem( |
| 733 | record_decl, |
| 734 | absl::Substitute("Cannot translate name for field '$0'", |
| 735 | field_decl->getNameAsString()), |
| 736 | field_decl->getBeginLoc()); |
Googler | e3434c3 | 2021-10-19 10:28:35 +0000 | [diff] [blame] | 737 | return std::nullopt; |
| 738 | } |
| 739 | fields.push_back( |
| 740 | {.identifier = *std::move(field_name), |
| 741 | .doc_comment = GetComment(field_decl), |
| 742 | .type = *type, |
| 743 | .access = TranslateAccessSpecifier(access), |
| 744 | .offset = layout.getFieldOffset(field_decl->getFieldIndex())}); |
| 745 | } |
| 746 | return fields; |
| 747 | } |
| 748 | |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 749 | std::string AstVisitor::GetMangledName( |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 750 | const clang::NamedDecl* named_decl) const { |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 751 | clang::GlobalDecl decl; |
| 752 | |
| 753 | // There are only three named decl types that don't work with the GlobalDecl |
| 754 | // unary constructor: GPU kernels (which do not exist in standard C++, so we |
| 755 | // ignore), constructors, and destructors. GlobalDecl does not support |
| 756 | // constructors and destructors from the unary constructor because there is |
| 757 | // more than one global declaration for a given constructor or destructor! |
| 758 | // |
| 759 | // * (Ctor|Dtor)_Complete is a function which constructs / destroys the |
| 760 | // entire object. This is what we want. :) |
| 761 | // * Dtor_Deleting is a function which additionally calls operator delete. |
| 762 | // * (Ctor|Dtor)_Base is a function which constructs/destroys the object but |
| 763 | // NOT including virtual base class subobjects. |
| 764 | // * (Ctor|Dtor)_Comdat: I *believe* this is the identifier used to |
| 765 | // deduplicate inline functions, and is not callable. |
| 766 | // * Dtor_(Copying|Default)Closure: These only exist in the MSVC++ ABI, |
| 767 | // which we don't support for now. I don't know when they are used. |
| 768 | // |
| 769 | // It was hard to piece this together, so writing it down here to explain why |
| 770 | // we magically picked the *_Complete variants. |
| 771 | if (auto dtor = llvm::dyn_cast<clang::CXXDestructorDecl>(named_decl)) { |
| 772 | decl = clang::GlobalDecl(dtor, clang::CXXDtorType::Dtor_Complete); |
| 773 | } else if (auto ctor = |
| 774 | llvm::dyn_cast<clang::CXXConstructorDecl>(named_decl)) { |
| 775 | decl = clang::GlobalDecl(ctor, clang::CXXCtorType::Ctor_Complete); |
| 776 | } else { |
| 777 | decl = clang::GlobalDecl(named_decl); |
| 778 | } |
| 779 | |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 780 | std::string name; |
| 781 | llvm::raw_string_ostream stream(name); |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 782 | mangler_->mangleName(decl, stream); |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 783 | stream.flush(); |
Marcel Hlopko | a5f59ae | 2021-08-24 20:38:04 +0000 | [diff] [blame] | 784 | return name; |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 785 | } |
| 786 | |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 787 | std::optional<UnqualifiedIdentifier> AstVisitor::GetTranslatedName( |
Marcel Hlopko | 7d73979 | 2021-08-12 07:52:47 +0000 | [diff] [blame] | 788 | const clang::NamedDecl* named_decl) const { |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 789 | switch (named_decl->getDeclName().getNameKind()) { |
| 790 | case clang::DeclarationName::Identifier: { |
| 791 | auto name = std::string(named_decl->getName()); |
| 792 | if (name.empty()) { |
Lukasz Anforowicz | 0c816f1 | 2021-12-15 17:41:49 +0000 | [diff] [blame] | 793 | if (const clang::ParmVarDecl* param_decl = |
| 794 | clang::dyn_cast<clang::ParmVarDecl>(named_decl)) { |
| 795 | int param_pos = param_decl->getFunctionScopeIndex(); |
| 796 | return {Identifier(absl::StrCat("__param_", param_pos))}; |
| 797 | } |
| 798 | // TODO(lukasza): Handle anonymous structs (probably this won't be an |
| 799 | // issue until nested types are handled - b/200067824). |
Devin Jeanpierre | f2ec871 | 2021-10-13 20:47:16 +0000 | [diff] [blame] | 800 | return std::nullopt; |
| 801 | } |
| 802 | return {Identifier(std::move(name))}; |
| 803 | } |
| 804 | case clang::DeclarationName::CXXConstructorName: |
| 805 | return {SpecialName::kConstructor}; |
| 806 | case clang::DeclarationName::CXXDestructorName: |
| 807 | return {SpecialName::kDestructor}; |
| 808 | default: |
| 809 | // To be implemented later: operators, conversion functions. |
| 810 | // There are also e.g. literal operators, deduction guides, etc., but |
| 811 | // we might not need to implement them at all. Full list at: |
| 812 | // https://clang.llvm.org/doxygen/classclang_1_1DeclarationName.html#a9ab322d434446b43379d39e41af5cbe3 |
| 813 | return std::nullopt; |
Devin Jeanpierre | e78b2fb | 2021-10-05 11:40:33 +0000 | [diff] [blame] | 814 | } |
Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 815 | } |
| 816 | |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 817 | void AstVisitor::CommentManager::TraverseDecl(clang::Decl* decl) { |
| 818 | ctx_ = &decl->getASTContext(); |
| 819 | |
| 820 | // When we go to a new file we flush the comments from the previous file, |
| 821 | // because source locations won't be comparable by '<' any more. |
| 822 | clang::FileID file = ctx_->getSourceManager().getFileID(decl->getBeginLoc()); |
Devin Jeanpierre | 96839c1 | 2021-12-14 00:27:38 +0000 | [diff] [blame] | 823 | // For example, we hit an invalid FileID for virtual destructor definitions. |
| 824 | if (file.isInvalid()) { |
| 825 | return; |
| 826 | } |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 827 | if (file != current_file_) { |
| 828 | FlushComments(); |
| 829 | current_file_ = file; |
| 830 | LoadComments(); |
| 831 | } |
| 832 | |
| 833 | // Visit all comments from the current file up to the current decl. |
| 834 | clang::RawComment* decl_comment = ctx_->getRawCommentForDeclNoCache(decl); |
| 835 | while (next_comment_ != file_comments_.end() && |
| 836 | (*next_comment_)->getBeginLoc() < decl->getBeginLoc()) { |
| 837 | // Skip the decl's doc comment, which will be emitted as part of the decl. |
| 838 | if (*next_comment_ != decl_comment) { |
| 839 | VisitTopLevelComment(*next_comment_); |
| 840 | } |
| 841 | ++next_comment_; |
| 842 | } |
| 843 | |
| 844 | // Skip comments that are within the decl, e.g., comments in the body of an |
| 845 | // inline function |
| 846 | // TODO(forster): We should retain floating comments within `Record`s |
| 847 | if (!clang::isa<clang::NamespaceDecl>(decl)) { |
| 848 | while (next_comment_ != file_comments_.end() && |
| 849 | (*next_comment_)->getBeginLoc() < decl->getEndLoc()) { |
| 850 | ++next_comment_; |
| 851 | } |
| 852 | } |
| 853 | } |
| 854 | |
| 855 | void AstVisitor::CommentManager::LoadComments() { |
| 856 | auto comments = ctx_->Comments.getCommentsInFile(current_file_); |
| 857 | if (comments) { |
| 858 | for (auto [_, comment] : *comments) { |
| 859 | file_comments_.push_back(comment); |
| 860 | } |
| 861 | } |
| 862 | next_comment_ = file_comments_.begin(); |
| 863 | } |
| 864 | |
| 865 | void AstVisitor::CommentManager::FlushComments() { |
| 866 | while (next_comment_ != file_comments_.end()) { |
| 867 | VisitTopLevelComment(*next_comment_); |
| 868 | next_comment_++; |
| 869 | } |
| 870 | file_comments_.clear(); |
| 871 | } |
| 872 | |
| 873 | void AstVisitor::CommentManager::VisitTopLevelComment( |
Michael Forster | 365bba1 | 2022-01-24 16:56:06 +0000 | [diff] [blame] | 874 | const clang::RawComment* comment) { |
| 875 | comments_.push_back(comment); |
Michael Forster | f1dce42 | 2021-10-13 09:50:16 +0000 | [diff] [blame] | 876 | } |
| 877 | |
Marcel Hlopko | e8f1c4e | 2021-07-28 18:12:49 +0000 | [diff] [blame] | 878 | } // namespace rs_bindings_from_cc |