public inbox for libabigail@sourceware.org
 help / color / mirror / Atom feed
From: Ondrej Oprala <ooprala@redhat.com>
To: Dodji Seketeli <dodji@seketeli.org>
Cc: libabigail@sourceware.org
Subject: Re: Support for function pointers and references
Date: Thu, 01 Jan 2015 00:00:00 -0000	[thread overview]
Message-ID: <560A90E1.3050709@redhat.com> (raw)
In-Reply-To: <861tdh4n5e.fsf@seketeli.org>



On 29.09.2015 10:58, Dodji Seketeli wrote:
> Hello Ondrej,
>
> I have been looking at the second and last patch of the series:
>
>      commit 18a700ff0751a0c578a8c5c59abc5c87c8143335
>      Author: Ondrej Oprala <ooprala@redhat.com>
>      Date:   Wed Sep 23 08:44:00 2015 +0200
>
> 	Support pointers and references to functions
>
> Again, great patch.  Thanks for your hard work.
>
> I have a few comments that you'll find below.
>
> diff --git a/include/abg-ir.h b/include/abg-ir.h
>
> [...]
>
> @@ -1042,6 +1045,7 @@ public:
>   
>     /// Convenience typedef for a vector of @ref decl_base_sptr.
>     typedef std::vector<decl_base_sptr >	declarations;
> +  typedef std::vector<function_type_sptr >	function_types;
>
> Please add a comment for this typedef (starting with "///") so that
> the apidoc is updated, just like what we do for the other typedefs.  I
> agree this commenting business feels cumbersome but then later we're
> happy when we enjoy the completeness of the apidoc :-)
>
>
> [...]
>
> @@ -5986,7 +5986,6 @@ compute_diff_for_types(const decl_base_sptr first,
>      ||(d = try_to_diff<array_type_def>(f, s, ctxt))
>      ||(d = try_to_diff<qualified_type_def>(f, s, ctxt))
>      ||(d = try_to_diff<typedef_decl>(f, s, ctxt))
> -   ||(d = try_to_diff<function_type>(f, s, ctxt))
>      ||(d = try_to_diff_distinct_kinds(f, s, ctxt)));
>
> Why avoid handling function types here, to just handle them ...
>
>      @@ -7138,9 +7137,21 @@ compute_diff(pointer_type_def_sptr	first,
>         if (first && second)
>           assert(first->get_environment() == second->get_environment());
>
>      -  diff_sptr d = compute_diff_for_types(first->get_pointed_to_type(),
>      -				       second->get_pointed_to_type(),
>      -				       ctxt);
>      +  diff_sptr d;
>      +
>      +  function_type_sptr f = dynamic_pointer_cast<function_type>(first->get_pointed_to_type()),
>      +		     g = dynamic_pointer_cast<function_type>(second->get_pointed_to_type());
>      +  if (f && g)
>      +    d = compute_diff(f, g, ctxt);
>      +  else if (f || g)
>      +    d = try_to_diff_distinct_kinds(first->get_pointed_to_type(),
>      +				   second->get_pointed_to_type(),
>      +				   ctxt);
>      +  else
>      +    d = compute_diff_for_types(first->get_pointed_to_type(),
>      +			       second->get_pointed_to_type(),
>      +			       ctxt);
>      +
>
> ... here ?
>
> I would think that compute_diff_for_type() would handle the two
> pointer types fine; then the overload of compute_diff() for pointer
> types would call compute_diff_for_type() on the pointed-to types,
> again; then compute_diff_for_type() *should* handle all the cases of
> pointed-to types; if not, it should extended to do so.  What am I
> missing?
You're right, fixed now.
> diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc
>
> [...]
>
> +	      /* For now, we skip the hidden vtable pointer */
> +	      if (n.substr(0, 5) == "_vptr"
> +		  && !std::isalnum(n.at(5))
> +		  && n.at(5) != '_')
> +                continue;
>
> Please add a comment explaining the (name) pattern you are looking for
> to recognize the vtable pointer member here.  In these matters, I
> believe redundancy of information is helpful to catch issues later.
>
> -    utype_decl =
> -      dynamic_pointer_cast<decl_base>(build_ir_node_for_void_type(ctxt));
>
> Hehe, see, I was using the dynamic_pointer_cast, rather than using the
> 'is_decl()' function I told you about earlier.  Bad bad me.  :-)
>
> It's cool how your changes removed those, by the way.
>
> Initially the code base had a lot of these; but then after I have
> started to debug the code base a little bit more, it appeared that using
> the is_*() function was much more practical.  So I introduced them in
> new code, updated some old code, but obviously, some old code still
> needs to be updated.  I think we'll need to provide some patches later
> to update the code towards that end.
>
> [...]
>
> +static function_type_sptr
> +build_function_type(read_context&	ctxt,
> +		    Dwarf_Die*		die,
> +		    bool		die_is_from_alt_di,
> +		    class_decl_sptr	is_method,
> +		    size_t		where_offset)
> +{
>
> [...]
>
> +    return_type_decl = dynamic_pointer_cast<decl_base>(
> +      build_ir_node_from_die(ctxt, &ret_type_die,
> +			     ret_type_die_is_in_alternate_debug_info,
> +			     /*called_from_public_decl=*/true,
> +			     where_offset));
>
> Please use is_decl() here.
>
> [...]
>
> +  if (!result && dwarf_child(die, &child) == 0)
> +    do
> +      {
>
> It seems to me the !result clause is useless here; is it not?
>
> I understand that you took this code from the former
> build_function_decl() code; in that former context, the !result clause
> was not useless because the 'result' could have been initialized to a
> non-nil declaration.  But here, I don't see that.
Oops, you're right
> [...]
>
> +	      parm_type_decl = dynamic_pointer_cast<decl_base>(
> +		build_ir_node_from_die(ctxt, &parm_type_die,
> +				       parm_type_die_is_in_alt_di,
> +				       /*called_from_public_decl=*/true,
> +				       where_offset));
>
> Please use is_decl() rather than the dynamic_pointer_cast.
>
> [...]
>
> +      }
> +  while (!result && dwarf_siblingof(&child, &child) == 0);
>
> Here, I think the !result clause is useless as well.
>
> By the way, build_function_type() is cool, I like it :-)
>
> and using it here ...
>
>      @@ -7315,75 +7447,10 @@ build_function_decl(read_context&	ctxt,
>      [...]
>
>      +      function_type_sptr fn_type(build_function_type(ctxt,
>      +						     die,
>      +						     is_in_alt_di,
>      +						     is_method,
>      +						     where_offset));
>
> looks very natural much more than what I was doing.  That is super cool.
> thank you for that!
>
> [...]
>
> diff --git a/src/abg-ir.cc b/src/abg-ir.cc
> [...]
>
> +/// Getter of the the function types of the current @ref translation
> +/// unit.
>
> There is a "the the" repetition there.  Also, it should be @ref translation_unit.
>
> [...]
>
> @@ -6541,16 +6549,16 @@ pointer_type_def::pointer_type_def(const type_base_sptr&
> [...]
>
> +      if (pto)
> +        set_visibility(pto->get_visibility());
> +      pointed_to_type_ = weak_ptr<type_base>(type_or_void(pointed_to, 0));
>
> Please use the type_base_wptr typedef here, rather than the longer
> weak_ptr<type_base> notation.
>
> -	name = "void";
> +        name = get_type_name(get_pointed_to_type(), /*qualified_name=*/true);
>
> It looks like there is a white space issue here.  Normally, before the
> "name" token, there should be one tab, not 8 white spaces.
>
> [...]
>
> +      else
> +        name = get_type_name(dynamic_pointer_cast<function_type>(pointed_to),
> +			     /*qualified_name=*/true) + "&";
>
> Please use is_function_type() here, rather than
> dynamic_pointer_cast().
>
> [...]
>
> +
> +      pointed_to_type_ = weak_ptr<type_base>(type_or_void(pointed_to, 0));
>
> Please use type_base_wptr.
>
> [...]
>
> @@ -6808,7 +6825,10 @@ reference_type_def::get_qualified_name() const
>   	get_type_declaration(type_or_void(get_pointed_to_type(),
>   					  get_environment()));
>         string name;
> -      td->get_qualified_name(name);
> +      if (!td)
> +	name = get_type_name(get_pointed_to_type(), /*qualified_name=*/true);
> +      else
> +	td->get_qualified_name(name);
>
> I think we could do away with 'td' completely. I mean Let's not even
> try to get the type declaration here.  Let's just use get_type_name()
> as it knows how to handle types that don't have declarations.  It'll
> make the logic simpler and thus easier to maintain later.
>
> [...]
>
> diff --git a/src/abg-writer.cc b/src/abg-writer.cc
> [...]
> @@ -1232,6 +1266,9 @@ write_pointer_type_def(const pointer_type_def_sptr	decl
> [...]
>
> +  if (dynamic_pointer_cast<function_type>(decl->get_pointed_to_type()))
> +    ctxt.record_type_as_emitted(decl->get_pointed_to_type());
> +
>
> I think that as the pointed to type is *not* written here, it should
> not be marked as being written.
>
> My understanding is that the reason why you are doing this hack is that
> only function types that are referenced via function pointers should be
> emitted.  Other functions types that are not referenced by function
> pointers should not be emitted.  Is that the case?
>
> If so, what you could do instead, is to keep a (well documented) map of
> "function types to emit", on the side.  Note that the key of the map
> would be the pointer *value* of the canonical type of the function type.
> So when you are here:
>
>      @@ -971,6 +991,20 @@ write_translation_unit(const translation_unit&	tu,
>      [...]
>      +  typedef scope_decl::function_types function_types;
>      +  typedef function_types::const_iterator const_fn_iterator;
>      +  const function_types& t = tu.get_function_types();
>      +
>      +  for (const_fn_iterator i = t.begin(); i != t.end(); ++i)
>      +    {
>      +      if (!ctxt.type_is_emitted(dynamic_pointer_cast<type_base>(*i)))
>      +	// This type has already been written out to the current
>      +	// translation unit, so do not emit it again.
>      +	continue;
>      +      o << "\n";
>      +      write_function_type(*i, ctxt, indent + c.get_xml_element_indent());
>      +    }
>      +
>
> , you can then check that the function type you are about to emit is
> part of the map of function types to emit.  If it is, then emit it
> (that would mark the function type as having been emitted) and remove
> it from the map of function pointers to emit.  You can thus assert
> that a function type that is in the map of the function types to emit
> has *not* been emitted yet.
>
> Then you can remove this:
>
>      +  void
>      +  record_type_id_as_not_emitted(const string& id)
>      +  {m_emitted_type_id_map.erase(id);}
>
> , this,
>
>      +  void
>      +  record_type_as_not_emitted(const type_base_sptr& t)
>
> and this (in the new write_function_type()):
>
>      +  ctxt.record_type_as_not_emitted(decl);

Yeah, I tried to hack around it using existing code...should be much 
better now.
>
> Cheers,
>
I've rebased, fixed and amended both patches and they're in 
ondrej/fnptrs again. Thank you for your review!
Cheers,
   Ondrej

  reply	other threads:[~2015-09-29 13:23 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-01  0:00 Ondrej Oprala
2015-01-01  0:00 ` Dodji Seketeli
2015-01-01  0:00   ` Ondrej Oprala [this message]
2015-01-01  0:00     ` Dodji Seketeli
2015-01-01  0:00       ` Ondrej Oprala
2015-01-01  0:00         ` Dodji Seketeli
2015-01-01  0:00           ` Ondrej Oprala
2015-01-01  0:00 ` Dodji Seketeli
2015-01-01  0:00 ` Dodji Seketeli
2015-01-01  0:00   ` Ondrej Oprala

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=560A90E1.3050709@redhat.com \
    --to=ooprala@redhat.com \
    --cc=dodji@seketeli.org \
    --cc=libabigail@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).