How to detect if errno_t is defined? - c++

I'm compiling code using gcc that comes from Visual C++ 2008. The code is using errno_t, but in some versions of gcc headers including <errno.h> doesn't define the type. How do I detect if the type is defined? Is there a define that signals that the type was defined? In the case it isn't defined I'd like to provide the typedef to let the code compile correctly on all platforms.

Microsoft's errno_t is redundant. errno is defined by the ISO C standard to be a modifiable lvalue of type int. If your code needs to store errno values, then you should put them into an int.
Do a global search and replace s/errno_t/int/ and you're done.
Edit: Also, you shouldn't be providing a typedef int errno_t in your code, because all names that end with _t are reserved.

You can't check for a typedef the way you can for a macro, so this is a bit on the tricky side. If you're using autoconf, this patch shows the minimum changes that you need to have autoconf check for the presence of errno_t and define it if it's missing (the typedef would be placed in a file that includes your generated config.h and is included by all files that need errno_t). If you're not using autoconf you need to come up with some way to do the same thing within your build system, or a very clever set of tests against compiler version macros.

This is typically the case where GNU autoconf comes to the rescue. Basically autoconf will generate a configure script that can detect various system-dependent features such as whether this type exists and how it is defined. You then include the generated C header file within your application.

If you know which versions of GCC are giving you trouble, you can test for them. You can check for versions of GCC using something like:
#if __GNUC__ == 3
...
#else
...
#endif

Related

Pycparser not working on preprocessed code

I need to use pycparser on preprocessed C code (the results produced by 'gcc -E'). However I am currently running into issue that I can't understand or solve.
I am using the provided samples year2.c and func_defs.py, which i modified to use a variety of preprocessors and fake libraries to no avail. Maybe some of you can look into this and see if you can reproduce/solve the issue. I will append all necessary code.
The errors were generated using year2.c (regular sample file) and year2.i ('gcc -E' output). There was no useable result for the latter while the former worked with both preprocessor/fakelib variants.
I have created a bitbucket repo with all relevant errors, the script used (albeit only its last variation) and the year2.c and year2.i files.
Error & Sample Repo
Thanks for your time.
The error you're getting is:
pycparser.plyparser.ParseError: /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h:40:27: before: __gnuc_va_list
The line indicated as causing the error (stdarg.h:40):
typedef __builtin_va_list __gnuc_va_list;
In gcc, __builtin_va_list is, as its name indicates, built in to the compiler. Consequently, no declaration of that type is necessary (or allowed).
It's pretty common for C compilers to use a symbol-table-based technique to parse typenames, since there are a number of ambiguities in the grammar if you cannot distinguish a typename from another identifier. Such a parser will assume that an undeclared identifier is not a typename, and if __builtin_va_list is not a typename, that typedef is a syntax error.
So I suppose that the pyparser grammar you're using doesn't know about gcc builtin types (and why should it?).
Your fakelib seems to be including the same header file. That's not surprising since it is hard to fake stdarg.h; although technically a library header, it is part of the small set of headers which must be provided by the compiler even in a freestanding (no standard library) implementation: <float.h>, <iso646.h>, <limits.h>, <stdalign.h>,
<stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and
<stdnoreturn.h> (C11 standard, clause 4, paragraph 6). These must be implemented by the compiler because there is no way an external library can know enough about the nature of the compiled code to properly define them.
Depending on what you require from the pyparsed output, you may be able to workaround this for pyparser by including a definition of __builtin_va_list, such as:
typedef struct __builtin_va_list { } __builtin_va_list;
__builtin_va_list is not the only builtin gcc datatype, although you may not run into the other ones. So you might have to iterate this solution a few times until you achieve whatever it is you are trying to achieve.
As #rici has explained the cause of the error. I'd focus more on how to solve it. I've taken my answer from pycparser author's blog -
http://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers
The idea is that pycparser needs to know what anyheader.h contains so it can properly parse the code. As actually parsing anyheader.h and all the other headers it transitively includes, could be very time consuming and perhaps not required for your task, fakeheaders can be used. A fake anyheader.h will only contain the parts of the original that are necessary for parsing - the #defines and the typedefs.
gcc -nostdinc -E -I/home/rg/pycparser-master/utils/fake_libc_include test.c > testPP.c
The above command preprocess test.c which contains <stdio.h> using fake headers provided with pycparser package. -nostdinc flag is used to block some pre-set system header directories that gcc automatically includes. Now, parsing the preprocessed file, using e.g. below code
import pycparser
pycparser.parse_file('testPP.c')
should work in the most of the cases. If it doesn't make sure you provide all the dependencies for preprocessing.
In case, for some headers fakes are not provided, you can fake error causing typedef using #defining e.g. to resolve an error caused by __builtin_va_list, you can try faking it as follows:
gcc -nostdinc -E -D'__builtin_va_list(x)=' -I/home/rg/pycparser-master/utils/fake_libc_include test.c > testPP.c

How to enable _USE_UNIX98 (Gcc/C++ v2.96)

I've a C++ application that works in actual compilers (I compile it with eclipse).
Now, I need compile it on a very old compiler version (gcc/c++ v2.96) on a Redhat 7.3 with Kdevelop.
When I compile the app it gives the following error: swprintf undeclared.
wchar.h header it's included, but I saw this file in the RH7.3 OS and only declare this function if __USE_UNIX98 __USE_ISOC99 are declared.
How can I enable __USE_UNIX98?
GNU libc defines the features that should be enabled in all of its headers using a special system header <features.h>. If you define the appropriate macros, <features.h> will define __USE_UNIX98 for you.
The typical way to get all functions, regardless of what standard (if any) covers them, is by adding -D_GNU_SOURCE on the command-line. Getting only the functions covered by a specific standard requires defining the macro as specified in that standard using the value specified in that standard, such as -D_POSIX_C_SOURCE=200112L. The precise values that are supported on your particular implementation are probably easiest found by inspecting /usr/include/features.h manually.
From inspection of <features.h> defining _XOPEN_SOURCE to 500 or greater will cause __USE_UNIX98 to be defined

How to deal with: redeclaration of C++ built-in type ‘char16_t’

In a C++11 project I have to use external C library. This library main header file defines
typedef uint16_t char16_t;
And because of it compilation of the C++ program which includes this library fails, with the message:
redeclaration of C++ built-in type ‘char16_t’
The only idea I have is to repackage whole library but because char16_t is pervasive in this library it would be very time consuming (if even possible). Are there some sensible ways of dealing with this problem?
Edit:
I have also another idea of removing problematic line and replacing every occurrence of char16_t with uint16_t but I would have to modify third party library headers and I do not particularly like this idea (there can be more similar errors). So I also wonder whether there is some good way of dealing of broader problem of incompatibilities between C++ and C when including headers.
You could use a macro to rename the library type while keeping it unrelated to the new language type char16_t:
#define char16_t LIBRARY_char16_t
#include <library>
#undef char16_t
Then, the library header will be compiled in your code base such that the typedef has the name LIBRARY_char16_t.
The library itself is still compiled such that the type in question is typedef'ed to uint16_t so you should not attempt to change this (by e.g. removing the typedef) in order to stay binary-compatible with the compiled library.
C++11 defines char32_t and char16_t as built in types. This error only happens if you are using C++11. i.e. in your Application.mk file you have:
APP_CPPFLAGS += -std=c++11
You can either remove the C++11 support, OR use the following workaround, that should probably be a part of the official Android source (if not already).
in file /frameworks/native/include/utils/Unicode.h
#if __cplusplus <= 199711L
typedef uint32_t char32_t;
typedef uint16_t char16_t;
#endif
It is based on answers from a question about char16/32_t with C++11

Shared Object Mismatch due to Preprocessor directive

I am building a Shared Object Project in ' IBM Rational Rhapsody 7.5 ' with qcc which in turn uses gcc .
A binary mismatch is observerd when the same code is built on two different machines having the exactly same build environment.
After some trial and error methods I observed that the mismatch is due to the pre-processsor directive used for conditional execution of code (Using #ifdef).When the pre-processor directive is removed and the project is built on different machines.The two binaries match exactly.
Is there is any reason for 'Why this mismatch occurs ?.
Is Pre-Processor directive adding machine dependent parameters in object file and so they are reflected in Executable, giving the mismatch ?
Please guide me.
The preprocessor directive #ifdef does conditional compilation. Whether or not this leads to binary incompatibility depends on what's between #ifdef and the corresponding #endif. For example, the following would obviously not have any effect at all:
#ifdef FOO
#endif
No matter whether FOO is defined, the compiled code looks exactly the same.
However the following will certainly cause an incompatibility:
#ifdef HAS_FOO_STRUCT
typedef foo foo_type;
#else
struct foo_type {};
#endif
void bar(foo_type);
Here, if HAS_FOO_STRUCT is defined, bar(foo_type) is actually bar(foo) and will be mangled as such. On the other hand, if HAS_FOO_STRUCT is not defined, foo_type is really a type of this name, thus bar(foo_type) will have that name mangled in. This there will be binary incompatibility.
Note that differences in defined macros can come from several different places. First, different compiler versions may define different macros (or define macros to different values). For example, there are macros identifying the type of system you are compiling on, and identifying the compiler version. Differences in macros can also come from system header files, which may have different #defines. Moreover, the build system may define macros indicating whether certain things (e.g. pre-installed libraries) were found or not found on the system.
Note that the binary incompatibility you see may well be intentional, in order to prevent running into a more subtle binary incompatibility which doesn't show up in compiling, but causes strange bugs under certain conditions.

Strange Eclipse C++ #define behaviour

(A case of over relying on an IDE)
I have some legacy C code that I compile as C++ for the purpose of Unit testing. The C source is C++ aware in that it conditionally defines based on environment.
E.g. (PRIVATE resolves to static):
#if!defined __cplusplus
#define PRIVATE1 PRIVATE
#endif
...
PRIVATE1 const int some_var;
The problem is I just can't seem to find out what PRIVATE1 resolves to or is in C++, the compiler complains of redefinition if I add a declaration but doesn't indicate where?
I have searched my MinGW/gcc include path, the C++ ISO specification and the C++ books available to me has been to no avail.
Edit:
Sure I checked the command line and makefiles before posting.
There's nothing like this in ISO C++ spec. Most likely, PRIVATE1 (as well as PRIVATE) are defined elsewhere in the project. Note that this doesn't need to be a #define in an .h file - it can also be defined via compiler switches in the makefile. I'd suggest doing a full grep on the project directory.
If PRIVATE1 resolves to PRIVATE, and PRIVATE resolves to static, then PRIVATE1 resolves to static.
It's unlikely (but not impossible) that they are defined by MinGW itself. Macros defined by the C++ or C implementation should begin with an underscore.
Eclipse C++ managed project's are a little, well stupid!
If a project is declared C++ it still bases it's build on file extension, hence .h file preprocessed as C and not C++ header which pulls in a #define PRIVATE1 from another header file similarly wrapped by:
#ifdef __cpluplus.
The project is then linked by g++.
Your best bet is to look at the preprocessor output. You didn't post what compiler you are using, but if you check the docs, most have an option to "Preprocess to file" which will create a file with all the macros substituted. This might be able to help you figure out what is happening. In Visual Studio you use the /E option (under C/C++->Preprocessor->Generate Preprocessed File) which will turn foo.c into foo.i. This file will generally be HUGE compared to the original source file, so scroll down to the bottom to see your code.
Most likely in C++ it's defined to, well, "private:".
Can you declare a function with PRIVATE1? If so, just write a function like so:
PRIVATE1 void Foo() {
// __FUNCSIG__ in Visual Studio, not sure about GCC
std::cout << __FUNCSIG__ << std::endl;
}