Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -368,6 +368,9 @@ "field of %1">, InGroup, DefaultIgnore; +def err_enums_not_permitted: + Error<"enumeration types are prohibited">; + // C++ decomposition declarations def err_decomp_decl_context : Error< "decomposition declaration not permitted in this context">; Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -176,7 +176,9 @@ ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method") ENUM_LANGOPT(DefaultCallingConv, DefaultCallingConvention, 3, DCC_None, "default calling convention") +LANGOPT(NoEnums , 1, 0, "prohibit the use of enum types") LANGOPT(ShortEnums , 1, 0, "short enum types") +LANGOPT(ABIEnums , 1, 0, "enums contain a value needing 32 bits to encode") LANGOPT(OpenCL , 1, 0, "OpenCL") LANGOPT(OpenCLVersion , 32, 0, "OpenCL version") Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1028,6 +1028,7 @@ def fno_rtti : Flag<["-"], "fno-rtti">, Group, Flags<[CC1Option]>, HelpText<"Disable generation of rtti information">; def fno_short_enums : Flag<["-"], "fno-short-enums">, Group; +def fno_abi_enums : Flag<["-"], "fno-abi-enums">, Group; def fno_show_column : Flag<["-"], "fno-show-column">, Group, Flags<[CC1Option]>, HelpText<"Do not include column number on diagnostics">; def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group, @@ -1165,8 +1166,12 @@ HelpText<"Override the default ABI to return small structs in registers">; def frtti : Flag<["-"], "frtti">, Group; def : Flag<["-"], "fsched-interblock">, Group; +def fno_enums : Flag<["-"], "fno-enums">, Group, Flags<[CC1Option]>, + HelpText<"Disable enumeration types">; def fshort_enums : Flag<["-"], "fshort-enums">, Group, Flags<[CC1Option]>, HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">; +def fabi_enums : Flag<["-"], "fabi-enums">, Group, Flags<[CC1Option]>, + HelpText<"All enums contain a value needing 32 bits to encode">; def fshort_wchar : Flag<["-"], "fshort-wchar">, Group, Flags<[CC1Option]>, HelpText<"Force wchar_t to be a short unsigned int">; def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group, Flags<[CC1Option]>, Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -5402,8 +5402,9 @@ Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4"); - Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", - Opts.ShortEnums ? "1" : "4"); + if (!Opts.NoEnums) + Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", + Opts.ShortEnums || Opts.ABIEnums ? "1" : "4"); if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") { Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); @@ -5928,8 +5929,9 @@ Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4"); - Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", - Opts.ShortEnums ? "1" : "4"); + if (!Opts.NoEnums) + Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", + Opts.ShortEnums || Opts.ABIEnums ? "1" : "4"); if (FPU == NeonMode) { Builder.defineMacro("__ARM_NEON", "1"); Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -51,6 +51,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/ProfileData/InstrProfReader.h" +#include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" @@ -460,9 +461,18 @@ Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity(); getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth); - // The minimum width of an enum in bytes - uint64_t EnumWidth = Context.getLangOpts().ShortEnums ? 1 : 4; - getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth); + // Generate a module flag which indicates the value of Tag_ABI_enum_size. + uint64_t EnumSizeBuildAttr; + if (Context.getLangOpts().NoEnums) + EnumSizeBuildAttr = llvm::ARMBuildAttrs::EnumProhibited; + else if (Context.getLangOpts().ShortEnums) + EnumSizeBuildAttr = llvm::ARMBuildAttrs::EnumSmallest; + else if (Context.getLangOpts().ABIEnums) + EnumSizeBuildAttr = llvm::ARMBuildAttrs::Enum32BitABI; + else + EnumSizeBuildAttr = llvm::ARMBuildAttrs::Enum32Bit; + getModule().addModuleFlag(llvm::Module::Error, "enumsize_buildattr", + EnumSizeBuildAttr); } if (CodeGenOpts.SanitizeCfiCrossDso) { Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -5721,10 +5721,35 @@ RTTIMode == ToolChain::RM_DisabledImplicitly))) CmdArgs.push_back("-fno-rtti"); - // -fshort-enums=0 is default for all architectures except Hexagon. - if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums, - getToolChain().getArch() == llvm::Triple::hexagon)) + // -fshort-enums + bool ShortEnums = Args.hasFlag(options::OPT_fshort_enums, + options::OPT_fno_short_enums, false); + // -fabi-enums + bool ABIEnums = Args.hasFlag(options::OPT_fabi_enums, + options::OPT_fno_abi_enums, false); + + // The last of -fno-enums, -fshort-enums, -fabi-enums wins. + Arg *Enum; + if (ShortEnums && ABIEnums) + Enum = Args.getLastArg(options::OPT_fno_enums, options::OPT_fshort_enums, + options::OPT_fabi_enums); + else if (ShortEnums) + Enum = Args.getLastArg(options::OPT_fno_enums, options::OPT_fshort_enums); + else if (ABIEnums) + Enum = Args.getLastArg(options::OPT_fno_enums, options::OPT_fabi_enums); + else + Enum = Args.getLastArg(options::OPT_fno_enums); + if (Enum) { + if (Enum->getOption().matches(options::OPT_fno_enums)) + CmdArgs.push_back("-fno-enums"); + else if (Enum->getOption().matches(options::OPT_fshort_enums)) + CmdArgs.push_back("-fshort-enums"); + else if (Enum->getOption().matches(options::OPT_fabi_enums)) + CmdArgs.push_back("-fabi-enums"); + } else if (getToolChain().getArch() == llvm::Triple::hexagon) { + // -fshort-enums=0 is default for all architectures except Hexagon. CmdArgs.push_back("-fshort-enums"); + } // -fsigned-char is default. if (Arg *A = Args.getLastArg( Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1956,7 +1956,9 @@ Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char); Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar); Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false); + Opts.NoEnums = Args.hasArg(OPT_fno_enums); Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); + Opts.ABIEnums = Args.hasArg(OPT_fabi_enums); Opts.Freestanding = Args.hasArg(OPT_ffreestanding); Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; if (!Opts.NoBuiltin) Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -131,8 +131,11 @@ if (const EnumConstantDecl *ECD = dyn_cast(D)) if (Result == AR_Available) { const DeclContext *DC = ECD->getDeclContext(); - if (const EnumDecl *TheEnumDecl = dyn_cast(DC)) + if (const EnumDecl *TheEnumDecl = dyn_cast(DC)) { + if (getLangOpts().NoEnums) + Diag(TheEnumDecl->getLocation(), diag::err_enums_not_permitted); Result = TheEnumDecl->getAvailability(Message); + } } if (Result == AR_NotYetIntroduced) { Index: test/CodeGen/arm-metadata.c =================================================================== --- test/CodeGen/arm-metadata.c +++ test/CodeGen/arm-metadata.c @@ -1,12 +1,18 @@ // RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s | FileCheck -check-prefix=DEFAULT %s +// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fno-enums | FileCheck -check-prefix=NO-ENUM %s // RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fshort-enums | FileCheck -check-prefix=SHORT-ENUM %s +// RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fabi-enums | FileCheck -check-prefix=ABI-ENUM %s // RUN: %clang_cc1 -triple armv7a-linux-gnueabi -emit-llvm -o - %s -fshort-wchar | FileCheck -check-prefix=SHORT-WCHAR %s // DEFAULT: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 4} -// DEFAULT: !{{[0-9]+}} = !{i32 1, !"min_enum_size", i32 4} +// DEFAULT: !{{[0-9]+}} = !{i32 1, !"enumsize_buildattr", i32 2} // SHORT-WCHAR: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 2} -// SHORT-WCHAR: !{{[0-9]+}} = !{i32 1, !"min_enum_size", i32 4} +// SHORT-WCHAR: !{{[0-9]+}} = !{i32 1, !"enumsize_buildattr", i32 2} -// SHORT_ENUM: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 4} -// SHORT-ENUM: !{{[0-9]+}} = !{i32 1, !"min_enum_size", i32 1} +// NO-ENUM: !{{[0-9]+}} = !{i32 1, !"enumsize_buildattr", i32 0} + +// SHORT-ENUM: !{{[0-9]+}} = !{i32 1, !"wchar_size", i32 4} +// SHORT-ENUM: !{{[0-9]+}} = !{i32 1, !"enumsize_buildattr", i32 1} + +// ABI-ENUM: !{{[0-9]+}} = !{i32 1, !"enumsize_buildattr", i32 3} Index: test/Driver/clang_f_opts.c =================================================================== --- test/Driver/clang_f_opts.c +++ test/Driver/clang_f_opts.c @@ -447,6 +447,20 @@ // CHECK-NO-WARNING4-NOT: not supported // CHECK-NO-WARNING4-NOT: argument unused +// RUN: %clang -### -S -fno-enums %s 2>&1 | FileCheck -check-prefix=NOENUMS %s +// NOENUMS: -fno-enums + +// RUN: %clang -### -S -fshort-enums %s 2>&1 | FileCheck -check-prefix=SHORTENUMS %s +// SHORTENUMS: -fshort-enums + +// RUN: %clang -### -S -fabi-enums %s 2>&1 | FileCheck -check-prefix=ABIENUMS %s +// ABIENUMS: -fabi-enums + +// RUN: %clang -### -S -fshort-enums -fno-enums -fabi-enums -fno-abi-enums %s 2>&1 | FileCheck -check-prefix=ENUMS %s +// ENUMS: -fno-enums +// ENUMS-NOT: -fabi-enums +// ENUMS-NOT: -fshort-enums + // RUN: %clang -### -S -fsigned-char %s 2>&1 | FileCheck -check-prefix=CHAR-SIGN1 %s // CHAR-SIGN1-NOT: -fno-signed-char Index: test/Preprocessor/aarch64-target-features.c =================================================================== --- test/Preprocessor/aarch64-target-features.c +++ test/Preprocessor/aarch64-target-features.c @@ -35,7 +35,7 @@ // CHECK: __ARM_PCS_AAPCS64 1 // CHECK-NOT: __ARM_PCS 1 // CHECK-NOT: __ARM_PCS_VFP 1 -// CHECK-NOT: __ARM_SIZEOF_MINIMAL_ENUM 1 +// CHECK: __ARM_SIZEOF_MINIMAL_ENUM 4 // CHECK-NOT: __ARM_SIZEOF_WCHAR_T 2 // RUN: %clang -target aarch64_be-eabi -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-BIGENDIAN @@ -62,10 +62,18 @@ // RUN: %clang -target arm64-none-linux-gnu -fshort-wchar -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SHORTWCHAR %s // CHECK-SHORTWCHAR: __ARM_SIZEOF_WCHAR_T 2 +// RUN: %clang -target aarch64-none-linux-gnu -fno-enums -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-NOENUMS %s +// RUN: %clang -target arm64-none-linux-gnu -fno-enums -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-NOENUMS %s +// CHECK-NOENUMS-NOT: __ARM_SIZEOF_MINIMAL_ENUM + // RUN: %clang -target aarch64-none-linux-gnu -fshort-enums -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SHORTENUMS %s // RUN: %clang -target arm64-none-linux-gnu -fshort-enums -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SHORTENUMS %s // CHECK-SHORTENUMS: __ARM_SIZEOF_MINIMAL_ENUM 1 +// RUN: %clang -target aarch64-none-linux-gnu -fabi-enums -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ABIENUMS %s +// RUN: %clang -target arm64-none-linux-gnu -fabi-enums -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ABIENUMS %s +// CHECK-ABIENUMS: __ARM_SIZEOF_MINIMAL_ENUM 1 + // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+simd -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-NEON %s // RUN: %clang -target arm64-none-linux-gnu -march=armv8-a+simd -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-NEON %s // CHECK-NEON: __ARM_NEON 1 Index: test/Preprocessor/arm-target-features.c =================================================================== --- test/Preprocessor/arm-target-features.c +++ test/Preprocessor/arm-target-features.c @@ -134,9 +134,15 @@ // RUN: %clang -target arm-none-linux-gnu -fshort-wchar -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-SHORTWCHAR %s // CHECK-SHORTWCHAR:#define __ARM_SIZEOF_WCHAR_T 2 +// RUN: %clang -target arm-none-linux-gnu -fno-enums -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-NOENUMS %s +// CHECK-NOENUMS-NOT: __ARM_SIZEOF_MINIMAL_ENUM + // RUN: %clang -target arm-none-linux-gnu -fshort-enums -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-SHORTENUMS %s // CHECK-SHORTENUMS:#define __ARM_SIZEOF_MINIMAL_ENUM 1 +// RUN: %clang -target arm-none-linux-gnu -fabi-enums -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-ABIENUMS %s +// CHECK-ABIENUMS:#define __ARM_SIZEOF_MINIMAL_ENUM 1 + // Test that -mhwdiv has the right effect for a target CPU which has hwdiv enabled by default. // RUN: %clang -target armv7 -mcpu=cortex-a15 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=HWDIV %s // RUN: %clang -target armv7 -mthumb -mcpu=cortex-a15 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=HWDIV %s Index: test/Sema/no-enums.c =================================================================== --- /dev/null +++ test/Sema/no-enums.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple armv7-arm-none-eabi -fno-enums %s -verify +// RUN: %clang_cc1 -triple thumbv7-arm-none-eabi -fno-enums %s -verify +// RUN: %clang_cc1 -triple aarch64-arm-none-eabi -fno-enums %s -verify + +enum { foo } bar; // expected-error{{enumeration types are prohibited}} + +void InvalidUseofEnum() { bar = foo; }