On Sat, 29 Jul 2017 12:43:59 -0700 Mark Millard <mar...@dsl-only.net> wrote:
> On 2017-Jul-29, at 12:27 PM, Tijl Coosemans <tijl at FreeBSD.org> wrote:
>> On Sat, 29 Jul 2017 00:34:39 -0700 Mark Millard <markmi at 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 <tijl at freebsd.org> wrote:    
>>>>>> 
>>>>>> On Thu, 27 Jul 2017 21:42:01 +0000 pkg-fallout at 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.  
> 
> Only if the compiler is told to compile the code as
> C++98 code or it is known that C++98 is the default
> target version for the compiler.
> 
> The compiler command that you published as part of
> the error report provides no such explicit control
> of what language/library version rules are to be
> used:
> 
> c++ -O2 -pipe -fstack-protector -fno-strict-aliasing  -O2 -pipe  
> -fstack-protector -fno-strict-aliasing  -DNDEBUG -Wall -W -Wcast-qual 
> -Wpointer-arith -Wcast-align -DUSE_C -DREVISION=8163 -I/usr/local/include/SDL 
> -I/usr/local/include -D_REENTRANT -D_THREAD_SAFE -DCOLOUR_DEPTH=16 -c -MMD -o 
> build/default/squirrel/squirrel/sqvm.o squirrel/squirrel/sqvm.cc
> 
> So if the default is to compile for C++11 or later
> the results of using the C++11 rules are the expected
> results here.
> 
>> 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?  
> 
> Unless you tell the compiler to use C++98 rules you get the
> rules of whatever version it targets by default.
> 
>>> 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.  
> 
> And if the compiler default version target was
> C++11 or later then what it did was what it should
> have done.

Since you've written three times the same thing here let me reply with
three times the same thing:

- Adding -std=c++98 still fails to compile with the same errors.

- The compiler default is C++98:
% c++ -x c++ -E -dM /dev/null | grep __cplusplus
#define __cplusplus 199711L

- A quick look at the libc++ headers makes it immediately obvious they
  expose and use C++11 features in C++98 mode.

And of course these were the very first things I checked before writing
my first email.
_______________________________________________
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