lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi] gcc [[noreturn]] oddities [Was: master 4b0c2ee 4/6: Remove an unre


From: Greg Chicares
Subject: [lmi] gcc [[noreturn]] oddities [Was: master 4b0c2ee 4/6: Remove an unreachable statement]
Date: Fri, 10 Mar 2017 13:32:14 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.6.0

On 2017-03-03 14:31, Vadim Zeitlin wrote:
> On Tue, 28 Feb 2017 22:02:58 -0500 (EST) Greg Chicares <address@hidden> wrote:
> 
> GC> branch: master
> GC> commit 4b0c2eeb402a36b63038f604ab8fe4b37ca5be7d
> GC> Author: Gregory W. Chicares <address@hidden>
> GC> Commit: Gregory W. Chicares <address@hidden>
> GC> 
> GC>     Remove an unreachable statement
> GC>     
> GC>     fatal_error() always throws. Writing 'return' after it was just
> GC>     confusing. (Elsewhere in lmi, this usage is seen:
> GC>       throw "Unreachable--silences a compiler diagnostic.";
> GC>     but there is no diagnostic to silence here.)
[...]
>  fatal_error() should really be marked with [[noreturn]] attribute, now
> that we use C++11.

Looking into this, I observe two oddities, one of which [(1) below]
may be a real concern, while the other [(2) below] seems more comical.
Given that gcc rejects code copied and pasted from the C++11 standard
[N3337], is there a way to use "[[noreturn]]" that is acceptable both
to gcc and also to conforming compilers?

(1) Where is "[[noreturn]]" to be written for a function template?

C++11 [18.8/1] specifies:

[[noreturn]] template <class T> void throw_with_nested(T&& t);

However, copying and pasting that into an lmi file gives:

/opt/lmi/src/lmi/xml_serializable.tpp:189:14: error: expected unqualified-id 
before 'template'
 [[noreturn]] template <class T> void throw_with_nested(T&& t);
              ^

...and if I add that attribute here, in real lmi code:

+[[noreturn]]
 template<typename T>
 int xml_serializable<T>::class_version() const
 {
     throw "Unreachable--silences a compiler diagnostic.";
 }

then debian's MinGW-w64 cross gcc-4.9.1 says:

/opt/lmi/src/lmi/xml_serializable.tpp:190:1: error: expected unqualified-id 
before 'template'
 template<typename T>
 ^

Let's see what libstdc++ says:

`i686-w64-mingw32-gcc -print-prog-name=cc1plus` -v         
ignoring nonexistent directory 
"/usr/lib/gcc/i686-w64-mingw32/4.9-win32/../../../../i686-w64-mingw32/sys-include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/i686-w64-mingw32/4.9-win32/include/c++
 /usr/lib/gcc/i686-w64-mingw32/4.9-win32/include/c++/i686-w64-mingw32
 /usr/lib/gcc/i686-w64-mingw32/4.9-win32/include/c++/backward
 /usr/lib/gcc/i686-w64-mingw32/4.9-win32/include
 /usr/lib/gcc/i686-w64-mingw32/4.9-win32/include-fixed
 /usr/lib/gcc/i686-w64-mingw32/4.9-win32/../../../../i686-w64-mingw32/include
End of search list.

Searching:
  grep throw_with_nested /usr/lib/gcc/i686-w64-mingw32/4.9-win32/include/**/* 
|less -S
leads us to:
  less 
/usr/lib/gcc/i686-w64-mingw32/4.9-win32/include/c++/bits/nested_exception.h
which uses the gcc-specific "__attribute__" instead:

  template<typename _Ex>
    void
    __throw_with_nested(_Ex&&, const nested_exception* = 0)
    __attribute__ ((__noreturn__));

which doesn't necessarily tell us where to write the standard "[[noreturn]]",
and conflicts with C++11 [7/1]:

| [ Note: In the declaration for an entity, attributes appertaining to
| that entity may appear at the start of the declaration and after the
| declarator-id for that declaration.
| — end note ] [ Example:
| [[noreturn]] void f [[noreturn]] (); // OK

which does not seem to permit the libstdc++ usage:

  void f () [[noreturn]];
            ^^^^^^^^^^^^ apparently nonstandard

And gcc won't accept it at this alternative location:

template<typename T>
int xml_serializable<T>::class_version() const
[[noreturn]]
{
    throw "Unreachable--silences a compiler diagnostic.";
}

/opt/lmi/src/lmi/xml_serializable.tpp:191:12: error: attribute ignored 
[-Werror=attributes]
 [[noreturn]]
            ^
/opt/lmi/src/lmi/xml_serializable.tpp:191:12: note: an attribute that 
appertains to a type-specifier is ignored

...or here either:

template<typename T>
int xml_serializable<T>::class_version()
[[noreturn]]
const

/opt/lmi/src/lmi/xml_serializable.tpp:192:1: error: expected initializer before 
'const'

...so I guess the only options gcc allows are

template<typename T>
int xml_serializable<T>::class_version
[[noreturn]]
() const

and

template<typename T>
[[noreturn]]
int xml_serializable<T>::class_version() const

(2) The warning is not idempotent. For example:

template<typename T>
[[noreturn]]
int xml_serializable<T>::class_version() const
{
    throw "Unreachable--silences a compiler diagnostic.";
}

This is accepted, except with CXXFLAGS='-Wsuggest-attribute=noreturn',
which, oddly enough, repeats the suggestion to use [[noreturn]]:

/opt/lmi/src/lmi/xml_serializable.tpp:191:5: error: function might be candidate 
for attribute 'noreturn' [-Werror=suggest-attribute=noreturn]
 int xml_serializable<T>::class_version() const
     ^

The outcome is the same if I write "[[noreturn]]" before "()".

This seems to mean that '-Wsuggest-attribute=noreturn' cannot be
used for production--instead, it can only be used in experimental
runs to collect suggestions.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]