Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion rs_bindings_from_cc/decl_importer.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ class Invocation {
Invocation(
BazelLabel target, absl::Span<const HeaderName> public_headers,
const absl::flat_hash_map<HeaderName, BazelLabel>& header_targets,
std::optional<absl::flat_hash_set<std::string>> do_not_bind_allowlist)
std::optional<absl::flat_hash_set<std::string>> do_not_bind_allowlist,
absl::flat_hash_map<BazelLabel, absl::flat_hash_set<std::string>>
crubit_features)
: target_(target),
public_headers_(public_headers),
lifetime_context_(std::make_shared<
Expand All @@ -49,6 +51,7 @@ class Invocation {
ir_.public_headers.insert(ir_.public_headers.end(), public_headers_.begin(),
public_headers.end());
ir_.current_target = target_;
ir_.crubit_features = std::move(crubit_features);
}

// Returns the target of a header, if any.
Expand Down Expand Up @@ -161,6 +164,9 @@ class ImportContext {
// other redeclarations of the decl.
virtual bool IsFromProtoTarget(const clang::Decl& decl) const = 0;

// Returns true iff `label` has opted in to crubit support.
virtual bool IsCrubitEnabledForTarget(const BazelLabel& label) const = 0;

// Gets an IR UnqualifiedIdentifier for the named decl.
//
// If the decl's name is an identifier, this returns that identifier as-is.
Expand Down
24 changes: 24 additions & 0 deletions rs_bindings_from_cc/importer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,20 @@ bool Importer::IsFromProtoTarget(const clang::Decl& decl) const {
return filename.has_value() && filename->ends_with(".proto.h");
}

bool Importer::IsCrubitEnabledForTarget(const BazelLabel& label) const {
if (auto i = invocation_.ir_.crubit_features.find(label);
i != invocation_.ir_.crubit_features.end()) {
return !i->second.empty();
}
// DO NOT SUBMIT: this should have a proper target assignment.
if (label.value().find("support") == std::string::npos) {
// fprintf(stderr, "Crubit is not enabled for target %s\n",
// label.value().c_str());
return false;
}
return true;
}

IR::Item Importer::HardError(const clang::Decl& decl, FormattedError error) {
return ImportUnsupportedItem(decl, std::nullopt, {error},
/*is_hard_error=*/true);
Expand Down Expand Up @@ -1061,6 +1075,16 @@ absl::StatusOr<CcType> Importer::ConvertTemplateSpecializationType(
type_string));
}

if (auto* template_decl = type->getTemplateName().getAsTemplateDecl()) {
auto target = GetOwningTarget(template_decl);
if (!IsCrubitEnabledForTarget(target)) {
return absl::InvalidArgumentError(absl::Substitute(
"Failed to complete template specialization type $0: template "
"belongs to target $1, which does not support Crubit.",
type_string, target.value()));
}
}

if (HasBeenAlreadySuccessfullyImported(specialization_decl))
return ConvertTypeDecl(specialization_decl);

Expand Down
1 change: 1 addition & 0 deletions rs_bindings_from_cc/importer.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class Importer final : public ImportContext {
BazelLabel GetOwningTarget(const clang::Decl* decl) const override;
bool IsFromCurrentTarget(const clang::Decl* decl) const override;
bool IsFromProtoTarget(const clang::Decl& decl) const override;
bool IsCrubitEnabledForTarget(const BazelLabel& label) const override;
absl::StatusOr<TranslatedUnqualifiedIdentifier> GetTranslatedName(
const clang::NamedDecl* named_decl) const override;
absl::StatusOr<TranslatedIdentifier> GetTranslatedIdentifier(
Expand Down
4 changes: 2 additions & 2 deletions rs_bindings_from_cc/ir_from_cc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ absl::StatusOr<IR> IrFromCc(IrFromCcOptions options) {

Invocation invocation(options.current_target, augmented_public_headers,
options.headers_to_targets,
std::move(options.do_not_bind_allowlist));
std::move(options.do_not_bind_allowlist),
std::move(options.crubit_features));
if (!clang::tooling::runToolOnCodeWithArgs(
std::make_unique<FrontendAction>(invocation),
virtual_input_file_content, args_as_strings,
Expand All @@ -238,7 +239,6 @@ absl::StatusOr<IR> IrFromCc(IrFromCcOptions options) {
!status.ok()) {
return status;
}
invocation.ir_.crubit_features = std::move(options.crubit_features);
return invocation.ir_;
}

Expand Down
4 changes: 4 additions & 0 deletions rs_bindings_from_cc/recording_diagnostic_consumer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ std::string RecordingDiagnosticConsumer::ConcatenatedDiagnostics(
RecordingDiagnosticConsumer RecordDiagnostics(
clang::DiagnosticsEngine& diagnostic_engine,
std::function<void(void)> callback) {
// Reset the diagnostic engine to a known state. In particular, if there were
// too many diagnostics reported previously (even in sfinae contexts),
// the diagnostic engine's fatal bit will get stuck on.
diagnostic_engine.Reset(/*soft=*/true);
RecordingDiagnosticConsumer diagnostic_recorder;
std::unique_ptr<clang::DiagnosticConsumer> original_consumer =
diagnostic_engine.takeClient();
Expand Down