public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Nathan Sidwell <nathan@acm.org>
To: Martin Sebor <msebor@gmail.com>,
	Gcc Patch List <gcc-patches@gcc.gnu.org>
Subject: Re: correct attribute ifunc C++ type safety (PR 82301)
Date: Thu, 28 Sep 2017 14:26:00 -0000	[thread overview]
Message-ID: <fa7cea04-b394-539c-50ea-3f7387cff929@acm.org> (raw)
In-Reply-To: <42ebe275-53db-35c9-4199-85b7423cd711@gmail.com>

On 09/24/2017 06:03 PM, Martin Sebor wrote:
> r253041 enhanced type checking for alias and ifunc attributes to
> detect declarations of incompatible aliases, or ifunc resolvers
> that return pointers to functions of an incompatible type.  More
> extensive testing exposed a bug in the implementation of the ifunc
> attribute handling in C++ where the checker expected the ifunc
> resolver to return a pointer to a member function when the
> implementation actually expects it return a pointer to a non-
> member function.
> 
> In a discussion of the test suite failures, Jakub also suggested
> to break the enhanced warning out of -Wattributes and issue it
> under a different option.
> 
> The attached patch corrects the C++ problem and moves the warning
> under -Wincompatible-pointer-types.  Since this is a C-only option,
> the patch also enables for it C++.  Since the option is enabled by
> default, the patch further requires -Wextra to issue the warning
> for ifunc resolvers returning void*.  However, the patched checker
> diagnoses other incompatibilities without it.
> 
> Martin

I find the maybe_diag_incompatible_alias function confusing.

> +/* Check declaration of the type of ALIAS for compatibility with its TARGET
> +   (which may be an ifunc resolver) and issue a diagnostic when they are
> +   not compatible according to language rules (plus a C++ extension for
> +   non-static member functions).  */
> +
> +static void
> +maybe_diag_incompatible_alias (tree alias, tree target)
> +{
> +  tree altype = TREE_TYPE (alias);
> +  tree targtype = TREE_TYPE (target);
> +
> +  bool ifunc = lookup_attribute ("ifunc", DECL_ATTRIBUTES (alias));
> +  if (ifunc)

I think it might be clearer if this was broken out into a diag_ifunc 
function?  But see below ...

> +    {
> +      /* Handle attribute ifunc first.  */
> +
> +      tree funcptr = altype;
> +
> +      /* Set FUNCPTR to the type of the alias target.  If the type
> +	 is a non-static member function of class C, construct a type
> +	 of an ordinary function taking C* as the first argument,
> +	 followed by the member function argument list, and use it
> +	 instead to check for compatibilties.  FUNCPTR is used only
> +	 in diagnostics.  */

This comment is self-contradictory.
   1 Set FUNCPTR
   2 Do some method-type shenanigans
   3 Use it to check for incompatibilites
   4 FUNCPTR is only used in diags

Which of #3 and #4 is true?


> +
> +      if (TREE_CODE (altype) == METHOD_TYPE)
> +	{

IMHO put the description of the METHOD_TYPE chicanery inside the block 
doing it?  FWIW, although the change being made works on many (most?) 
ABIs, it's not formally correct and I think fails on some where 'this' 
is passed specially. You might want to note that?

> +	  tree rettype = TREE_TYPE (altype);
> +	  tree args = TYPE_ARG_TYPES (altype);
> +	  altype = build_function_type (rettype, args);
> +	  funcptr = altype;
> +	}
> +

> +	  if ((!FUNC_OR_METHOD_TYPE_P (targtype)
> +	       || (prototype_p (altype)
> +		   && prototype_p (targtype)
> +		   && !types_compatible_p (altype, targtype))))
> +	    {
> +	      funcptr = build_pointer_type (funcptr);
> +
> +	      if (warning_at (DECL_SOURCE_LOCATION (target),
> +			      OPT_Wincompatible_pointer_types,
> +			      "%<ifunc%> resolver for %qD should return %qT",
> +			      alias, funcptr))
> +		inform (DECL_SOURCE_LOCATION (alias),
> +			"resolver indirect function declared here");
> +	    }

this block is almost the same as the non-ifunc block.  Surely they can 
be the same code? (by generalizing one of the cases until it turns into 
the other?)


> +	  /* Deal with static member function pointers.  */

I do not understand this comment or condition. We seem to have dealt 
with pointers already and the conditions seem confused.

> +	  if (TREE_CODE (targtype) != RECORD_TYPE
> +	      || TYPE_FIELDS (targtype)
> +	      || TREE_CODE (TREE_TYPE (TYPE_FIELDS (targtype))) != POINTER_TYPE
> +	      || (TREE_CODE (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (targtype))))
> +		  != METHOD_TYPE))

if
   not a record,
   or has TYPE_FIELDS non-NULL
   or the first field doesn't have pointer type (we can't get here)
   or something else about the first field

oh, I think it's trying to spot the pointer to NON-static member 
function internal record type.  But brokenly. I think pmf record_types 
have DECL_ARTIFICIAL and BUILTIN_LOCATION, that might be useful.

> +	    {
> +	      funcptr = build_pointer_type (funcptr);
> +
> +	      error ("%<ifunc%> resolver for %qD must return %qT",
> +		     alias, funcptr);
> +			
> +	      inform (DECL_SOURCE_LOCATION (alias),
> +		      "resolver indirect function declared here");
> +	    }
> +	}
> +

> +  if ((!FUNC_OR_METHOD_TYPE_P (targtype)
> +       || (prototype_p (altype)
> +	   && prototype_p (targtype)
> +	   && !types_compatible_p (altype, targtype))))

Similar to above, already noted.

Is this function called before we know whether we've enabled the 
appropriate warnings?  It would be better to bail out sooner if the 
warnings are disabled.

nathan

-- 
Nathan Sidwell

  parent reply	other threads:[~2017-09-28 14:26 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-25  1:03 Martin Sebor
2017-09-27 15:22 ` Martin Sebor
2017-09-28 11:23 ` Pedro Alves
2017-09-29 15:57   ` Martin Sebor
2017-09-28 14:26 ` Nathan Sidwell [this message]
2017-10-04 19:40   ` Martin Sebor
2017-10-11 11:53     ` Nathan Sidwell
2017-10-11 17:26       ` Jeff Law
2017-10-11 16:32     ` [PING] " Martin Sebor
2017-10-11 16:34       ` Nathan Sidwell
2017-10-11 16:46         ` Martin Sebor

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=fa7cea04-b394-539c-50ea-3f7387cff929@acm.org \
    --to=nathan@acm.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=msebor@gmail.com \
    /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).