Skip to content

Commit

Permalink
Fix clash of enum shared discriminant
Browse files Browse the repository at this point in the history
gcc/rust/ChangeLog:

	* backend/rust-compile-item.cc (CompileItem::visit):
	Use HIR::Enum visit
	* backend/rust-compile-item.h: Fix clash of enum shared
	discriminant
	* backend/rust-compile-type.cc (check_variant_record_collision):
	Likewise
	(TyTyResolveCompile::visit): Likewise.
  • Loading branch information
badumbatish committed Feb 26, 2025
1 parent cb56731 commit 3b6dc56
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
11 changes: 11 additions & 0 deletions gcc/rust/backend/rust-compile-item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,17 @@ CompileItem::visit (HIR::Function &function)
ctx->pop_const_context ();
}

void
CompileItem::visit (HIR::Enum &e)
{
TyTy::BaseType *resolved_type = nullptr;
bool ok = ctx->get_tyctx ()->lookup_type (e.get_mappings ().get_hirid (),
&resolved_type);
rust_assert (ok);

tree type = TyTyResolveCompile::compile (ctx, resolved_type);
reference = type;
}
void
CompileItem::visit (HIR::ImplBlock &impl_block)
{
Expand Down
3 changes: 1 addition & 2 deletions gcc/rust/backend/rust-compile-item.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor
void visit (HIR::ImplBlock &impl_block) override;
void visit (HIR::ExternBlock &extern_block) override;
void visit (HIR::Module &module) override;

void visit (HIR::Enum &) override;
// Empty visit for unused Stmt HIR nodes.
void visit (HIR::TupleStruct &) override {}
void visit (HIR::EnumItem &) override {}
Expand All @@ -62,7 +62,6 @@ class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor
void visit (HIR::UseDeclaration &) override {}
void visit (HIR::TypeAlias &) override {}
void visit (HIR::StructStruct &) override {}
void visit (HIR::Enum &) override {}
void visit (HIR::Union &) override {}
void visit (HIR::Trait &) override {}
void visit (HIR::EmptyStmt &) override {}
Expand Down
50 changes: 46 additions & 4 deletions gcc/rust/backend/rust-compile-type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
// <http://www.gnu.org/licenses/>.

#include "rust-compile-type.h"
#include "rust-compile-context.h"
#include "rust-compile-expr.h"
#include "rust-constexpr.h"
#include "rust-gcc.h"

#include "tree.h"
#include "stor-layout.h"
#include <cstdio>

namespace Rust {
namespace Compile {
Expand Down Expand Up @@ -239,14 +241,54 @@ TyTyResolveCompile::visit (const TyTy::FnPtr &type)
type.get_ident ().locus);
}

void
check_variant_record_collision (Context *ctx, const TyTy::ADTType &type,
std::vector<tree> &variant_records)
{
// bdbt: we're checking if shared discriminants crash with each other or
// not. lets make a map from uhwi to hir id. A clash of uhwi in a variant
// record to which said record can be converted uhwi is indicative of
// issue 3351 of gccrs

size_t i = 0;
std::map<HOST_WIDE_INT, std::vector<size_t>> shwi_to_index;
for (; i < variant_records.size (); i++)
{
TyTy::VariantDef *variant = type.get_variants ().at (i);
if (variant->has_discriminant ())
{
tree discriminant_expr
= CompileExpr::Compile (variant->get_discriminant (), ctx);
HOST_WIDE_INT discriminant_integer
= tree_to_shwi (fold_expr (discriminant_expr));
shwi_to_index[discriminant_integer].push_back (i);
}
}

for (auto &[discriminant_integer, index_vector] : shwi_to_index)
{
// collision happens
if (index_vector.size () >= 2)
{
rust_error_at (type.get_locus (), ErrorCode::E0081,
"discriminant value `%d` assigned more than once",
discriminant_integer);
for (auto index : index_vector)
{
TyTy::VariantDef *variant = type.get_variants ().at (index);
rust_error_at (variant->get_discriminant ().get_locus (),
"`%d` assigned here", discriminant_integer);
}
}
}
}
void
TyTyResolveCompile::visit (const TyTy::ADTType &type)
{
tree type_record = error_mark_node;
if (!type.is_enum ())
{
rust_assert (type.number_of_variants () == 1);

TyTy::VariantDef &variant = *type.get_variants ().at (0);
std::vector<Backend::typed_identifier> fields;
for (size_t i = 0; i < variant.num_fields (); i++)
Expand Down Expand Up @@ -349,9 +391,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type)
// add them to the list
variant_records.push_back (named_variant_record);
}

// now we need to make the actual union, but first we need to make
// named_type TYPE_DECL's out of the variants
check_variant_record_collision (ctx, type, variant_records);
// the actual union, but first we need to make named_type TYPE_DECL's out
// of the variants

size_t i = 0;
std::vector<Backend::typed_identifier> enum_fields;
Expand Down

0 comments on commit 3b6dc56

Please sign in to comment.