Jump to content
  • Advertisement
Sign in to follow this  
Finalspace

C++ Win32 Clang c++98 vs c++11

Recommended Posts

I am having trouble getting clang into a C++/98 mode, can someone help me with that?

 

1.) No uint32_t in c++/98

// Are this the correct includes for uint32_t and size_t ?
#include <stdint.h> // uint64_t, uint32_t, uint8_t, int16_t, etc.
#include <stdlib.h> // size_t
#include <limits.h> // UINT32_MAX

/*
..\final_platform_layer.hpp:1646:11: error: unknown type name 'uint32_t'; did you mean 'int32_t'?
                fpl_api uint32_t ReadFileBlock32(const FileHandle &fileHandle, const uint32_t sizeToRead, void *targetBuffer, const uint32_t maxTargetBufferSize);
*/


2.) Macro is expanded always - even though __cplusplus should not be greater than 199711...

 

#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900)
	//! Null pointer (nullptr)
#	define fpl_null nullptr
	//! Constant (constexpr)
#	define fpl_constant constexpr
#else
	//! Null pointer (0)
#	define fpl_null 0
	//! Constant (static const)
#	define fpl_constant static const
#endif
  
/*
In file included from FPL_Console\main.cpp:13:
..\final_platform_layer.hpp:1623:4: error: unknown type name 'constexpr'
                        fpl_constant uint32_t MAX_FILEENTRY_PATH_LENGTH = 1024;
*/

 

I am compiling like this (Win32): 

set BUILD_DIR=bin\FPL_Console\x64-Debug
set IGNORED_WARNINGS=-Wno-missing-field-initializers -Wno-sign-conversion -Wno-cast-qual -Wno-unused-parameter -Wno-format-nonliteral -Wno-old-style-cast -Wno-header-hygiene
rmdir /s /q %BUILD_DIR%
mkdir %BUILD_DIR%
clang -g -Weverything %IGNORED_WARNINGS% -DFPL_DEBUG -std=c++98 -O0 -I..\ -lkernel32.lib -o%BUILD_DIR%\FPL_Console.exe FPL_Console\main.cpp > error.txt 2>&1

 

Edited by Finalspace

Share this post


Link to post
Share on other sites
Advertisement
2 hours ago, Finalspace said:

1.) No uint32_t in c++/98

The standard int-types in stdint.h are an C++11 feature. If you want to use them for C++98, you have to define them yourself.

2 hours ago, Finalspace said:

2.) Macro is expanded always - even though __cplusplus should not be greater than 199711...

What is the value of __cplusplus? You should be able to view/output it to see whats going wrong. Even so, it seems that clang rather uses a check for each indivdual feature instead (https://stackoverflow.com/questions/7139323/what-macro-does-clang-define-to-announce-c11-mode-if-any).

Share this post


Link to post
Share on other sites

<stdint.h> is a C99 header.  I don't know what vendor's C standard library you;re using, but if it's the native Microsoft Windows one it doesn't support C99 yet.

Clang uses a non-conformant method of indicating support for various features instead of the standards-sanctioned ways, which means you're going to need to use libc++ for the standard library because other vendor's standard C++ libraries are conformant.  There was some discussion in the standards committee about whether to do something like clang does, but it was rejected outright as non-scalable.

Is there any reason you can't just switch from an ancient primordial version of the language to an old out-of-date one?  The differences between C++98 and C++11 are subtle and obscure for he most part, if you avoid the newer features (and do you really care that std::list::length() is guaranteed O(1) instead of having its complexity order implementation-defined?) You should be able to just compile C++98 code in C++11 mode without problem.

Share this post


Link to post
Share on other sites
16 hours ago, Bregma said:

<stdint.h> is a C99 header.  I don't know what vendor's C standard library you;re using, but if it's the native Microsoft Windows one it doesn't support C99 yet.

Clang uses a non-conformant method of indicating support for various features instead of the standards-sanctioned ways, which means you're going to need to use libc++ for the standard library because other vendor's standard C++ libraries are conformant.  There was some discussion in the standards committee about whether to do something like clang does, but it was rejected outright as non-scalable.

Is there any reason you can't just switch from an ancient primordial version of the language to an old out-of-date one?  The differences between C++98 and C++11 are subtle and obscure for he most part, if you avoid the newer features (and do you really care that std::list::length() is guaranteed O(1) instead of having its complexity order implementation-defined?) You should be able to just compile C++98 code in C++11 mode without problem.

Well i have written a platform abstraction library and i want this to be as portable as possible, so its based on C++/98 - but i want to optionally want to support C++/11 features like constexpr, nullptr and the standard types.

So the only thing i want right know is to reliably detect if i am compiling with C++/11 or not - on common platforms (Win32, Linux, Unix) and compilers (MSVC, G++, CLANG, Intel, MingW).

But thanks for that infos!

Edited by Finalspace

Share this post


Link to post
Share on other sites

Seems like this is the way to go:

//
// C++ feature detection
//
#if (__cplusplus >= 201103L) || (defined(FPL_COMPILER_MSVC) && _MSC_VER >= 1900)
#	define FPL_CPP_2011
#endif

#if !defined(cxx_constexpr)
#	define cxx_constexpr 2235
#endif
#if !defined(cxx_nullptr)
#	define cxx_nullptr 2431
#endif

#if !defined(__has_feature)
#	if defined(FPL_CPP_2011)
#		define __has_feature(x) (((x == cxx_constexpr) || (x == cxx_nullptr)) ? 1 : 0)
#	else
#		define __has_feature(x) 0
#	endif
#endif

#define FPL_CPP_CONSTEXPR __has_feature(cxx_constexpr)
#define FPL_CPP_NULLPTR __has_feature(cxx_nullptr)

 

Edited by Finalspace

Share this post


Link to post
Share on other sites
4 hours ago, Finalspace said:

So the only thing i want right know is to reliably detect if i am compiling with C++/11 or not - on common platforms (Win32, Linux, Unix) and compilers (MSVC, G++, CLANG, Intel, MingW).

 

You need to go even deeper.  You need every single practical combination of OS, compiler, standard library, and possibly thread model and exception model.  If you're using clang on a Linux OS, for example, are you using libstdc++, libc++, or one of the more obscure third-party libraries?  If you're using mingw on a Linux OS to cross-compile for Win32 to run on Win64, do you choose the posix thread model or the win32 thread model?  It's a crazy crazy world out there and I can tell you from experience there are bizarre toolchain combinations that will never work 100% despite your manager a technical expert insisting they're the way things have to be done.

If you really want to make your stuff portable across platforms, look at how boost does it.  It's OK to leverage the work of others, and best of luck to you it can be a fun challenge.

Share this post


Link to post
Share on other sites
4 hours ago, Bregma said:

You need to go even deeper.  You need every single practical combination of OS, compiler, standard library, and possibly thread model and exception model.  If you're using clang on a Linux OS, for example, are you using libstdc++, libc++, or one of the more obscure third-party libraries?  If you're using mingw on a Linux OS to cross-compile for Win32 to run on Win64, do you choose the posix thread model or the win32 thread model?  It's a crazy crazy world out there and I can tell you from experience there are bizarre toolchain combinations that will never work 100% despite your manager a technical expert insisting they're the way things have to be done.

If you really want to make your stuff portable across platforms, look at how boost does it.  It's OK to leverage the work of others, and best of luck to you it can be a fun challenge.

I dont intent to use any libraries whatsoever in the library itself - except for very raw operating system libraries, like kernel32.dll in win32 and libld.so in linux. Also if possible i would eliminate the need of the c++ runtime as well. Therefore thirdparty libraries are out of question!

But i know that you cannot get it work on every platform/architecture - i just want to work it for common combinations like MSVC/Win32 or Clang/Win32 or Clang/Posix or G++/Posix in x86 and x86_64.

Edited by Finalspace

Share this post


Link to post
Share on other sites
Posted (edited)

I still cannot get it to compile with clang, even after i cleaned up all c++/98 incompatible stuff and now get the following error:

In file included from FPL_Console\main.cpp:13:
In file included from ..\final_platform_layer.hpp:2966:
In file included from C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\um\Windows.h:168:
In file included from C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\shared\windef.h:24:
In file included from C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\shared\minwindef.h:182:
C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\um\winnt.h:11483:1: error: unknown type name 'constexpr'
DEFINE_ENUM_FLAG_OPERATORS(JOB_OBJECT_NET_RATE_CONTROL_FLAGS)

C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\um\winnt.h:11483:1: error: expected ';' after top level declarator
C:\Program Files (x86)\Windows Kits\10\include\10.0.14393.0\um\winnt.h:2288:38: note: expanded from macro 'DEFINE_ENUM_FLAG_OPERATORS'
inline _ENUM_FLAG_CONSTEXPR ENUMTYPE operator | (ENUMTYPE a, ENUMTYPE b) throw() { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) | ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \

The line 2966 in my library is just the include of the windows.h -.-

I have no idea why clang in combination with the windows header wants to use constexpr...

 

Here are the clang input:

clang -g -Weverything %IGNORED_WARNINGS% -DFPL_DEBUG -std=c++98 -O0 -I..\ -lkernel32.lib -o%BUILD_DIR%\FPL_Console.exe FPL_Console\main.cpp > error.txt 2>&1

 

If you want to try it yourself:

- Clone https://github.com/f1nalspace/final_game_tech

- Go into demos folder

- Call "clang_x64_debug.bat"

- Look into the errors.txt

 

Does LLVM/clang not support c++/98?

Edited by Finalspace

Share this post


Link to post
Share on other sites
1 hour ago, Finalspace said:

The line 2966 in my library is just the include of the windows.h -.-

I have no idea why clang in combination with the windows header wants to use constexpr...

Inspect windows.h and try to see why it tries to use constexpr.

You will probably need to define some macros that you'll discover while inspecting windows.h

 

Also:

></pre>
<table>				typedef unsigned char fpl_u8;					</table>
<table>				typedef unsigned short fpl_u16;					</table>
<table>				typedef unsigned int fpl_u32;					</table>
<table>				typedef unsigned long long fpl_u64;					</table>
<table>				typedef signed char fpl_s8;					</table>
<table>				typedef signed short fpl_s16;					</table>
<table>				typedef signed int fpl_s32;					</table>
<p>	typedef signed long long fpl_s64;</p><p>

 

This is not guaranteed to be what you think about them. Most of the time, yes, but sometimes no. You'll have to rely on other things (compiler pre-defined macros, standard headers max values for each types...).

Share this post


Link to post
Share on other sites
Posted (edited)
9 hours ago, _Silence_ said:

Inspect windows.h and try to see why it tries to use constexpr.

You will probably need to define some macros that you'll discover while inspecting windows.h

Good idea, i will look into that. No idea why i didnt thought this solution myself...

9 hours ago, _Silence_ said:

Also:

 


></pre>
<table>				typedef unsigned char fpl_u8;					</table>
<table>				typedef unsigned short fpl_u16;					</table>
<table>				typedef unsigned int fpl_u32;					</table>
<table>				typedef unsigned long long fpl_u64;					</table>
<table>				typedef signed char fpl_s8;					</table>
<table>				typedef signed short fpl_s16;					</table>
<table>				typedef signed int fpl_s32;					</table>
<p>	typedef signed long long fpl_s64;</p><p>

This is not guaranteed to be what you think about them. Most of the time, yes, but sometimes no. You'll have to rely on other things (compiler pre-defined macros, standard headers max values for each types...).

I know, but there are no "default" types in C++/98, so i have no choice to define them myself.

But really the only problem i see are unsigned int64 aka long long and the dilemma about long vs int. Maybe short can be defined in a weird way, but i wouldn´t expect that "int" is less than 32-bit or "char" more than 8-bit. Unfortunatly i dont have platforms which are defined other than that and right know, i support x86 and x86_64. But i will ask a friend which works all day on dozens of different platforms.

Edited by Finalspace

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!