Skip to content

Commit e7b0557

Browse files
authored
Merge pull request #8248 from tautschnig/features/follow-struct_union_tag
Add namespacet::follow_struct_union_tag to simplify follow_tag uses
2 parents 9cbfe7e + 6cea206 commit e7b0557

File tree

4 files changed

+64
-5
lines changed

4 files changed

+64
-5
lines changed

Diff for: src/util/c_types.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,11 @@ inline union_typet &to_union_type(typet &type)
195195
}
196196

197197
/// A union tag type, i.e., \ref union_typet with an identifier
198-
class union_tag_typet : public tag_typet
198+
class union_tag_typet : public struct_or_union_tag_typet
199199
{
200200
public:
201201
explicit union_tag_typet(const irep_idt &identifier)
202-
: tag_typet(ID_union_tag, identifier)
202+
: struct_or_union_tag_typet(ID_union_tag, identifier)
203203
{
204204
}
205205
};

Diff for: src/util/namespace.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ namespace_baset::follow_tag(const c_enum_tag_typet &src) const
9292
return to_c_enum_type(symbol.type);
9393
}
9494

95+
const struct_union_typet &namespace_baset::follow_struct_or_union_tag(
96+
const struct_or_union_tag_typet &src) const
97+
{
98+
const symbolt &symbol = lookup(src.get_identifier());
99+
CHECK_RETURN(symbol.is_type);
100+
CHECK_RETURN(symbol.type.id() == ID_struct || symbol.type.id() == ID_union);
101+
return to_struct_union_type(symbol.type);
102+
}
103+
95104
/// Follow macros to their values in a given expression.
96105
/// \param expr: The expression to follow macros in.
97106
void namespace_baset::follow_macros(exprt &expr) const

Diff for: src/util/namespace.h

+6
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ class symbol_exprt;
2121
class tag_typet;
2222
class union_typet;
2323
class struct_typet;
24+
class struct_union_typet;
2425
class c_enum_typet;
2526
class union_tag_typet;
2627
class struct_tag_typet;
28+
class struct_or_union_tag_typet;
2729
class c_enum_tag_typet;
2830
class symbol_table_baset;
2931

@@ -68,6 +70,10 @@ class namespace_baset
6870
const struct_typet &follow_tag(const struct_tag_typet &) const;
6971
const c_enum_typet &follow_tag(const c_enum_tag_typet &) const;
7072

73+
/// Resolve a `struct_tag_typet` or `union_tag_typet` to the complete version.
74+
const struct_union_typet &
75+
follow_struct_or_union_tag(const struct_or_union_tag_typet &) const;
76+
7177
/// Returns the minimal integer n such that there is no symbol (in any of the
7278
/// symbol tables) whose name is of the form "An" where A is \p prefix.
7379
/// The intended use case is finding the next available symbol name for a

Diff for: src/util/std_types.h

+47-3
Original file line numberDiff line numberDiff line change
@@ -444,12 +444,56 @@ inline tag_typet &to_tag_type(typet &type)
444444
return static_cast<tag_typet &>(type);
445445
}
446446

447+
/// A struct or union tag type. This is only to be used to create type-safe /
448+
/// APIs, no instances of this one can be created directly, use \ref
449+
/// struct_tag_typet or \ref union_tag_typet when creating objects.
450+
class struct_or_union_tag_typet : public tag_typet
451+
{
452+
protected:
453+
struct_or_union_tag_typet(const irep_idt &id, const irep_idt &identifier)
454+
: tag_typet(id, identifier)
455+
{
456+
PRECONDITION(id == ID_struct_tag || id == ID_union_tag);
457+
}
458+
};
459+
460+
/// Check whether a reference to a typet is a \ref struct_or_union_tag_typet.
461+
/// \param type: Source type.
462+
/// \return True if \p type is a \ref struct_or_union_tag_typet.
463+
template <>
464+
inline bool can_cast_type<struct_or_union_tag_typet>(const typet &type)
465+
{
466+
return type.id() == ID_struct_tag || type.id() == ID_union_tag;
467+
}
468+
469+
/// \brief Cast a typet to a \ref struct_or_union_tag_typet
470+
///
471+
/// This is an unchecked conversion. \a type must be known to be \ref
472+
/// struct_or_union_tag_typet. Will fail with a precondition violation if type
473+
/// doesn't match.
474+
///
475+
/// \param type: Source type.
476+
/// \return Object of type \ref struct_or_union_tag_typet
477+
inline const struct_or_union_tag_typet &
478+
to_struct_or_union_tag_type(const typet &type)
479+
{
480+
PRECONDITION(can_cast_type<struct_or_union_tag_typet>(type));
481+
return static_cast<const struct_or_union_tag_typet &>(type);
482+
}
483+
484+
/// \copydoc to_struct_or_union_tag_type(const typet &)
485+
inline struct_or_union_tag_typet &to_struct_or_union_tag_type(typet &type)
486+
{
487+
PRECONDITION(can_cast_type<struct_or_union_tag_typet>(type));
488+
return static_cast<struct_or_union_tag_typet &>(type);
489+
}
490+
447491
/// A struct tag type, i.e., \ref struct_typet with an identifier
448-
class struct_tag_typet:public tag_typet
492+
class struct_tag_typet : public struct_or_union_tag_typet
449493
{
450494
public:
451-
explicit struct_tag_typet(const irep_idt &identifier):
452-
tag_typet(ID_struct_tag, identifier)
495+
explicit struct_tag_typet(const irep_idt &identifier)
496+
: struct_or_union_tag_typet(ID_struct_tag, identifier)
453497
{
454498
}
455499
};

0 commit comments

Comments
 (0)