diff --git a/gcc/d/gdc.texi b/gcc/d/gdc.texi index 24b6ee00478943fde0849b1b4c8733a4bf54827b..6f81967a83dc1b7fe052ff20417a02e7e1bf8db4 100644 --- a/gcc/d/gdc.texi +++ b/gcc/d/gdc.texi @@ -699,6 +699,23 @@ Do not warn about usage of deprecated features and symbols with @item -Werror Turns all warnings into errors. +@opindex Wextra +@opindex Wno-extra +@item -Wextra +This enables some extra warning flags that are not enabled by +@option{-Wall}. + +@gccoptlist{-Waddress +-Wcast-result +-Wmismatched-special-enum +-Wunknown-pragmas} + +@opindex Wmismatched-special-enum +@opindex Wno-mismatched-special-enum +@item -Wmismatched-special-enum +Warn when an enum the compiler recognizes as special is declared with a +different size to the built-in type it is representing. + @opindex Wspeculative @opindex Wno-speculative @item -Wspeculative diff --git a/gcc/d/implement-d.texi b/gcc/d/implement-d.texi index 039e5fbd24e0845c4ffcd884be2fbdbbb2ff3dfe..6f33bc192fe3577a3567895fefe6078eca416ffd 100644 --- a/gcc/d/implement-d.texi +++ b/gcc/d/implement-d.texi @@ -2085,6 +2085,11 @@ for convenience: @code{c_complex_double}, @code{c_complex_float}, @code{c_complex_real}, @code{cpp_long}, @code{cpp_longlong}, @code{c_long_double}, @code{cpp_ulong}, @code{cpp_ulonglong}. +It may cause undefined behavior at runtime if a special enum is declared with a +base type that has a different size to the target C/C++ type it is +representing. The GNU D compiler will catch such declarations and emit a +warning when the @option{-Wmismatched-special-enum} option is seen on the +command-line. @c -------------------------------------------------------- diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt index bb0a3dcc911bb2e24f9250853d275095415334ef..26ca92c4c17bc540b35b6d160949952a527f64e8 100644 --- a/gcc/d/lang.opt +++ b/gcc/d/lang.opt @@ -134,6 +134,14 @@ Werror D ; Documented in common.opt +Wextra +D Warning +; Documented in common.opt + +Wmismatched-special-enum +D Warning Var(warn_mismatched_special_enum) LangEnabledBy(D, Wextra) +Warn when a special enum is declared with the wrong base type. + Wpsabi D ; Documented in C diff --git a/gcc/d/types.cc b/gcc/d/types.cc index beaf2a61af999d833be0f67a01e87b6873122ebd..a4c05bfb75f01ada0073ebf7db3dbe5c3cb4cab2 100644 --- a/gcc/d/types.cc +++ b/gcc/d/types.cc @@ -1067,6 +1067,21 @@ public: gcc_assert (underlying != NULL); t->ctype = build_variant_type_copy (build_ctype (underlying)); + + /* When the size of the declared enum base type doesn't match the target + C type that this enum is being used as a placeholder for, we can't + use the generated underlying type as it'll conflict with all sizes + the front-end has computed during semantic. */ + if (TYPE_SIZE (t->ctype) != TYPE_SIZE (basetype)) + { + warning_at (make_location_t (t->sym->loc), + OPT_Wmismatched_special_enum, + "size of %qs (%wd) differ from its declared size (%wd)", + t->sym->ident->toChars (), int_size_in_bytes (t->ctype), + int_size_in_bytes (basetype)); + t->ctype = basetype; + } + build_type_decl (t->ctype, t->sym); } else if (t->sym->ident == NULL diff --git a/gcc/testsuite/gdc.dg/Wmismatched_enum.d b/gcc/testsuite/gdc.dg/Wmismatched_enum.d new file mode 100644 index 0000000000000000000000000000000000000000..54f47988c2b5683af58b2236fadab6079683acaf --- /dev/null +++ b/gcc/testsuite/gdc.dg/Wmismatched_enum.d @@ -0,0 +1,4 @@ +// { dg-do compile } +// { dg-options "-Wmismatched-special-enum" } + +enum __c_longlong : byte; // { dg-warning "differ from its declared size" }