diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index 2018b9575aed..62e80db0d603 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -272,6 +272,7 @@ or compiler being used: | c_args | | free-form comma-separated list | C compile arguments to use | | c_link_args | | free-form comma-separated list | C link arguments to use | | c_std | none | none, c89, c99, c11, c17, c18, c2x, c23, gnu89, gnu99, gnu11, gnu17, gnu18, gnu2x, gnu23 | C language standard to use | +| c_legal_code | true | true, false | Ban C dangerous constructs by default in C99 or later | | c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against | | c_thread_count | 4 | integer value ≥ 0 | Number of threads to use with emcc when using threads | | cpp_args | | free-form comma-separated list | C++ compile arguments to use | diff --git a/docs/markdown/snippets/c-legal-code.md b/docs/markdown/snippets/c-legal-code.md new file mode 100644 index 000000000000..e65c652ab226 --- /dev/null +++ b/docs/markdown/snippets/c-legal-code.md @@ -0,0 +1,16 @@ +## `c_legal_code` option introduced + +The new `c_legal_code` option is enabled by default. It bans +dangerous C constructs in C99 or later to emulate newer C compiler +defaults. + +For GCC, it sets the following: +* `-Werror=implicit` (-> `-Werror=implicit-int,implicit-function-declaration`) +* `-Werror=int-conversion` +* `-Werror=incompatible-pointer-types` + +For Clang, it sets the following: +* `-Werror=implicit` (-> `-Werror=implicit-int,implicit-function-declaration`) +* `-Werror=int-conversion` +* `-Werror=incompatible-pointer-types` +* `-Wno-error=incompatible-pointer-types-discards-qualifiers` (to emulate GCC's behavior) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 819ef8bb8628..900d1d0465dd 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -153,6 +153,15 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ def get_options(self) -> 'MutableKeyedOptionDictType': opts = super().get_options() + + self.update_options( + opts, + self.create_option(options.UserBooleanOption, + self.form_compileropt_key('legal_code'), + 'Ban use of dangerous constructs', + True), + ) + if self.info.is_windows() or self.info.is_cygwin(): self.update_options( opts, @@ -169,6 +178,11 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] std = options.get_value(key) if std != 'none': args.append('-std=' + std) + + if options.get_value(self.form_compileropt_key('legal_code')): + if version_compare(self.version, '>=3.3.0') and std.value not in ('c89', 'c90', 'gnu89', 'gnu90'): + args.extend(('-Werror=implicit', '-Werror=int-conversion', '-Werror=incompatible-pointer-types', '-Wno-error=incompatible-pointer-types-discards-qualifiers')) + return args def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: @@ -306,11 +320,20 @@ def get_options(self) -> 'MutableKeyedOptionDictType': std_opt = opts[key] assert isinstance(std_opt, options.UserStdOption), 'for mypy' std_opt.set_versions(stds, gnu=True) + + self.update_options( + opts, + self.create_option(options.UserBooleanOption, + self.form_compileropt_key('legal_code'), + 'Ban use of dangerous constructs', + True), + ) + if self.info.is_windows() or self.info.is_cygwin(): self.update_options( opts, self.create_option(options.UserArrayOption, - key.evolve('c_winlibs'), + self.form_compileropt_key('c_winlibs'), 'Standard Win libraries to link against', gnu_winlibs), ) @@ -322,6 +345,11 @@ def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str] std = options.get_value(key) if std != 'none': args.append('-std=' + std) + + if options.get_value(self.form_compileropt_key('legal_code')): + if version_compare(self.version, '>=5.1.0') and version_compare(self.version, '<14.0.0') and std.value not in ('c89', 'c90', 'gnu89', 'gnu90'): + args.extend(('-Werror=implicit', '-Werror=int-conversion', '-Werror=incompatible-pointer-types')) + return args def get_option_link_args(self, options: 'KeyedOptionDictType') -> T.List[str]: diff --git a/test cases/vala/1 basic/meson.build b/test cases/vala/1 basic/meson.build index d1bfabdc1b30..40643131c1d4 100644 --- a/test cases/vala/1 basic/meson.build +++ b/test cases/vala/1 basic/meson.build @@ -1,5 +1,5 @@ # Language are case unsensitive, check here that capital C works too. -project('valatest', 'vala', 'C') +project('valatest', 'vala', 'C', default_options: ['c_legal_code=false']) valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')] diff --git a/test cases/vala/11 generated vapi/meson.build b/test cases/vala/11 generated vapi/meson.build index d5f38cad6abd..a9655598b16a 100644 --- a/test cases/vala/11 generated vapi/meson.build +++ b/test cases/vala/11 generated vapi/meson.build @@ -1,4 +1,4 @@ -project('vapi-test', ['c', 'vala']) +project('vapi-test', ['c', 'vala'], default_options: ['c_legal_code=false']) gnome = import('gnome') subdir('libfoo') diff --git a/test cases/vala/14 target glib version and gresources/meson.build b/test cases/vala/14 target glib version and gresources/meson.build index dee26278d9b5..bf3e608cf8b6 100644 --- a/test cases/vala/14 target glib version and gresources/meson.build +++ b/test cases/vala/14 target glib version and gresources/meson.build @@ -1,4 +1,4 @@ -project('test glib target version and gresources', 'c', 'vala') +project('test glib target version and gresources', 'c', 'vala', default_options: ['c_legal_code=false']) gnome = import('gnome') diff --git a/test cases/vala/16 mixed dependence/meson.build b/test cases/vala/16 mixed dependence/meson.build index b44b47b31260..f9faa8c88fdc 100644 --- a/test cases/vala/16 mixed dependence/meson.build +++ b/test cases/vala/16 mixed dependence/meson.build @@ -1,4 +1,4 @@ -project('mixed dependence', 'vala', 'c') +project('mixed dependence', 'vala', 'c', default_options: ['c_legal_code=false']) cc = meson.get_compiler('c') diff --git a/test cases/vala/17 plain consumer/meson.build b/test cases/vala/17 plain consumer/meson.build index e98bca122486..b6ac311dab60 100644 --- a/test cases/vala/17 plain consumer/meson.build +++ b/test cases/vala/17 plain consumer/meson.build @@ -1,4 +1,4 @@ -project('plain consumer', 'vala', 'c') +project('plain consumer', 'vala', 'c', default_options: ['c_legal_code=false']) deps = [dependency('glib-2.0'), dependency('gobject-2.0')] diff --git a/test cases/vala/18 vapi consumed twice/meson.build b/test cases/vala/18 vapi consumed twice/meson.build index 6a7f5ebc5fc3..938391b6b585 100644 --- a/test cases/vala/18 vapi consumed twice/meson.build +++ b/test cases/vala/18 vapi consumed twice/meson.build @@ -1,4 +1,4 @@ -project('vapi consumed twice', 'vala', 'c') +project('vapi consumed twice', 'vala', 'c', default_options: ['c_legal_code=false']) base_deps = [dependency('glib-2.0'), dependency('gobject-2.0')] diff --git a/test cases/vala/2 multiple files/meson.build b/test cases/vala/2 multiple files/meson.build index dc3607377e9e..3b00aa0cbf12 100644 --- a/test cases/vala/2 multiple files/meson.build +++ b/test cases/vala/2 multiple files/meson.build @@ -1,5 +1,5 @@ # adding 'c' shouldn't be required -project('multiple files') +project('multiple files', default_options: ['c_legal_code=false']) add_languages('vala') glib = dependency('glib-2.0') diff --git a/test cases/vala/20 genie multiple mixed sources/meson.build b/test cases/vala/20 genie multiple mixed sources/meson.build index 148ce0e479d5..b865d7f61120 100644 --- a/test cases/vala/20 genie multiple mixed sources/meson.build +++ b/test cases/vala/20 genie multiple mixed sources/meson.build @@ -1,4 +1,4 @@ -project( 'Genie multiple and mixed sources', 'vala', 'c' ) +project( 'Genie multiple and mixed sources', 'vala', 'c', default_options: ['c_legal_code=false']) genie_deps = [ dependency( 'glib-2.0' ), diff --git a/test cases/vala/21 type module/meson.build b/test cases/vala/21 type module/meson.build index 9bd26e3185fd..873bb7967180 100644 --- a/test cases/vala/21 type module/meson.build +++ b/test cases/vala/21 type module/meson.build @@ -1,4 +1,4 @@ -project('valatest', 'c', 'vala') +project('valatest', 'c', 'vala', default_options: ['c_legal_code=false']) glib_dep = dependency('glib-2.0') gobject_dep = dependency('gobject-2.0') diff --git a/test cases/vala/22 same target in directories/meson.build b/test cases/vala/22 same target in directories/meson.build index 6785f7377be0..107a53e85d27 100644 --- a/test cases/vala/22 same target in directories/meson.build +++ b/test cases/vala/22 same target in directories/meson.build @@ -1,4 +1,4 @@ -project('valatest', 'vala', 'c') +project('valatest', 'vala', 'c', default_options: ['c_legal_code=false']) valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')] valafiles = files( diff --git a/test cases/vala/25 extract_all_objects/meson.build b/test cases/vala/25 extract_all_objects/meson.build index a1a4ebce1044..f1621ce5133e 100644 --- a/test cases/vala/25 extract_all_objects/meson.build +++ b/test cases/vala/25 extract_all_objects/meson.build @@ -1,4 +1,4 @@ -project('valatest', 'vala', 'c') +project('valatest', 'vala', 'c', default_options: ['c_legal_code=false']) valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')] diff --git a/test cases/vala/26 vala and asm/meson.build b/test cases/vala/26 vala and asm/meson.build index 4e662e70caf6..f8b6c87b8352 100644 --- a/test cases/vala/26 vala and asm/meson.build +++ b/test cases/vala/26 vala and asm/meson.build @@ -1,4 +1,4 @@ -project('vala and asm', 'vala', 'c') +project('vala and asm', 'vala', 'c', default_options: ['c_legal_code=false']) cpu = host_machine.cpu_family() cc = meson.get_compiler('c') diff --git a/test cases/vala/27 file as command line argument/meson.build b/test cases/vala/27 file as command line argument/meson.build index 579ca51987f5..5831f40dda5d 100644 --- a/test cases/vala/27 file as command line argument/meson.build +++ b/test cases/vala/27 file as command line argument/meson.build @@ -1,4 +1,4 @@ -project('composite', 'vala', 'c') +project('composite', 'vala', 'c', default_options: ['c_legal_code=false']) gnome = import('gnome') deps = [ dependency('glib-2.0', version : '>=2.38'), diff --git a/test cases/vala/3 dep/meson.build b/test cases/vala/3 dep/meson.build index c3563b1e6804..2072c68dbbc0 100644 --- a/test cases/vala/3 dep/meson.build +++ b/test cases/vala/3 dep/meson.build @@ -1,4 +1,4 @@ -project('giotest', 'vala', 'c') +project('giotest', 'vala', 'c', default_options: ['c_legal_code=false']) glib = dependency('glib-2.0') gobject = dependency('gobject-2.0') diff --git a/test cases/vala/4 config/meson.build b/test cases/vala/4 config/meson.build index 7cb93cf73777..bb966ab766f2 100644 --- a/test cases/vala/4 config/meson.build +++ b/test cases/vala/4 config/meson.build @@ -1,4 +1,4 @@ -project('valatest', 'vala', 'c') +project('valatest', 'vala', 'c', default_options: ['c_legal_code=false']) valac = meson.get_compiler('vala') # Try to find our library diff --git a/test cases/vala/5 target glib/meson.build b/test cases/vala/5 target glib/meson.build index 089bb3c97354..ecc814627616 100644 --- a/test cases/vala/5 target glib/meson.build +++ b/test cases/vala/5 target glib/meson.build @@ -1,4 +1,4 @@ -project('valatest', 'vala', 'c') +project('valatest', 'vala', 'c', default_options: ['c_legal_code=false']) valadeps = [dependency('glib-2.0', version : '>=2.32'), dependency('gobject-2.0')] diff --git a/test cases/vala/6 static library/meson.build b/test cases/vala/6 static library/meson.build index c74bdf89b691..7176e0a95d86 100644 --- a/test cases/vala/6 static library/meson.build +++ b/test cases/vala/6 static library/meson.build @@ -1,4 +1,4 @@ -project('valastatic', 'vala', 'c') +project('valastatic', 'vala', 'c', default_options: ['c_legal_code=false']) valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')] diff --git a/test cases/vala/7 shared library/meson.build b/test cases/vala/7 shared library/meson.build index 9c56f1498dc9..04879bb7f9ba 100644 --- a/test cases/vala/7 shared library/meson.build +++ b/test cases/vala/7 shared library/meson.build @@ -1,4 +1,4 @@ -project('shared library', 'vala', 'c') +project('shared library', 'vala', 'c', default_options: ['c_legal_code=false']) valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')]