Skip to content

Commit

Permalink
Add namespacet::follow_struct_or_union_tag to simplify follow_tag uses
Browse files Browse the repository at this point in the history
Replacing namespacet::follow by namespacet::follow_tag produced several
instances that require expanding composite data types, without a need to
distinguish structs vs unions.
  • Loading branch information
tautschnig committed Mar 22, 2024
1 parent 9cbfe7e commit 6cea206
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/util/c_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,11 @@ inline union_typet &to_union_type(typet &type)
}

/// A union tag type, i.e., \ref union_typet with an identifier
class union_tag_typet : public tag_typet
class union_tag_typet : public struct_or_union_tag_typet
{
public:
explicit union_tag_typet(const irep_idt &identifier)
: tag_typet(ID_union_tag, identifier)
: struct_or_union_tag_typet(ID_union_tag, identifier)
{
}
};
Expand Down
9 changes: 9 additions & 0 deletions src/util/namespace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ namespace_baset::follow_tag(const c_enum_tag_typet &src) const
return to_c_enum_type(symbol.type);
}

const struct_union_typet &namespace_baset::follow_struct_or_union_tag(

Check warning on line 95 in src/util/namespace.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/namespace.cpp#L95

Added line #L95 was not covered by tests
const struct_or_union_tag_typet &src) const
{
const symbolt &symbol = lookup(src.get_identifier());
CHECK_RETURN(symbol.is_type);
CHECK_RETURN(symbol.type.id() == ID_struct || symbol.type.id() == ID_union);
return to_struct_union_type(symbol.type);

Check warning on line 101 in src/util/namespace.cpp

View check run for this annotation

Codecov / codecov/patch

src/util/namespace.cpp#L98-L101

Added lines #L98 - L101 were not covered by tests
}

/// Follow macros to their values in a given expression.
/// \param expr: The expression to follow macros in.
void namespace_baset::follow_macros(exprt &expr) const
Expand Down
6 changes: 6 additions & 0 deletions src/util/namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ class symbol_exprt;
class tag_typet;
class union_typet;
class struct_typet;
class struct_union_typet;
class c_enum_typet;
class union_tag_typet;
class struct_tag_typet;
class struct_or_union_tag_typet;
class c_enum_tag_typet;
class symbol_table_baset;

Expand Down Expand Up @@ -68,6 +70,10 @@ class namespace_baset
const struct_typet &follow_tag(const struct_tag_typet &) const;
const c_enum_typet &follow_tag(const c_enum_tag_typet &) const;

/// Resolve a `struct_tag_typet` or `union_tag_typet` to the complete version.
const struct_union_typet &
follow_struct_or_union_tag(const struct_or_union_tag_typet &) const;

/// Returns the minimal integer n such that there is no symbol (in any of the
/// symbol tables) whose name is of the form "An" where A is \p prefix.
/// The intended use case is finding the next available symbol name for a
Expand Down
50 changes: 47 additions & 3 deletions src/util/std_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -444,12 +444,56 @@ inline tag_typet &to_tag_type(typet &type)
return static_cast<tag_typet &>(type);
}

/// A struct or union tag type. This is only to be used to create type-safe /
/// APIs, no instances of this one can be created directly, use \ref
/// struct_tag_typet or \ref union_tag_typet when creating objects.
class struct_or_union_tag_typet : public tag_typet
{
protected:
struct_or_union_tag_typet(const irep_idt &id, const irep_idt &identifier)
: tag_typet(id, identifier)
{
PRECONDITION(id == ID_struct_tag || id == ID_union_tag);
}
};

/// Check whether a reference to a typet is a \ref struct_or_union_tag_typet.
/// \param type: Source type.
/// \return True if \p type is a \ref struct_or_union_tag_typet.
template <>
inline bool can_cast_type<struct_or_union_tag_typet>(const typet &type)
{
return type.id() == ID_struct_tag || type.id() == ID_union_tag;
}

/// \brief Cast a typet to a \ref struct_or_union_tag_typet
///
/// This is an unchecked conversion. \a type must be known to be \ref
/// struct_or_union_tag_typet. Will fail with a precondition violation if type
/// doesn't match.
///
/// \param type: Source type.
/// \return Object of type \ref struct_or_union_tag_typet
inline const struct_or_union_tag_typet &
to_struct_or_union_tag_type(const typet &type)
{
PRECONDITION(can_cast_type<struct_or_union_tag_typet>(type));
return static_cast<const struct_or_union_tag_typet &>(type);
}

/// \copydoc to_struct_or_union_tag_type(const typet &)
inline struct_or_union_tag_typet &to_struct_or_union_tag_type(typet &type)
{
PRECONDITION(can_cast_type<struct_or_union_tag_typet>(type));
return static_cast<struct_or_union_tag_typet &>(type);
}

/// A struct tag type, i.e., \ref struct_typet with an identifier
class struct_tag_typet:public tag_typet
class struct_tag_typet : public struct_or_union_tag_typet
{
public:
explicit struct_tag_typet(const irep_idt &identifier):
tag_typet(ID_struct_tag, identifier)
explicit struct_tag_typet(const irep_idt &identifier)
: struct_or_union_tag_typet(ID_struct_tag, identifier)
{
}
};
Expand Down

0 comments on commit 6cea206

Please sign in to comment.