Commit 394f1ae8 authored by Carlos Ramos Carreño's avatar Carlos Ramos Carreño

Fix wrong substitution in GCC's fixincludes.

Old GCC versions wrongly patched `__has_include` directives in system
includes (using fixincludes).
This was reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91085,
and patches to fix this behavior are given in
https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=6bf383c37e6131a8e247e8a0997d55d65c830b6d
and are applied upstream in versions above 12.1.
This commit applies these patches to older GCC versions.

This bug in GCC's fixincludes manifest itself with several seemingly
unrelated symptoms.
In particular, there are two conflicting "mount.h" includes, one coming
from Linux and other from Glibc.
Newer Glibc included some preprocessor tricks to detect if the Linux
header has been previously included and prevent incompatibilities by not
redefining common symbols, thus allowing its header to be included
*after* the Linux header.
In case that the header is included *before* the Linux header, it uses
the aforementioned `__has_include` directive to detect and include the
Linux header before itself if present, thus preventing its inclusion
afterwards.
However, due to the `fixincludes` wrong substitution, the check was
always false, and thus including the Glibc header before the Linux one
caused the compilation to fail, with an error similar to:

```C
In file included from ./include/mount-api-utils.h:11,
                 from libmount/src/optlist.c:19:
/usr/include/linux/mount.h:95:6: error: redeclaration of 'enum fsconfig_command'
   95 | enum fsconfig_command {
      |      ^~~~~~~~~~~~~~~~
In file included from libmount/src/libmount.h:40,
                 from libmount/src/mountP.h:31,
                 from libmount/src/optlist.c:18:
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:249:6: note: originally defined here
  249 | enum fsconfig_command
      |      ^~~~~~~~~~~~~~~~
/usr/include/linux/mount.h:96:2: error: redeclaration of enumerator 'FSCONFIG_SET_FLAG'
   96 |  FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */
      |  ^~~~~~~~~~~~~~~~~
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:251:3: note: previous definition of 'FSCONFIG_SET_FLAG' was here
  251 |   FSCONFIG_SET_FLAG       = 0,    /* Set parameter, supplying no value */
      |   ^~~~~~~~~~~~~~~~~
/usr/include/linux/mount.h:97:2: error: redeclaration of enumerator 'FSCONFIG_SET_STRING'
   97 |  FSCONFIG_SET_STRING = 1, /* Set parameter, supplying a string value */
      |  ^~~~~~~~~~~~~~~~~~~
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:253:3: note: previous definition of 'FSCONFIG_SET_STRING' was here
  253 |   FSCONFIG_SET_STRING     = 1,    /* Set parameter, supplying a string value */
      |   ^~~~~~~~~~~~~~~~~~~
/usr/include/linux/mount.h:98:2: error: redeclaration of enumerator 'FSCONFIG_SET_BINARY'
   98 |  FSCONFIG_SET_BINARY = 2, /* Set parameter, supplying a binary blob value */
      |  ^~~~~~~~~~~~~~~~~~~
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:255:3: note: previous definition of 'FSCONFIG_SET_BINARY' was here
  255 |   FSCONFIG_SET_BINARY     = 2,    /* Set parameter, supplying a binary blob value */
      |   ^~~~~~~~~~~~~~~~~~~
/usr/include/linux/mount.h:99:2: error: redeclaration of enumerator 'FSCONFIG_SET_PATH'
   99 |  FSCONFIG_SET_PATH = 3, /* Set parameter, supplying an object by path */
      |  ^~~~~~~~~~~~~~~~~
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:257:3: note: previous definition of 'FSCONFIG_SET_PATH' was here
  257 |   FSCONFIG_SET_PATH       = 3,    /* Set parameter, supplying an object by path */
      |   ^~~~~~~~~~~~~~~~~
/usr/include/linux/mount.h:100:2: error: redeclaration of enumerator 'FSCONFIG_SET_PATH_EMPTY'
  100 |  FSCONFIG_SET_PATH_EMPTY = 4, /* Set parameter, supplying an object by (empty) path */
      |  ^~~~~~~~~~~~~~~~~~~~~~~
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:259:3: note: previous definition of 'FSCONFIG_SET_PATH_EMPTY' was here
  259 |   FSCONFIG_SET_PATH_EMPTY = 4,    /* Set parameter, supplying an object by (empty) path */
      |   ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/linux/mount.h:101:2: error: redeclaration of enumerator 'FSCONFIG_SET_FD'
  101 |  FSCONFIG_SET_FD  = 5, /* Set parameter, supplying an object by fd */
      |  ^~~~~~~~~~~~~~~
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:261:3: note: previous definition of 'FSCONFIG_SET_FD' was here
  261 |   FSCONFIG_SET_FD         = 5,    /* Set parameter, supplying an object by fd */
      |   ^~~~~~~~~~~~~~~
/usr/include/linux/mount.h:102:2: error: redeclaration of enumerator 'FSCONFIG_CMD_CREATE'
  102 |  FSCONFIG_CMD_CREATE = 6, /* Invoke superblock creation */
      |  ^~~~~~~~~~~~~~~~~~~
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:263:3: note: previous definition of 'FSCONFIG_CMD_CREATE' was here
  263 |   FSCONFIG_CMD_CREATE     = 6,    /* Invoke superblock creation */
      |   ^~~~~~~~~~~~~~~~~~~
/usr/include/linux/mount.h:103:2: error: redeclaration of enumerator 'FSCONFIG_CMD_RECONFIGURE'
  103 |  FSCONFIG_CMD_RECONFIGURE = 7, /* Invoke superblock reconfiguration */
      |  ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:265:3: note: previous definition of 'FSCONFIG_CMD_RECONFIGURE' was here
  265 |   FSCONFIG_CMD_RECONFIGURE = 7,   /* Invoke superblock reconfiguration */
      |   ^~~~~~~~~~~~~~~~~~~~~~~~
In file included from ./include/mount-api-utils.h:11,
                 from libmount/src/optlist.c:19:
/usr/include/linux/mount.h:129:8: error: redefinition of 'struct mount_attr'
  129 | struct mount_attr {
      |        ^~~~~~~~~~
In file included from libmount/src/libmount.h:40,
                 from libmount/src/mountP.h:31,
                 from libmount/src/optlist.c:18:
/opt/slapgrid/0f0705ad6e3e586cc45dcb5c9ab9e5f6/parts/gcc-10.5/lib/gcc/x86_64-pc-linux-gnu/10.5.0/include-fixed/sys/mount.h:219:8: note: originally defined here
  219 | struct mount_attr
      |        ^~~~~~~~~~
make[2]: *** [Makefile:12048: libmount/src/la-optlist.lo] Error 1
```

This error was originally detected in Nexedi in
nexedi/slapos@fe60394b (comment 189391)
by @vpelletier, but no action was taken at the time to solve it.
Some of its symptoms were detected and fixed individually in
nexedi/slapos!1579 and
nexedi/slapos!1580 ,
by reordering the includes, but the above error in libmount, which could
not be solved that easily, made me delve more into the problem and find
the root cause.
parent e9ef74fd
......@@ -73,11 +73,16 @@ patch-binary = ${patch:location}/bin/patch
patch-options = -p1
patches =
${:_profile_base_location_}/gcc-libsanitizer-multiple-definition-fsconfig_command.patch#2135c53c901d67ce230f5c94352b7780
${:_profile_base_location_}/gcc-fixincludes.patch#4eaaee0fa06b845ba1fd939e53bc4b53
[gcc-10.5]
<= gcc-common
version = 10.5.0
md5sum = c7d1958570fbd1cd859b015774b9987a
patch-binary = ${patch:location}/bin/patch
patch-options = -p1
patches =
${:_profile_base_location_}/gcc-fixincludes.patch#4eaaee0fa06b845ba1fd939e53bc4b53
[gcc-12.3]
<= gcc-common
......
--- a/fixincludes/fixfixes.c
+++ b/fixincludes/fixfixes.c
@@ -477,6 +477,39 @@ FIX_PROC_HEAD( char_macro_def_fix )
fputs (text, stdout);
}
+/* Check if the pattern at pos is actually in a "__has_include(...)"
+ directive. Return the pointer to the ')' of this
+ "__has_include(...)" if it is, NULL otherwise. */
+static const char *
+check_has_inc (const char *begin, const char *pos, const char *end)
+{
+ static const char has_inc[] = "__has_include";
+ const size_t has_inc_len = sizeof (has_inc) - 1;
+ const char *p;
+
+ for (p = memmem (begin, pos - begin, has_inc, has_inc_len);
+ p != NULL;
+ p = memmem (p, pos - p, has_inc, has_inc_len))
+ {
+ p += has_inc_len;
+ while (p < end && ISSPACE (*p))
+ p++;
+
+ /* "__has_include" may appear as "defined(__has_include)",
+ search for the next appearance then. */
+ if (*p != '(')
+ continue;
+
+ /* To avoid too much complexity, just hope there is never a
+ ')' in a header name. */
+ p = memchr (p, ')', end - p);
+ if (p == NULL || p > pos)
+ return p;
+ }
+
+ return NULL;
+}
+
/* Fix for machine name #ifdefs that are not in the namespace reserved
by the C standard. They won't be defined if compiling with -ansi,
and the headers will break. We go to some trouble to only change
@@ -524,7 +557,7 @@ FIX_PROC_HEAD( machine_name_fix )
/* If the 'name_pat' matches in between base and limit, we have
a bogon. It is not worth the hassle of excluding comments
because comments on #if/#ifdef lines are rare, and strings on
- such lines are illegal.
+ such lines are only legal in a "__has_include" directive.
REG_NOTBOL means 'base' is not at the beginning of a line, which
shouldn't matter since the name_re has no ^ anchor, but let's
@@ -544,8 +577,16 @@ FIX_PROC_HEAD( machine_name_fix )
break;
p = base + match[0].rm_so;
- base += match[0].rm_eo;
+ /* Check if the match is in __has_include(...) (PR 91085). */
+ q = check_has_inc (base, p, limit);
+ if (q)
+ {
+ base = q + 1;
+ goto again;
+ }
+
+ base += match[0].rm_eo;
/* One more test: if on the same line we have the same string
with the appropriate underscores, then leave it alone.
We want exactly two leading and trailing underscores. */
--- a/fixincludes/inclhack.def
+++ b/fixincludes/inclhack.def
@@ -3151,7 +3151,8 @@ fix = {
c_fix = machine_name;
test_text = "/* MACH_DIFF: */\n"
- "#if defined( i386 ) || defined( sparc ) || defined( vax )"
+ "#if defined( i386 ) || defined( sparc ) || defined( vax ) || "
+ "defined( linux ) || __has_include ( <linux.h> )"
"\n/* no uniform test, so be careful :-) */";
};
--- a/fixincludes/tests/base/testing.h
+++ b/fixincludes/tests/base/testing.h
@@ -64,7 +64,7 @@ BSD43__IOWR('T', 1) /* Some are multi-line */
#if defined( MACHINE_NAME_CHECK )
/* MACH_DIFF: */
-#if defined( i386 ) || defined( sparc ) || defined( vax )
+#if defined( i386 ) || defined( sparc ) || defined( vax ) || defined( linux ) || __has_include ( <linux.h> )
/* no uniform test, so be careful :-) */
#endif /* MACHINE_NAME_CHECK */
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment