https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81721
Bug ID: 81721
Summary: precompiled header : internal compiler error:
Segmentation fault
Product: gcc
Version: 7.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: juro.bystricky at intel dot com
Target Milestone: ---
Created attachment 41930
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=41930=edit
symacros.h to corroborate the bug report
Given two simple files "precompiled.h" and "main.cpp" :
$ cat precompiled.h
#ifndef PRECOMPILED_H
#define PRECOMPILED_H
#include
#endif // PRECOMPILED_H
$ cat main.cpp
#include "precompiled.h"
class Version {
public:
void major() {}
};
int main(void){ return 0;}
The following sequence will generate a segmentation fault:
$ g++ -x c++-header precompiled.h
$ g++ -H main.cpp
main.cpp:5:2: internal compiler error: Segmentation fault
void major() {}
^~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://gcc.gnu.org/bugs/> for instructions.
In order to reproduce this, you also need to have /usr/include/sys/sysmacros.h
containing (file attached):
/* Caution: The text of this deprecation message is unquoted, so that
#symbol can be substituted. (It is converted to a string by
__SYSMACROS_DM1.) This means the message must be a sequence of
complete pp-tokens; in particular, English contractions (it's,
can't) cannot be used.
The message has been manually word-wrapped to fit in 80 columns
when output by GCC 5 and 6. The first line is shorter to leave
some room for the "foo.c:23: warning:" annotation. */
#define __SYSMACROS_DM(symbol) __SYSMACROS_DM1 \
(In the GNU C Library, #symbol is defined\n\
by . For historical compatibility, it is\n\
currently defined by as well, but we plan to\n\
remove this soon. To use #symbol, include \n\
directly. If you did not intend to use a system-defined macro\n\
#symbol, you should undefine it after including .)
After some debugging, I found the segmentation fault was caused in libcpp/lex.c
(cpp_spell_token):
case SPELL_IDENT:
if (forstring)
{
memcpy (buffer, NODE_NAME (token->val.node.spelling),
NODE_LEN (token->val.node.spelling));
buffer += NODE_LEN (token->val.node.spelling);
}
In particular, the code barfs on NODE_NAME (token->val.node.spelling), because
the code implicitly assumes token->type == CPP_NAME.
However, the routine actually gets CPP_NOT (which we got from parsing
sysmacros.h "If you did not intend" sentence).
A ***very*** crude fix/POC is to do something like this in libcpp/lex.c:
case SPELL_IDENT:
if (forstring)
{
if (token->type == CPP_NAME)
{
memcpy (buffer, NODE_NAME (token->val.node.spelling),
NODE_LEN (token->val.node.spelling));
buffer += NODE_LEN (token->val.node.spelling);
}
if (token->type == CPP_NOT)
{
memcpy(buffer, "not", 3);
buffer += 3;
break;
}
}
There is, of course, a more generic way to handle this for other token->types,
not just CPP_NOT, providing that token->types other than CPP_NAME are legal in
this routine/context and this is where the fix should be applied.
BTW, there are two workarounds for this error, either pre-compile the headers
with -save-temps:
$ g++ -save-temps -x c++-header precompiled.h
$ g++ -H main.cpp
Or explicitly include #include before #include "precompiled.h"
We may get this instead:
main.cpp:5:13: warning: In the GNU C Library, "major" is defined
by . For historical compatibility, it is
currently defined by as well, but we plan to
remove this soon. To use "major", include
directly. If you did not intend to use a system-defined macro
"major", you should undefine it after including .
void major() {}
^~~~
(For more details please see
https://bugzilla.yoctoproject.org/show_bug.cgi?id=11738 )