Skip to content

Commit

Permalink
codegen: Emit diagnostic pragmas for GCC 14, Clang 16 compatibility
Browse files Browse the repository at this point in the history
GCC 14 refuses to compile C sources with certain type errors, to
provide prompt feedback to programmers about mistakes.
Vala does not have the required information for const qualifiers
of parameters and return values which leads to incompatible-pointer
warnings/errors.

As a stop-gap measure, this commit introduces pragmata to turn the
relevant GCC/Clang diagnostics into warnings.  For experimentation,
this can be avoided at C compilation time by defining VALA_STRICT_C.

Clang 16 is broadly similar, except that it is not possible to
turn the errors into warnings using #pragma.  They have to be disabled
completely.  In Clang 16 and 17, -Wincompatible-pointer-types is not
an error yet, but that is likely to change in future Clang versions,
so this commit disables this warning, too.  Another error,
-Wincompatible-function-pointer-types has been split from that,
and needs to be disabled.

Fixes https://gitlab.gnome.org/GNOME/vala/issues/1408
  • Loading branch information
fweimer-rh authored and ricotz committed Feb 4, 2024
1 parent fee6dad commit ae2cbcd
Show file tree
Hide file tree
Showing 832 changed files with 6,895 additions and 0 deletions.
1 change: 1 addition & 0 deletions ccode/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ libvalaccode_la_VALASOURCES = \
valaccodeoncesection.vala \
valaccodeparameter.vala \
valaccodeparenthesizedexpression.vala \
valaccodepragma.vala \
valaccodereturnstatement.vala \
valaccodestatement.vala \
valaccodestruct.vala \
Expand Down
62 changes: 62 additions & 0 deletions ccode/valaccodepragma.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* valaccodepragma.vala
*
* Copyright (C) 2024 Rico Tzschichholz
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Author:
* Rico Tzschichholz <[email protected]>
*/

using GLib;

/**
* Represents a pragma in the C code.
*/
public class Vala.CCodePragma : CCodeNode {
/**
* The prefix of this pragma.
*/
public string prefix { get; set; }

/**
* The directive of this pragma.
*/
public string directive { get; set; }

/**
* The value of this pragma.
*/
public string? value { get; set; }

public CCodePragma (string prefix, string directive, string? value = null) {
this.prefix = prefix;
this.directive = directive;
this.value = value;
}

public override void write (CCodeWriter writer) {
writer.write_indent ();
writer.write_string ("#pragma ");
writer.write_string (prefix);
writer.write_string (" ");
writer.write_string (directive);
if (value != null) {
writer.write_string (" ");
writer.write_string (@value);
}
writer.write_newline ();
}
}
16 changes: 16 additions & 0 deletions codegen/valaccodebasemodule.vala
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,20 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
decl_space.add_define (extern_define);
}

void append_c_compiler_mitigations (CCodeFile decl_space) {
var vala_strict_c = new CCodeIfSection ("!defined(VALA_STRICT_C)");

CCodeIfSection if_section;
if_section = new CCodeIfSection ("!defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)");
vala_strict_c.append (if_section);
if_section.append (new CCodePragma ("GCC", "diagnostic", "warning \"-Wincompatible-pointer-types\""));
if_section = if_section.append_else ("defined(__clang__) && (__clang_major__ >= 16)");
if_section.append (new CCodePragma ("clang", "diagnostic", "ignored \"-Wincompatible-function-pointer-types\""));
if_section.append (new CCodePragma ("clang", "diagnostic", "ignored \"-Wincompatible-pointer-types\""));

decl_space.add_define (vala_strict_c);
}

public override void visit_source_file (SourceFile source_file) {
cfile = new CCodeFile (CCodeFileType.SOURCE, source_file);

Expand Down Expand Up @@ -877,6 +891,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
return;
}

append_c_compiler_mitigations (cfile);

if (requires_assert) {
cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("_vala_assert(expr, msg)", new CCodeConstant ("if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);")));
cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("_vala_return_if_fail(expr, msg)", new CCodeConstant ("if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }")));
Expand Down
9 changes: 9 additions & 0 deletions tests/annotations/deprecated-delegate-minimal.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@

#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

typedef void (*Foo) (void) G_GNUC_DEPRECATED ;

static void _vala_main (void);
Expand Down
9 changes: 9 additions & 0 deletions tests/annotations/deprecated-enum-minimal.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@

#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

typedef enum {
FOO_BAR
} Foo G_GNUC_DEPRECATED ;
Expand Down
8 changes: 8 additions & 0 deletions tests/annotations/deprecated-method-minimal.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@

#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/annotations/deprecated-property-minimal.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@

#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
9 changes: 9 additions & 0 deletions tests/annotations/deprecated-struct-minimal.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@

#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

typedef struct _Foo Foo;

struct _Foo {
Expand Down
8 changes: 8 additions & 0 deletions tests/annotations/deprecated.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
#include <glib-object.h>
#include <string.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/annotations/description.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
#include <stdlib.h>
#include <string.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/cast-struct-boxed-element-access.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
#include <string.h>
#include <stdlib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/class-field-fixed-length-initializer.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
#include <glib.h>
#include <gobject/gvaluecollector.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/class-field-initializer.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
#include <glib-object.h>
#include <gobject/gvaluecollector.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/class-field-length-cname.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
#include <glib.h>
#include <gobject/gvaluecollector.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/constant-element-access.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
#include <string.h>
#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/element-class-assignment.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
#include <gobject/gvaluecollector.h>
#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
9 changes: 9 additions & 0 deletions tests/arrays/element-nullable-assignment.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
#include <glib.h>
#include <string.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

#define _g_free0(var) ((var == NULL) ? NULL : (var = (g_free (var), NULL)))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/empty-length-0.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
#include <string.h>
#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/field-global-length-cname.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@

#include <glib.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/fixed-length-enum-value.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
#include <glib.h>
#include <string.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_WIN32) || defined(__CYGWIN__)
#define VALA_EXTERN __declspec(dllexport) extern
Expand Down
8 changes: 8 additions & 0 deletions tests/arrays/fixed-length-init0-not-allowed.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
#include <string.h>

#define BAR 1024
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
Expand Down
9 changes: 9 additions & 0 deletions tests/arrays/in-operator-with-boxed-needle.c-expected
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
#include <glib.h>
#include <string.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

#define _g_free0(var) ((var == NULL) ? NULL : (var = (g_free (var), NULL)))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
Expand Down
Loading

0 comments on commit ae2cbcd

Please sign in to comment.