On Sat, 29 Jul 2017 00:34:39 -0700 Mark Millard <mar...@dsl-only.net> wrote:
> On 2017-Jul-28, at 4:59 PM, Tijl Coosemans <tijl at FreeBSD.org> wrote:
>> On Fri, 28 Jul 2017 19:54:04 +0200 Dimitry Andric <dim at FreeBSD.org> 
>> wrote:  
>>> On 28 Jul 2017, at 13:55, Tijl Coosemans <t...@freebsd.org> wrote:  
>>>> 
>>>> On Thu, 27 Jul 2017 21:42:01 +0000 pkg-fall...@freebsd.org wrote:    
>>> ...  
>>>>> In file included from squirrel/squirrel/sqvm.cc:5:
>>>>> In file included from /usr/include/c++/v1/math.h:310:
>>>>> /usr/include/c++/v1/limits:149:85: error: expected expression
>>>>>   _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR type max() _NOEXCEPT 
>>>>> {return type();}
>>>>>                                                                           
>>>>>         ^
>>>>> squirrel/squirrel/sqobject.h:131:24: note: expanded from macro 'type'
>>>>> #define type(obj) ((obj)._type)
>>>>>                      ^    
>>>> 
>>>> Simutrans code defines 'type' as a macro.  Shouldn't libc++ headers use
>>>> _type or __type or something?    
>>> 
>>> No, the member name 'type' is used in many classes in the C++ standard
>>> library, for example all the traits in <type_traits>.  Programs should
>>> not attempt to redefine this, at least not as a macro.
>>> 
>>> Note that this also doesn't work with libstdc++, e.g.:
>>> 
>>> $ cat boom.cpp
>>> #define type "nope, this will not work"
>>> #include <type_traits>
>>> 
>>> and then:
>>> 
>>> $ g++ -c boom.cpp
>>> boom.cpp:1:14: error: expected unqualified-id before string constant
>>> #define type "nope, this will not work"
>>>              ^
>>> boom.cpp:1:14: error: expected class-name before string constant
>>> #define type "nope, this will not work"
>>>              ^
>>> boom.cpp:1:14: error: expected '{' before string constant
>>> boom.cpp:1:14: error: expected class-name before string constant
>>> #define type "nope, this will not work"
>>>              ^
>>> boom.cpp:1:14: error: expected '{' before string constant
>>> boom.cpp:1:14: error: expected class-name before string constant
>>> #define type "nope, this will not work"
>>>              ^
>>> boom.cpp:1:14: error: expected '{' before string constant
>>> boom.cpp:1:14: error: expected class-name before string constant
>>> #define type "nope, this will not work"
>>>              ^
>>> boom.cpp:1:14: error: expected '{' before string constant
>>> boom.cpp:1:14: error: expected unqualified-id before string constant
>>> #define type "nope, this will not work"
>>>              ^
>>> In file included from boom.cpp:3:0:
>>> /usr/local/lib/gcc6/include/c++/type_traits:212:60: error: template 
>>> argument 1 is invalid
>>>     : public __is_void_helper<typename remove_cv<_Tp>::type>::type
>>>                                                            ^
>>> /usr/local/lib/gcc6/include/c++/type_traits:212:61: error: expected '{' 
>>> before '::' token
>>>     : public __is_void_helper<typename remove_cv<_Tp>::type>::type
>>>                                                             ^~
>>> [...and lots more errors like this...]  
>> 
>> The code does not include <type_traits> or any of that C++11 stuff.  It
>> includes <math.h>.  This works with libstdc++ because it doesn't have
>> <math.h>, but it would also work when <cmath> was included, because
>> libstdc++ uses __type everywhere (and __enable_if and __is_arithmetic,
>> etc. where libc++ headers use enable_if and is_arithmetic).  The
>> libstdc++ way makes more sense.  You cannot expect C++98 code to know
>> about reserved identifiers in C++11 or C++11 code to know about reserved
>> identifiers in later standards.  
> 
> I'll first note that Annex D D.5 C standard library
> headers says:
> 
> "the C++ standard library provides the 25 C headers,
> as shown in table 154"
> 
> and table 154 lists: <math.h> . That is relevant
> for the below.
> 
> ISO/IEC 14882:2011(E) 17.6.4.3.1 Macro Names
> says:
> 
> "A translation unit that include a standard library
> header shall not #define or #undef names declared
> in any standard library header."
> 
> I'll note that the standard has sections with titles
> like "Type names", "Class names", "Nested type names",
> "Names of template specializations", and "Predefined
> macro names". My understanding is that the earlier
> quote spans avoiding matching all such names.
> 
> 
> 
> ISO/IEC 14882:2011(E) mandates such things as:
> 
> template <bool, class T> struct is_arithmetic;
> . . .
> template <bool, class T = void> struct enable_if;
> . . .
> template <class T, T v> typedef integral_constant {
> . . .
>    typedef integral_constant<T,v> type;
> . . .
> };

But none of this should be exposed to C++98 code.  These names were not
reserved in the C++98 standard so C++98 code is free to use them.  If
libc++ cannot compile such valid C++98 code it is simply not compliant
with that standard.  Note that in this case we were lucky to see a
diagnostic.  C++98 code may use these names in a way that doesn't cause
an error.  Who's going to review our 27000 ports to make sure they are
still compiled correctly?

> For targeting -std=c++11 or later in compiles
> __enable_if and __is_arithemtic and __type
> would be wrong in these places and require
> code using the standard to use the names
> that have the __ prefixes, in violation of
> the standard's specifications. That includes
> having no explicit -std= but depending on a
> default that happens to end up with c++11 or
> later as the version to target.

Of course things like __enable_if are for internal use only.  In C++11
mode enable_if needs to be made available.
_______________________________________________
freebsd-toolchain@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"

Reply via email to