labrinea created this revision.
labrinea added reviewers: cfe-commits, rengolin.
Herald added a subscriber: aemerson.

The ABI for the ARM architecture 
<http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045e/IHI0045E_ABI_addenda.pdf>
 describes four build attribute values for the size of enumeration types. 
Currently, Clang cannot instruct LLVM to emit the value 0 (use of enums is 
prohibited) and 3 (every enumeration visible across an ABI-complying interface
 contains a value needing 32 bits to encode). This patch adds the Driver flags 
'-fno-enums' and '-fabi-enums' to indicate the missing values. The build 
attribute values are passed to LLVM via metadata in the IR.


https://reviews.llvm.org/D26968

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/LangOptions.def
  include/clang/Driver/Options.td
  lib/Basic/Targets.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/Driver/Tools.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Sema/SemaExpr.cpp
  test/CodeGen/arm-metadata.c
  test/Driver/clang_f_opts.c
  test/Preprocessor/aarch64-target-features.c
  test/Preprocessor/arm-target-features.c
  test/Sema/no-enums.c

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; }
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/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/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/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: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -131,8 +131,11 @@
   if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
     if (Result == AR_Available) {
       const DeclContext *DC = ECD->getDeclContext();
-      if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC))
+      if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC)) {
+        if (getLangOpts().NoEnums)
+          Diag(TheEnumDecl->getLocation(), diag::err_enums_not_permitted);
         Result = TheEnumDecl->getAvailability(Message);
+      }
     }
 
   if (Result == AR_NotYetIntroduced) {
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/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/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/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: 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<f_Group>, Flags<[CC1Option]>,
   HelpText<"Disable generation of rtti information">;
 def fno_short_enums : Flag<["-"], "fno-short-enums">, Group<f_Group>;
+def fno_abi_enums : Flag<["-"], "fno-abi-enums">, Group<f_Group>;
 def fno_show_column : Flag<["-"], "fno-show-column">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Do not include column number on diagnostics">;
 def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group<f_Group>,
@@ -1165,8 +1166,12 @@
   HelpText<"Override the default ABI to return small structs in registers">;
 def frtti : Flag<["-"], "frtti">, Group<f_Group>;
 def : Flag<["-"], "fsched-interblock">, Group<clang_ignored_f_Group>;
+def fno_enums : Flag<["-"], "fno-enums">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Disable enumeration types">;
 def fshort_enums : Flag<["-"], "fshort-enums">, Group<f_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<f_Group>, Flags<[CC1Option]>,
+  HelpText<"All enums contain a value needing 32 bits to encode">;
 def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Force wchar_t to be a short unsigned int">;
 def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, Flags<[CC1Option]>,
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/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -368,6 +368,9 @@
           "field of %1">,
   InGroup<ShadowFieldInConstructorModified>, 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">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to