[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.