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

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

Related

Does <algorithm> include <cmath>?

The following program compiles correctly:
#include <algorithm>
int main(int argc, char *argv[]) {
return int(log(23.f));
}
(under g++ 4.9.2 with the flag -std=c++11)
The code uses the function log, which is defined on <cmath>. However, it does not include the header <cmath>, only the header <algorithm>. Why is it that g++ doesn't give any warnings, and compiles the code correctly?
According to the standard, some headers do include others. As an example, <cinttypes> includes <cstdint>. See the Includes section here. With respect to <algorithm>, there is no such statement as to which other headers it should include (see here). So, the conclusion is, <algorithm> is not required to include <cmath>, and your example code is not portable. It may fail to compile on other C++ implementations.
In the C++11 standard, [res.on.headers]/1 states that
A C++ header may include other C++ headers. A C++ header shall provide
the declarations and definitions that appear in its synopsis. A C++
header shown in its synopsis as including other C++ headers shall
provide the declarations and definitions that appear in the synopses
of those other headers.
Now consider [algorithms.general]/2:
Header <algorithm> synopsis
#include <initializer_list>
namespace std {
// ......
<cmath> isn't listed and clearly not included in <initializer_list>. Thus your program is not guaranteed to compile on a standard-conforming implementation. One should never rely on "implicit inclusion" - the general guideline is to include every header from which an entity is used.
Exceptions are e.g. <iostream> including <ostream>, which is guaranteed since C++11.
To answer your question:
Why is it that g++ doesn't give any warnings, and compiles the code correctly?
Because C++ implementations aren't required to and it's actually quite difficult to implement this warning given the way #include works. Attempts have been made, but there are problems that haven't been entirely addressed.
Moving to a different model can enable this kind of checking. However, in the interests of backwards compatibility and allowing the easiest possible transition the 'modularizations' of the standard library I've used happen to explicitly allow code that previously depended on indirect includes to continue to work.
You can see this, for example, in libc++'s module map; Those export * lines declare "any modules imported by this module are also exported." Which is to say, a module std.algorithm that imports a module std.cmath also exports, so anyone that imports std.algorithm also gets access to std.cmath.
For new code it would be very nice if these 'legacy exports' could be turned off, but for pre-existing large projects it is very nice to be able to just flip on -fmodules and have the project work with no changes.
Using clang's implementation of modules with libc++, and modifying the module map file to remove the non-portable, indirect include behavior, clang reports such errors like:
main.cpp:5:16: error: declaration of 'log' must be imported from module 'Darwin.C.math' before it is required
return int(log(23.f));
^
/usr/include/math.h:387:15: note: previous declaration is here
extern double log(double);
^
1 error generated.
libc++ <algorithm> doesn't include <cmath>, so I used <random> instead. Otherwise the source that produced the above is the same as what you show.

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

Why it seems not necessary to include some STL headers

I think some headers need to be included to compile with gcc(4.9),
#include <algorithm> // for std::transform
#include <numeric> // for std::adjacent_difference
However, I found it's not necessary include them at all, I can still call
for example, the following functions
std::adjacent_difference (V1.begin(), V1.end(), V2.begin());
std::transform(V2.begin(), V2.end(), V3.begin(), V4.begin(), std::divides<double>());
Maybe I have misunderstood the mechanism of including header files...Any hint?
It is quite typical for a header to include other headers. The headers included by header x will be included in any file that includes x. That should be trivial to understand once you grasp what including a file in another means. In this case, one of the standard headers happened to be included in another.
Files included by headers can change between versions. If you don't include a required header, your program may break under another (version of) standard library even though it may appear to work in the current implementation. Of course, this applies to other libraries as well.
The C++ standard says the following in section 17.6.5.2 [res.on.headers]:
A C++ header may include other C++ headers.
For your question, this means a compiler can just act as if you included other C++ headers. In your example, the compiler is allowed to include the <numeric> header if you include <algorithm>, or vice versa.
But that's not the whole story. The standard also says:
A C++ header shown in its synopsis as including other C++ headers
shall provide the declarations and definitions that appear in the
synopses of those other headers.
And:
The C standard headers [...] shall include only their corresponding
C++ standard header [...]
(Note that I am quoting from the last free C++11 draft. The final version of the ISO standard is not free. See https://isocpp.org/std/the-standard.)
The <utility> header is an example of a C++ header which is guaranteed to include another. Its synopsis explitly includes <initializer_list>. Which means a conforming compiler must accept the following:
#include <utility>
// #include <initializer_list> // not needed
int main()
{
std::initializer_list<int> x = {};
}
For the C headers, in contrast, this means that the following must not compile:
#include <stdio.h>
int main()
{
std::cout << "\n"; // must not compile
}
What the standard says is surely confirmed by your implementation's documentation. For example, the documentation for Visual C++ 2013 says:
A C++ library header includes any other C++ library headers it needs
to define needed types. (Always include explicitly any C++ library
headers needed in a translation unit, however, lest you guess wrong
about its actual dependencies.) A Standard C header never includes
another standard header.
The advice given here is a good one; do not depend on automatic inclusion. Explicitly include everything you need.

Warnings when including C header file with C++ compiler

I have some header file that was written for use in a C99 program. This header includes all the function definitions, and is not paired with a source file. I am including it in a C++ file.
My C++ compiler flags include -pedantic -std=c++11, which gives me various warnings in the header file such as "ISO C++ forbids compound literals", and "ISO C++ forbids variable length arrays". Obviously the C++ compiler is treating the C99 code as C++. Two questions:
Is this a potential problem when trying to write code that will run correctly on various platforms using different compilers?
What is a good way to resolve the warnings, and produce standard conforming code? I was thinking of making a precompiled header file using gcc, but don't know enough about the process to be assured that I am not going to have unintended consequences from included a C precompiled header in a C++ source.
Thanks
Is this a potential problem when trying to write code that will run correctly on various platforms using different compilers?
Yes. GCC may just give a warning, other compilers (e.g. Visual Studio, or GCC with other options) could very well give an error.
What is a good way to resolve the warnings, and produce standard conforming code?
The correct way to resolve the problems is to write the header in the common subset of C and C++. Functions and object-definitions that use C99 features (such as variable-length arrays and compound literals) should be moved to a separate C source file (that gets compiled with a C compiler!).
To include a pure C header file(*) in a C++ project, you should wrap the include statement in an extern "C" block:
// C++
extern "C" {
// C-code goes here
#include "foo.h"
}
This is because C++ performs name mangling on all function names to make overloading work. C doesn't use name mangling, so C++ parses C function signatures with name mangling.
Please note that extern "C" doesn't put the compiler into "C-mode" (there is no such mode but you might falsely think of this instruction as such), it doesn't mangle the function names (+ changes the calling convention and forbids overloading; thanks for doomster for pointing these things out).
However, it shouldn't be a problem if you are including a header only (with inline implementations), since this name mangling will only be a problem when you link the C source file or library against your C++ project, since the function names are different in this case.
This being said, you should use the common subset of C and C++ for the header file, extract and compile the implementations of these functions separately with a C compiler, not C++. Then, you (hopefully) can link both parts together. A lot of C libraries already have headers which are compatible with C++, so this is a common procedure.
(*): Some header files are already made to be compatible with both languages C and C++ by using the common subset of language features plus wrapping everything in a conditional extern "C" block. For such headers, you should not use this method, but only for the ones which don't have such a block in it.

How to detect if errno_t is defined?

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