Skip to content

Commit

Permalink
Update fixes for struct and union
Browse files Browse the repository at this point in the history
  • Loading branch information
leewei05 committed May 13, 2024
1 parent fd4fdb2 commit 60b6f43
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 26 deletions.
8 changes: 4 additions & 4 deletions include/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,17 @@ struct ArrDeclNode : public DeclNode {
std::vector<std::unique_ptr<ExprNode>> init_list;
};

/// @brief Record Declaration Node holds the definition of struct or union.
/// @brief This holds the declaration of struct or union type.
struct RecordDeclNode : public DeclNode {
RecordDeclNode(Location loc, std::string id, std::unique_ptr<Type> type,
std::vector<std::unique_ptr<FieldNode>> field_list)
std::vector<std::unique_ptr<FieldNode>> fields)
: DeclNode{loc, std::move(id), std::move(type)},
field_list{std::move(field_list)} {}
fields{std::move(fields)} {}

void Accept(NonModifyingVisitor&) const override;
void Accept(ModifyingVisitor&) override;

std::vector<std::unique_ptr<FieldNode>> field_list;
std::vector<std::unique_ptr<FieldNode>> fields;
};

/// @brief A field in a struct or an union.
Expand Down
9 changes: 3 additions & 6 deletions include/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,10 @@ class StructType : public Type {

class UnionType : public Type {
public:
/// @param selected_ The index of the selected field in the union.
explicit UnionType(std::vector<std::unique_ptr<Type>> field_types,
std::size_t selected = 0)
: field_types_{std::move(field_types)}, selected_{selected} {}
explicit UnionType(std::vector<std::unique_ptr<Type>> field_types)
: field_types_{std::move(field_types)} {}

bool IsStruct() const noexcept override {
bool IsUnion() const noexcept override {
return true;
}

Expand All @@ -210,7 +208,6 @@ class UnionType : public Type {

private:
std::vector<std::unique_ptr<Type>> field_types_;
std::size_t selected_;
};

#endif // TYPE_HPP_
14 changes: 5 additions & 9 deletions parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ func_def: declaration_specifiers declarator compound_stmt {
assert(dynamic_cast<FuncDefNode*>(func_def.get()));
assert(func_def->type->IsFunc());
const auto* func_type = static_cast<FuncType*>(func_def->type.get());
auto type = std::move(std::get<std::unique_ptr<Type>>($1));
auto type = std::get<std::unique_ptr<Type>>($1);
auto resolved_return_type = ResolveType(std::move(type), func_type->return_type().Clone());
auto param_types = std::vector<std::unique_ptr<Type>>{};
for (auto& param : func_type->param_types()) {
Expand Down Expand Up @@ -454,17 +454,13 @@ struct_or_union_specifier: struct_or_union id_opt LEFT_CURLY struct_declaration_
field_types.push_back(field->type->Clone());
}

if (dynamic_cast<StructType*>(type.get())) {
if (type->IsStruct()) {
type = std::make_unique<StructType>(std::move(field_types));
} else {
type = std::make_unique<UnionType>(std::move(field_types));
}

if (decl_id) {
$$ = std::make_unique<RecordDeclNode>(Loc(@2), std::move(decl_id->id), std::move(type), std::move(field_list));
} else {
$$ = std::make_unique<RecordDeclNode>(Loc(@2), /* no id */ "", std::move(type), std::move(field_list));
}
$$ = std::make_unique<RecordDeclNode>(Loc(@2), decl_id ? std::move(decl_id->id) : "", std::move(type), std::move(field_list));
}
| struct_or_union ID {
auto field_list = std::vector<std::unique_ptr<FieldNode>>{};
Expand Down Expand Up @@ -508,7 +504,7 @@ specifier_qualifier_list: type_specifier {
}
;

/* Identifier_opt is used for struct, union, enum. */
/* id_opt is used for struct, union, enum. */
id_opt: ID {
auto type = std::make_unique<PrimType>(PrimitiveType::kUnknown);
$$ = std::make_unique<VarDeclNode>(Loc(@1), $1, std::move(type));
Expand Down Expand Up @@ -626,7 +622,7 @@ parameter_declaration: declaration_specifiers declarator {
/* Declare parameters without identifiers. */
| declaration_specifiers abstract_declarator_opt {
// XXX: The identifier is empty.
auto type = std::move(std::get<std::unique_ptr<Type>>($1));
auto type = std::get<std::unique_ptr<Type>>($1);
$$ = std::make_unique<ParamNode>(Loc(@1), /* id */ "", ResolveType(std::move(type), $2));
}
;
Expand Down
2 changes: 1 addition & 1 deletion src/ast_dumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void AstDumper::Visit(const RecordDeclNode& record_decl) {
<< "> " << record_decl.type->ToString() << id << " definition\n";

indenter_.IncreaseLevel();
for (const auto& field : record_decl.field_list) {
for (const auto& field : record_decl.fields) {
field->Accept(*this);
}
indenter_.DecreaseLevel();
Expand Down
16 changes: 10 additions & 6 deletions src/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ std::unique_ptr<Type> FuncType::Clone() const {

bool StructType::IsEqual(const Type& that) const noexcept {
if (const auto* that_struct = dynamic_cast<const StructType*>(&that)) {
if (that_struct->size() != that.size()) {
if (that_struct->size() != size()) {
return false;
}
for (auto i = std::size_t{0}, e = field_types_.size(); i < e; ++i) {
Expand All @@ -171,8 +171,8 @@ bool StructType::IsEqual(const Type& that) const noexcept {
std::size_t StructType::size() const {
// TODO: There may be unnamed padding at the end of a structure or union.
auto size = std::size_t{0};
for (auto i = std::size_t{0}, e = field_types_.size(); i < e; ++i) {
size += field_types_.at(i)->size();
for (const auto& field_type : field_types_) {
size += field_type->size();
}
return size;
}
Expand All @@ -191,15 +191,19 @@ std::unique_ptr<Type> StructType::Clone() const {

bool UnionType::IsEqual(const Type& that) const noexcept {
if (const auto* that_union = dynamic_cast<const UnionType*>(&that)) {
return (that_union->selected_ == selected_) &&
(that_union->size() == size());
return that_union->size() == size();
}
return false;
}

std::size_t UnionType::size() const {
// The size of a union is sufficient to contain the largest of its members.
// TODO: There may be unnamed padding at the end of a structure or union.
return field_types_.at(selected_)->size();
auto size = std::size_t{0};
for (const auto& field_type : field_types_) {
size = std::max(size, field_type->size());
}
return size;
}

std::string UnionType::ToString() const {
Expand Down

0 comments on commit 60b6f43

Please sign in to comment.