d: Warn when declared size of a special enum does not match its intrinsic type.
All special enums have declarations in the D runtime library, but the compiler will recognize and treat them specially if declared in any module. When the underlying base type of a special enum is a different size to its matched intrinsic, then this can cause undefined behavior at runtime. Detect and warn about when such a mismatch occurs. gcc/d/ChangeLog: * gdc.texi (Warnings): Document -Wextra and -Wmismatched-special-enum. * implement-d.texi (Special Enums): Add reference to warning option -Wmismatched-special-enum. * lang.opt: Add -Wextra and -Wmismatched-special-enum. * types.cc (TypeVisitor::visit (TypeEnum *)): Warn when declared special enum size mismatches its intrinsic type. gcc/testsuite/ChangeLog: * gdc.dg/Wmismatched_enum.d: New test.
This commit is contained in:
parent
108ff03bac
commit
3ad9313a2e
5 changed files with 49 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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 --------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
4
gcc/testsuite/gdc.dg/Wmismatched_enum.d
Normal file
4
gcc/testsuite/gdc.dg/Wmismatched_enum.d
Normal file
|
@ -0,0 +1,4 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-Wmismatched-special-enum" }
|
||||
|
||||
enum __c_longlong : byte; // { dg-warning "differ from its declared size" }
|
Loading…
Add table
Reference in a new issue