/// Convenience typedef for a shared pointer on a @ref typedef_decl.
typedef shared_ptr<typedef_decl> typedef_decl_sptr;
+/// Convenience typedef for a weak pointer on a @ref typedef_decl.
+typedef weak_ptr<typedef_decl> typedef_decl_wptr;
+
/// The abstraction of a typedef declaration.
class typedef_decl : public virtual type_base, public virtual decl_base
{
virtual void
set_alignment_in_bits(size_t);
+ typedef_decl_sptr
+ get_naming_typedef() const;
+
+ void
+ set_naming_typedef(const typedef_decl_sptr&);
+
bool
get_is_declaration_only() const;
result.reset(new typedef_decl(name, utype, loc, linkage_name));
ctxt.associate_die_to_type(die, result, where_offset);
+
+ if (class_decl_sptr klass = is_class_type(utype))
+ if (is_anonymous_type(klass))
+ klass->set_naming_typedef(result);
+
return result;
}
/// Test if a given type is anonymous.
///
+/// Note that this function considers that an anonymous class that is
+/// named by a typedef is not anonymous anymore. This is the C idiom:
+///
+/// typedef struct {int member;} s_type;
+///
+/// The typedef s_type becomes the name of the originally anonymous
+/// struct.
+///
/// @param t the type to consider.
///
/// @return true iff @p t is anonymous.
is_anonymous_type(type_base* t)
{
decl_base* d = get_type_declaration(t);
- if (!d)
- return false;
- return d->get_is_anonymous();
+ if (d)
+ if (d->get_is_anonymous())
+ {
+ if (class_decl *klass = is_class_type(t))
+ {
+ // An anonymous class that is named by a typedef is not
+ // considered anonymous anymore.
+ if (!klass->get_naming_typedef())
+ return true;
+ }
+ else
+ return true;
+ }
+ return false;
}
/// Test if a given type is anonymous.
// <class_or_union definitions>
struct class_or_union::priv
{
+ typedef_decl_wptr naming_typedef_;
decl_base_sptr declaration_;
class_or_union_wptr definition_of_declaration_;
member_types member_types_;
}
}
+/// Getter for the naming typedef of the current class.
+///
+/// Consider the C idiom:
+///
+/// typedef struct {int member;} foo_type;
+///
+/// In that idiom, foo_type is the naming typedef of the anonymous
+/// struct that is declared.
+///
+/// @return the naming typedef, if any. Otherwise, returns nil.
+typedef_decl_sptr
+class_or_union::get_naming_typedef() const
+{
+ if (priv_->naming_typedef_.expired())
+ return typedef_decl_sptr();
+ return typedef_decl_sptr(priv_->naming_typedef_);
+}
+
+/// Set the naming typedef of the current instance of @ref class_decl.
+///
+/// Consider the C idiom:
+///
+/// typedef struct {int member;} foo_type;
+///
+/// In that idiom, foo_type is the naming typedef of the anonymous
+/// struct that is declared.
+///
+/// @param typedef_type the new naming typedef.
+void
+class_or_union::set_naming_typedef(const typedef_decl_sptr& typedef_type)
+{
+ priv_->naming_typedef_ = typedef_type;
+}
+
/// Set the definition of this declaration-only @ref class_or_union.
///
/// @param d the new definition to set.
string cl = "class ";
if (!internal && is_struct())
cl = "struct ";
+
+ // When computing the pretty representation for internal purposes,
+ // if an anonymous class is named by a typedef, then consider that
+ // it has a name, which is the typedef name.
+ if (internal && get_is_anonymous())
+ if (typedef_decl_sptr d = get_naming_typedef())
+ {
+ string qualified_name =
+ decl_base::priv_->qualified_parent_name_ + "::" + d->get_name();
+ return cl + qualified_name;
+ }
+
return cl + get_qualified_name(internal);
}
bool is_anonymous = false;
read_is_anonymous(node, is_anonymous);
+ string naming_typedef_id;
+ typedef_decl_sptr naming_typedef;
+
+ if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "naming-typedef-id"))
+ naming_typedef_id = xml::unescape_xml_string(CHAR_STR(s));
+ if (!naming_typedef_id.empty())
+ naming_typedef = is_typedef(ctxt.get_type_decl(naming_typedef_id));
+
assert(!id.empty());
class_decl_sptr previous_definition, previous_declaration;
const vector<type_base_sptr> *types_ptr = ctxt.get_all_type_decls(id);
decl->set_is_anonymous(is_anonymous);
}
+ if (naming_typedef)
+ decl->set_naming_typedef(naming_typedef);
+
string def_id;
bool is_def_of_decl = false;
if (xml_char_sptr s = XML_NODE_GET_ATTRIBUTE(node, "def-of-decl-id"))
ostream&);
static void write_is_struct(const class_decl_sptr&, ostream&);
static void write_is_anonymous(const decl_base_sptr&, ostream&);
+static void write_naming_typedef(const class_decl_sptr&, write_context&);
static bool write_decl(const decl_base_sptr&, write_context&, unsigned);
static void write_decl_in_scope(const decl_base_sptr&,
write_context&, unsigned);
o << " is-anonymous='yes'";
}
+/// Serialize the "naming-typedef-id" attribute, if the current
+/// instance of @ref class_decl has a naming typedef.
+///
+/// @param klass the @ref class_decl to consider.
+///
+/// @param ctxt the write context to use.
+static void
+write_naming_typedef(const class_decl_sptr& klass, write_context& ctxt)
+{
+ if (!klass)
+ return;
+
+ ostream &o = ctxt.get_ostream();
+
+ if (typedef_decl_sptr typedef_type = klass->get_naming_typedef())
+ {
+ string id = ctxt.get_id_for_type(typedef_type);
+ o << " naming-typedef-id='" << id << "'";
+ }
+}
+
/// Serialize a pointer to an of decl_base into an output stream.
///
/// @param decl the pointer to decl_base to serialize
write_is_anonymous(decl, o);
+ write_naming_typedef(decl, ctxt);
+
write_visibility(decl, o);
write_location(decl, o);