Explicitly request unsigned enum types when desired

The underlying type of all plain enums in MSVC is 'int', even if the
enumerator contains large 32-bit unsigned values or values greater than
UINT_MAX.  The only way to get a large or unsigned enum type is to
request it explicitly with the C++11 strong enum types feature.

However, since LLVM isn't C++11 yet, I had to add a conditional
LLVM_ENUM_INT_TYPE to Compiler.h to control its usage.

The motivating true positive for this change is compiling PointerIntPair
with MSVC for win64.  The PointerIntMask value is supposed to be pointer
sized value of all ones with some low zeros.  Instead, it's truncated to
32-bits!  We are only saved later because it is sign extended back in
the AND with int64_t, and we happen to want all ones.

This silences lots of -Wmicrosoft warnings during a clang self-host
targeting Windows.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191241 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Kleckner 2013-09-23 23:26:57 +00:00
parent 5a63474e2d
commit 118a0659ab
11 changed files with 46 additions and 27 deletions

View File

@ -14,6 +14,7 @@
#ifndef LLVM_ADT_POINTERINTPAIR_H #ifndef LLVM_ADT_POINTERINTPAIR_H
#define LLVM_ADT_POINTERINTPAIR_H #define LLVM_ADT_POINTERINTPAIR_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert> #include <cassert>
@ -40,7 +41,7 @@ template <typename PointerTy, unsigned IntBits, typename IntType=unsigned,
typename PtrTraits = PointerLikeTypeTraits<PointerTy> > typename PtrTraits = PointerLikeTypeTraits<PointerTy> >
class PointerIntPair { class PointerIntPair {
intptr_t Value; intptr_t Value;
enum { enum LLVM_ENUM_INT_TYPE(uintptr_t) {
/// PointerBitMask - The bits that come from the pointer. /// PointerBitMask - The bits that come from the pointer.
PointerBitMask = PointerBitMask =
~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1),

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/PointerLikeTypeTraits.h"
#include <bitset> #include <bitset>
#include <cassert> #include <cassert>
@ -200,7 +201,7 @@ public:
/// index `1'. /// index `1'.
class AttributeSet { class AttributeSet {
public: public:
enum AttrIndex { enum AttrIndex LLVM_ENUM_INT_TYPE(unsigned) {
ReturnIndex = 0U, ReturnIndex = 0U,
FunctionIndex = ~0U FunctionIndex = ~0U
}; };

View File

@ -197,7 +197,7 @@ public:
// These are helper methods for dealing with flags in the INLINEASM SDNode // These are helper methods for dealing with flags in the INLINEASM SDNode
// in the backend. // in the backend.
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// Fixed operands on an INLINEASM SDNode. // Fixed operands on an INLINEASM SDNode.
Op_InputChain = 0, Op_InputChain = 0,
Op_AsmString = 1, Op_AsmString = 1,

View File

@ -41,7 +41,7 @@ public:
/// These are the section type and attributes fields. A MachO section can /// These are the section type and attributes fields. A MachO section can
/// have only one Type, but can have any of the attributes specified. /// have only one Type, but can have any of the attributes specified.
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// TypeAndAttributes bitmasks. // TypeAndAttributes bitmasks.
SECTION_TYPE = 0x000000FFU, SECTION_TYPE = 0x000000FFU,
SECTION_ATTRIBUTES = 0xFFFFFF00U, SECTION_ATTRIBUTES = 0xFFFFFF00U,

View File

@ -16,6 +16,9 @@
#ifndef LLVM_MC_MACHINELOCATION_H #ifndef LLVM_MC_MACHINELOCATION_H
#define LLVM_MC_MACHINELOCATION_H #define LLVM_MC_MACHINELOCATION_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
namespace llvm { namespace llvm {
class MCSymbol; class MCSymbol;
@ -25,7 +28,7 @@ private:
unsigned Register; // gcc/gdb register number. unsigned Register; // gcc/gdb register number.
int Offset; // Displacement if not register. int Offset; // Displacement if not register.
public: public:
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// The target register number for an abstract frame pointer. The value is // The target register number for an abstract frame pointer. The value is
// an arbitrary value that doesn't collide with any real target register. // an arbitrary value that doesn't collide with any real target register.
VirtualFP = ~0U VirtualFP = ~0U

View File

@ -192,7 +192,7 @@ public:
ST_Other ST_Other
}; };
enum Flags { enum Flags LLVM_ENUM_INT_TYPE(unsigned) {
SF_None = 0, SF_None = 0,
SF_Undefined = 1U << 0, // Symbol is defined in another object file SF_Undefined = 1U << 0, // Symbol is defined in another object file
SF_Global = 1U << 1, // Global symbol SF_Global = 1U << 1, // Global symbol

View File

@ -222,7 +222,7 @@ namespace COFF {
uint32_t Characteristics; uint32_t Characteristics;
}; };
enum SectionCharacteristics { enum SectionCharacteristics LLVM_ENUM_INT_TYPE(uint32_t) {
SC_Invalid = 0xffffffff, SC_Invalid = 0xffffffff,
IMAGE_SCN_TYPE_NO_PAD = 0x00000008, IMAGE_SCN_TYPE_NO_PAD = 0x00000008,

View File

@ -391,4 +391,16 @@
# define LLVM_STATIC_ASSERT(expr, msg) # define LLVM_STATIC_ASSERT(expr, msg)
#endif #endif
/// \macro LLVM_ENUM_INT_TYPE
/// \brief Expands to colon followed by the given integral type on compilers
/// which support C++11 strong enums. This can be used to make enums unsigned
/// with MSVC.
#if __has_feature(cxx_strong_enums)
# define LLVM_ENUM_INT_TYPE(intty) : intty
#elif defined(_MSC_VER) && _MSC_VER >= 1600 // Added in MSVC 2010.
# define LLVM_ENUM_INT_TYPE(intty) : intty
#else
# define LLVM_ENUM_INT_TYPE(intty)
#endif
#endif #endif

View File

@ -16,6 +16,7 @@
#ifndef LLVM_SUPPORT_DWARF_H #ifndef LLVM_SUPPORT_DWARF_H
#define LLVM_SUPPORT_DWARF_H #define LLVM_SUPPORT_DWARF_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
namespace llvm { namespace llvm {
@ -23,7 +24,7 @@ namespace llvm {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Debug info constants. // Debug info constants.
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
LLVMDebugVersion = (12 << 16), // Current version of debug information. LLVMDebugVersion = (12 << 16), // Current version of debug information.
LLVMDebugVersion11 = (11 << 16), // Constant for version 11. LLVMDebugVersion11 = (11 << 16), // Constant for version 11.
LLVMDebugVersion10 = (10 << 16), // Constant for version 10. LLVMDebugVersion10 = (10 << 16), // Constant for version 10.
@ -46,7 +47,7 @@ namespace dwarf {
// Do not mix the following two enumerations sets. DW_TAG_invalid changes the // Do not mix the following two enumerations sets. DW_TAG_invalid changes the
// enumeration base type. // enumeration base type.
enum LLVMConstants { enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) {
// llvm mock tags // llvm mock tags
DW_TAG_invalid = ~0U, // Tag for invalid results. DW_TAG_invalid = ~0U, // Tag for invalid results.

View File

@ -650,7 +650,7 @@ enum {
}; };
// ARM Specific e_flags // ARM Specific e_flags
enum { enum LLVM_ENUM_INT_TYPE(unsigned) {
EF_ARM_SOFT_FLOAT = 0x00000200U, EF_ARM_SOFT_FLOAT = 0x00000200U,
EF_ARM_VFP_FLOAT = 0x00000400U, EF_ARM_VFP_FLOAT = 0x00000400U,
EF_ARM_EABI_UNKNOWN = 0x00000000U, EF_ARM_EABI_UNKNOWN = 0x00000000U,
@ -800,7 +800,7 @@ enum {
}; };
// Mips Specific e_flags // Mips Specific e_flags
enum { enum LLVM_ENUM_INT_TYPE(unsigned) {
EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions
EF_MIPS_PIC = 0x00000002, // Position independent code EF_MIPS_PIC = 0x00000002, // Position independent code
EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code
@ -1116,7 +1116,7 @@ enum {
}; };
// Section types. // Section types.
enum { enum LLVM_ENUM_INT_TYPE(unsigned) {
SHT_NULL = 0, // No associated section (inactive entry). SHT_NULL = 0, // No associated section (inactive entry).
SHT_PROGBITS = 1, // Program-defined contents. SHT_PROGBITS = 1, // Program-defined contents.
SHT_SYMTAB = 2, // Symbol table. SHT_SYMTAB = 2, // Symbol table.
@ -1164,7 +1164,7 @@ enum {
}; };
// Section flags. // Section flags.
enum { enum LLVM_ENUM_INT_TYPE(unsigned) {
// Section data should be writable during execution. // Section data should be writable during execution.
SHF_WRITE = 0x1, SHF_WRITE = 0x1,
@ -1234,7 +1234,7 @@ enum {
}; };
// Section Group Flags // Section Group Flags
enum { enum LLVM_ENUM_INT_TYPE(unsigned) {
GRP_COMDAT = 0x1, GRP_COMDAT = 0x1,
GRP_MASKOS = 0x0ff00000, GRP_MASKOS = 0x0ff00000,
GRP_MASKPROC = 0xf0000000 GRP_MASKPROC = 0xf0000000
@ -1451,7 +1451,7 @@ enum {
}; };
// Segment flag bits. // Segment flag bits.
enum { enum LLVM_ENUM_INT_TYPE(unsigned) {
PF_X = 1, // Execute PF_X = 1, // Execute
PF_W = 2, // Write PF_W = 2, // Write
PF_R = 4, // Read PF_R = 4, // Read

View File

@ -14,13 +14,14 @@
#ifndef LLVM_SUPPORT_MACHO_H #ifndef LLVM_SUPPORT_MACHO_H
#define LLVM_SUPPORT_MACHO_H #define LLVM_SUPPORT_MACHO_H
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/Support/Host.h" #include "llvm/Support/Host.h"
namespace llvm { namespace llvm {
namespace MachO { namespace MachO {
// Enums from <mach-o/loader.h> // Enums from <mach-o/loader.h>
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// Constants for the "magic" field in llvm::MachO::mach_header and // Constants for the "magic" field in llvm::MachO::mach_header and
// llvm::MachO::mach_header_64 // llvm::MachO::mach_header_64
MH_MAGIC = 0xFEEDFACEu, MH_MAGIC = 0xFEEDFACEu,
@ -75,12 +76,12 @@ namespace llvm {
MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u
}; };
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// Flags for the "cmd" field in llvm::MachO::load_command // Flags for the "cmd" field in llvm::MachO::load_command
LC_REQ_DYLD = 0x80000000u LC_REQ_DYLD = 0x80000000u
}; };
enum LoadCommandType { enum LoadCommandType LLVM_ENUM_INT_TYPE(uint32_t) {
// Constants for the "cmd" field in llvm::MachO::load_command // Constants for the "cmd" field in llvm::MachO::load_command
LC_SEGMENT = 0x00000001u, LC_SEGMENT = 0x00000001u,
LC_SYMTAB = 0x00000002u, LC_SYMTAB = 0x00000002u,
@ -130,7 +131,7 @@ namespace llvm {
LC_LINKER_OPTIONS = 0x0000002Du LC_LINKER_OPTIONS = 0x0000002Du
}; };
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// Constant bits for the "flags" field in llvm::MachO::segment_command // Constant bits for the "flags" field in llvm::MachO::segment_command
SG_HIGHVM = 0x1u, SG_HIGHVM = 0x1u,
SG_FVMLIB = 0x2u, SG_FVMLIB = 0x2u,
@ -173,7 +174,7 @@ namespace llvm {
S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u
}; };
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// Constant masks for the "flags[31:24]" field in llvm::MachO::section and // Constant masks for the "flags[31:24]" field in llvm::MachO::section and
// llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_USR) // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_USR)
S_ATTR_PURE_INSTRUCTIONS = 0x80000000u, S_ATTR_PURE_INSTRUCTIONS = 0x80000000u,
@ -235,9 +236,9 @@ namespace llvm {
}; };
enum BindSpecialDylib { enum BindSpecialDylib {
BIND_SPECIAL_DYLIB_SELF = 0u, BIND_SPECIAL_DYLIB_SELF = 0,
BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1u, BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE = -1,
BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2u BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2
}; };
enum { enum {
@ -347,7 +348,7 @@ namespace llvm {
N_LENG = 0xFEu N_LENG = 0xFEu
}; };
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// Constant values for the r_symbolnum field in an // Constant values for the r_symbolnum field in an
// llvm::MachO::relocation_info structure when r_extern is 0. // llvm::MachO::relocation_info structure when r_extern is 0.
R_ABS = 0, R_ABS = 0,
@ -892,7 +893,7 @@ namespace llvm {
} }
// Enums from <mach/machine.h> // Enums from <mach/machine.h>
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// Capability bits used in the definition of cpu_type. // Capability bits used in the definition of cpu_type.
CPU_ARCH_MASK = 0xff000000, // Mask for architecture bits CPU_ARCH_MASK = 0xff000000, // Mask for architecture bits
CPU_ARCH_ABI64 = 0x01000000 // 64 bit ABI CPU_ARCH_ABI64 = 0x01000000 // 64 bit ABI
@ -912,13 +913,13 @@ namespace llvm {
CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64
}; };
enum { enum LLVM_ENUM_INT_TYPE(uint32_t) {
// Capability bits used in the definition of cpusubtype. // Capability bits used in the definition of cpusubtype.
CPU_SUB_TYPE_MASK = 0xff000000, // Mask for architecture bits CPU_SUB_TYPE_MASK = 0xff000000, // Mask for architecture bits
CPU_SUB_TYPE_LIB64 = 0x80000000, // 64 bit libraries CPU_SUB_TYPE_LIB64 = 0x80000000, // 64 bit libraries
// Special CPU subtype constants. // Special CPU subtype constants.
CPU_SUBTYPE_MULTIPLE = -1 CPU_SUBTYPE_MULTIPLE = ~0u
}; };
// Constants for the cpusubtype field. // Constants for the cpusubtype field.