This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC PATCH] avoid applying attributes to explicit specializations (PR 83871)


On Fri, Feb 9, 2018 at 6:57 PM, Martin Sebor <msebor@gmail.com> wrote:
> On 02/09/2018 12:52 PM, Jason Merrill wrote:
>> On 02/08/2018 04:52 PM, Martin Sebor wrote:
>>>
>>> I took me a while to find DECL_TEMPLATE_RESULT.  Hopefully
>>> that's the right way to get the primary from a TEMPLATE_DECL.
>>
>> Yes.
>>
>>>>> Attached is an updated patch.  It hasn't gone through full
>>>>> testing yet but please let me know if you'd like me to make
>>>>> some changes.
>>>>
>>>>
>>>>> +  const char* const whitelist[] = {
>>>>> +    "error", "noreturn", "warning"
>>>>> +  };
>>>>
>>>>
>>>> Why whitelist noreturn?  I would expect to want that to be consistent.
>>>
>>> I expect noreturn to be used on a primary whose definition
>>> is provided but that's not meant to be used the way the API
>>> is otherwise expected to be.  As in:
>>>
>>>    template <class T>
>>>    T [[noreturn]] foo () { throw "not implemented"; }
>>>
>>>    template <> int foo<int>();   // implemented elsewhere
>>
>> Marking that template as noreturn seems pointless, and possibly harmful;
>> the deprecated, warning, or error attributes would be better for this
>> situation.
>
> I meant either:
>
>   template <class T>
>   T __attribute__ ((noreturn)) foo () { throw "not implemented"; }
>
>   template <> int foo<int>();   // implemented elsewhere
>
> or (sigh)
>
>   template <class T>
>   [[noreturn]] T foo () { throw "not implemented"; }
>
>   template <> int foo<int>();   // implemented elsewhere
>
> It lets code like this
>
>   int bar ()
>   {
>      return foo<char>();
>   }
>
> be diagnosed because it's likely a bug (as Clang does with
> -Wunreachable-code).  It doesn't stop code like the following
> from compiling (which is good) but it instead lets them throw
> at runtime which is what foo's author wants.
>
>   void bar ()
>   {
>      foo<char>();
>   }
>
> It's the same as having an "unimplemented" base virtual function
> throw an exception when it's called rather than making it pure
> and having calls to it abort.  Declaring the base virtual function
> noreturn is useful for the same reason (and also diagnosed by
> Clang).  I should remember to add the same warning in GCC 9.

Yes, I understood the patterns you had in mind, but I disagree with
them.  My point about harmful is that declaring a function noreturn
because it's unimplemented could be a problem for when the function is
later implemented, and callers were optimized inappropriately.  This
seems like a rather roundabout way to get a warning about calling an
unimplemented function, and not worth overriding the normal behavior.

> I actually had some misgivings about both warning and deprecated
> for the white-listing, but not for noreturn.  My (only mild)
> concern is that both warning and deprecated functions can and
> likely will in some cases still be called, and so using them to
> suppress the warning runs the risk that their calls might be
> wrong and no one will notice.  Warning cannot be suppressed
> so it seems unlikely to be ignored, but deprecated can be.
> So I wonder if the white-listing for deprecated should be
> conditional on -Wdeprecated being enabled.
>
>>> -      /* Merge the type qualifiers.  */
>>> -      if (TREE_READONLY (newdecl))
>>> -    TREE_READONLY (olddecl) = 1;
>>>        if (TREE_THIS_VOLATILE (newdecl))
>>>      TREE_THIS_VOLATILE (olddecl) = 1;
>>> -      if (TREE_NOTHROW (newdecl))
>>> -    TREE_NOTHROW (olddecl) = 1;
>>> +
>>> +      if (merge_attr)
>>> +    {
>>> +      /* Merge the type qualifiers.  */
>>> +      if (TREE_READONLY (newdecl))
>>> +        TREE_READONLY (olddecl) = 1;
>>> +    }
>>> +      else
>>> +    {
>>> +      /* Set the bits that correspond to the const function
>>> attributes.  */
>>> +      TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
>>> +    }
>>
>>
>> Let's limit the const/volatile handling here to non-functions, and
>> handle the const/noreturn attributes for functions in the later hunk
>> along with nothrow/malloc/pure.
>
>
> I had to keep the TREE_HAS_VOLATILE handling as is since it
> applies to functions too (has side-effects).  Otherwise the
> attr-nothrow-2.C test fails.

When I mentioned "noreturn" above I was referring to
TREE_HAS_VOLATILE; sorry I wasn't clear.  For functions it should be
handled along with nothrow/readonly/malloc/pure.

Jason


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]