After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 790318 - gnome-terminal 3.27.1 fails to build (clang 5)
gnome-terminal 3.27.1 fails to build (clang 5)
Status: RESOLVED FIXED
Product: gnome-terminal
Classification: Core
Component: general
3.27.x
Other Linux
: Low enhancement
: ---
Assigned To: GNOME Terminal Maintainers
GNOME Terminal Maintainers
Depends on:
Blocks:
 
 
Reported: 2017-11-14 09:02 UTC by Cynede
Modified: 2017-12-27 22:33 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Workaround (708 bytes, patch)
2017-11-24 21:07 UTC, Egmont Koblinger
none Details | Review
Workaround, v2 (893 bytes, patch)
2017-12-16 23:29 UTC, Egmont Koblinger
none Details | Review

Description Cynede 2017-11-14 09:02:34 UTC
al_server-terminal-debug.o `test -f 'terminal-debug.c' || echo './'`terminal-debug.c
clang -DHAVE_CONFIG_H -I. -I..  -DTERMINAL_COMPILATION -DTERM_LOCALEDIR="\"/usr/share/locale\"" -DTERM_LIBEXECDIR="\"/usr/libexec\""   -pthread -I/usr/include/vte-2.91 -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libdrm -I/usr/include/libpng16 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/dconf -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/uuid -I/usr/include/gsettings-desktop-schemas -pipe -Waggregate-return -Wall -Wcast-align -Wendif-labels -Werror=format=2 -Werror=format-nonliteral -Werror=format-security -Werror=implicit-function-declaration -Werror=init-self -Werror=missing-include-dirs -Werror=missing-prototypes -Werror=pointer-arith -Wextra -Wfloat-equal -Wimplicit -Wmissing-declarations -Wmissing-include-dirs -Wmissing-format-attribute -Wmissing-noreturn -Wnested-externs -Wno-missing-field-initializers -Wno-switch-enum -Wno-unused-parameter -Wold-style-definition -Wpacked -Wshadow -Wsign-compare -Wstrict-aliasing=2 -Wstrict-prototypes -Wundef -Wuninitialized -Wwrite-strings -fno-common -fdiagnostics-show-option -fno-strict-aliasing -fvisibility=hidden -fstack-protector -fstack-protector-strong  -O2 -march=native -mtune=native -pipe -c -o gnome_terminal_server-terminal-encoding.o `test -f 'terminal-encoding.c' || echo './'`terminal-encoding.c
terminal-options.c:62:24: error: format string is not a string literal [-Werror,-Wformat-nonliteral]
        g_vfprintf(fp, commented_format, args);
                       ^~~~~~~~~~~~~~~~
Comment 1 Cynede 2017-11-14 09:04:55 UTC
confirming: compiles fine with gcc 6.4.0, fails on clang 5
Comment 2 Christian Persch 2017-11-14 09:54:11 UTC
That's what the G_GNUC_FORMAT on the function above it is for. If that doesn't work, that's clang's fault, not our code's. Try adding a prototype for it with the format and deleting the format from the implementation, or try moving the FORMAT before the static; does any of these fix this?
Comment 3 Christian Persch 2017-11-20 18:54:09 UTC
Well?
Comment 4 Cynede 2017-11-21 06:29:18 UTC
Sorry, had no time for that, currently set to it to be built with gcc
Comment 5 Egmont Koblinger 2017-11-24 13:17:57 UTC
I don't think it's clang's fault.

G_GNUC_FORMAT applies to the parameter of format_as_comment() but not to its return value. I can't find a corresponding annotation for the latter. g_strdup_printf doesn't have anything like this either. So the compiler has no chance of knowing that the return value of this function is also a printf-format string.

This return value is then stored in commented_format, again, I can't find any way to denote that it's a format string; and later this is passed to g_vfprintf().
Comment 6 Egmont Koblinger 2017-11-24 13:28:16 UTC
Hmmm, I might have been wrong here.

G_GNUC_FORMAT translates to __attribute__((__format_arg__(...))) for which https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes says:

    The format_arg attribute specifies that a function takes a format string for a printf, scanf, strftime or strfmon style function and modifies it [...]

    extern char *
    my_dgettext (char *my_domain, const char *my_format)
          __attribute__ ((format_arg (2)));

I wish it elaborated on that "modifies" word, but modifying in-place doesn't make any sense, so I guess it means to "return" the new value. In which case our code indeed looks correct to me.
Comment 7 Egmont Koblinger 2017-11-24 13:30:57 UTC
> Try adding a prototype
> for it with the format and deleting the format from the implementation, or
> try moving the FORMAT before the static; does any of these fix this?

Nope.
Comment 8 Egmont Koblinger 2017-11-24 21:02:41 UTC
It looks to me that there's nothing wrong with the G_GNUC_FORMAT(1) attribute. It could be moved to after the function name and parameters to be more consistent, but it's irrelevant.

What clang doesn't like is placing the result in char *commented_format. Looks to me that somehow it doesn't trust that just because we assign a certain value to this variable _here_, this variable will always have such a format value everywhere (in particular, at that g_vfprintf() below).

Clang is happy if we skip this intermediate variable:

  g_vfprintf(fp, format_as_comment (format), args);

or if we make it super-duper constant:

  const char * const commented_format = format_as_comment (format);

Note that both "const"s are required, omitting any of them results in the aforementioned error.

How to free the string in these cases, though?? gs_free is obviously rejected, one possibility is to free with an un-consting cast:

  g_free ((char *)commented_format);

which is quite ugly, but might be the best we can come up with.
Comment 9 Egmont Koblinger 2017-11-24 21:07:53 UTC
Created attachment 364360 [details] [review]
Workaround
Comment 10 Egmont Koblinger 2017-11-24 21:09:18 UTC
A note to my future self:

sudo apt install clang-5.0

CC=clang-5.0 CPP=clang-cpp-5.0 CXX=clang++-5.0 CXXCPP=clang-cpp-5.0 ./autogen.sh ...
Comment 11 Christian Persch 2017-11-24 22:45:16 UTC
How about

static const char * G_GNUC_FORMAT (2)
format_as_comment (char** freeme, const char *format)
{
  return *freeme = g_strdup_printf ("# %s", format);
}

and use as

gs_free char* freeme;
g_vfprintf(fp, format_as_comment(&freeme, format), args);
Comment 12 Egmont Koblinger 2017-11-24 22:52:16 UTC
Compiles cleanly.
Comment 13 Egmont Koblinger 2017-11-24 23:20:14 UTC
... or just simply print "# " and then vfprintf(fp, format, args).

It has a slim chance of some other tool that also produces output to intervene, although I guess this problem is negligible.

By the way, this whole thing with the "# " prefix, to be compatible with --print-environment as the comment in the file says, makes me wonder: Why do we print warning/error messages to stdout rather than stderr?
Comment 14 Egmont Koblinger 2017-12-16 23:29:51 UTC
Created attachment 365631 [details] [review]
Workaround, v2

Let's not forget about this... Christian, please submit whichever workaround you prefer, thanks :)
Comment 15 Christian Persch 2017-12-17 10:20:59 UTC
Comment on attachment 365631 [details] [review]
Workaround, v2

This one please :-)

@Reporter: Please file a bug with clang for this erroneous warning.
Comment 16 Egmont Koblinger 2017-12-17 11:27:53 UTC
(In reply to Christian Persch from comment #15)

> @Reporter: Please file a bug with clang for this erroneous warning.

Please point them to https://git.gnome.org/browse/gnome-terminal/tree/src/terminal-options.c?h=3.27.1#n44 lines 44-64 for the relevant code.
Comment 17 Egmont Koblinger 2017-12-17 11:33:03 UTC
> This one please :-)

Submitted.
Comment 18 Christian Persch 2017-12-27 22:33:11 UTC
@Reporter: Please add a link to the clang bug on the See Also: field on this bug.