[cxx] int vs. enum -- bit overload version (#10274)
commit779ee790817aa5d5aa1ffa3e2f902218945e7ca6
authorJay Krell <jay.krell@cornell.edu>
Wed, 29 Aug 2018 02:50:38 +0000 (28 19:50 -0700)
committerGitHub <noreply@github.com>
Wed, 29 Aug 2018 02:50:38 +0000 (28 19:50 -0700)
treee238bc6127fbe3d4fc3d092482c76b4408c2038f
parentf0966dcd91a5c1bbdfddd90dba48826e1bc24773
[cxx] int vs. enum -- bit overload version (#10274)

* [cxx] int vs. enum.

There are at least three or so approaches to this.

1. Sprinkle around casts.
2. Overload operators.
2a. Bit-only (| & ^ |= &= ^=)   This PR.
2b.  Also math (+ - ++ -- == !=)
3. typedef to int instead (https://github.com/mono/mono/pull/10231)

They all have tradeoffs.

1. Casts: The most line damage. Not huge, but the most.

2. Overloads: New idiom to some but an old idiom. Supported in this way by windows.h even.
  This is the most "C++y solution".

3. int: Highest level of source compat and semantic compat. Least line damage (just
change the declarations). Least debuggable and least typesafe.

In terms of semantic compat, even in C the guarantees aren't particularly strong.
Some enums will be int, some unsigned, depending on the values and the compiler.
Perhaps even other types, but I doubt it.

I observe C++ compilers don't tend toward unsigned the same way, so switching
to C++ will on some platforms lose unsignedness. Given we didn't have it portably
anyway, should be ok.

A typesafe enum has the properties that enum A cannot be silently assigned to enum B (ok,
there might be a warning), or from an integer.

A typesafe enum, bitfield or otherwise, can/will be shown symbolically by a debugger.
 (lldb does not handle bitfields, only strict enums)

A C enum might be debuggable, w/o typesafety.

A C enum can be freely mixed with other enums and integers.

A C++ enum is more restricted.

Using typedef int, is a maybe surprising option, but does provide the closest meaning to C enum.

Per guidance, this PR also changes one enum to #defines + int.

* PR: "mono" => "g"
"T" => "type"
static_cast where it works (not to reference)
Use templatized typedef instead of macro, if it works on g++4.4.
Add test.
Provide to build eglib tests.
Borrow CXXFLAGS_COMMON from https://github.com/mono/mono/pull/10271.
Add some const to test harness.

* g++4.4 compat (not quite C++11) -- use macro, not template typedef.

* Fix real problem with aliasing seen with g++4.4.
Use attribute(may_alias) when casting pointers/references.

* Add mono/eglib/test/enum.cpp.
20 files changed:
configure.ac
mono/eglib/eglib-remap.h
mono/eglib/glib.h
mono/eglib/gmodule.h
mono/eglib/gunicode.c
mono/eglib/test/Makefile.am
mono/eglib/test/enum.cpp [new file with mode: 0644]
mono/eglib/test/test.c
mono/eglib/test/test.h
mono/eglib/test/tests.h
mono/metadata/domain-internals.h
mono/metadata/sre.c
mono/metadata/threads-types.h
mono/metadata/threads.c
mono/metadata/w32handle.c
mono/utils/checked-build.h
mono/utils/mono-threads.h
mono/utils/os-event-unix.c
msvc/test_eglib.vcxproj
msvc/test_eglib.vcxproj.filters