public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, RFC, C] Add -fno-float to forbid floating point data types
@ 2014-11-12 16:31 Thomas Preud'homme
  2014-11-12 22:13 ` Joseph Myers
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Preud'homme @ 2014-11-12 16:31 UTC (permalink / raw)
  To: gcc-patches

In several occasions (see [1][2] people requested a switch to tell GCC that a given compilation unit should not contain any float and that GCC should warn about any violation of this assumption. Such a switch would ensure that no softfloat library is going to be pulled in by the linker and would also allow to notify the linker that the resulting file is float ABI independent (a feature useful for [3]). A previous patch was posted here [4] and this patch tries to address all the comments that were done.

[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60070
[2] https://answers.launchpad.net/gcc-arm-embedded/+question/254345
[3] http://jira.arm.com/browse/GCC32RM-276
[4] https://gcc.gnu.org/ml/gcc-patches/2014-08/msg01099.html

This patch modifies the C parser to give an error if:
  - any variable or function parameter is declared with a float type or a type containing a float (prototype are ignored)
  - a cast is made with a float type or a type containing a float
  - a float litteral is encountered

This is a RFC, only the changes to the C frontend are implemented right now. Beside at least one bug still exist as using this option while compiling the kernel gives an ICE. I would like some feedback on the approach before proceeding further. Beside this approach I've considered doing this as a new pass. This would have the advantage of being frontend independent but doing it in the frontend means it can be done on the fly.

ChangeLog are as follows:

*** gcc/ChangeLog ***

2014-09-28  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * doc/invoke.texi (fno-float): Add to the list of C options and explain
        its meaning.


*** gcc/c/ChangeLog ***

2014-09-29  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * c-decl.c (declspecs_add_type): Set location for typedef, struct,
        union and enum typespecs.
        (finish_declspecs): Set location for complex as typespec.
        * c-parser.c (contains_floating_point_type): Forward declaration.
        (struct_contains_floating_point_type): New function.
        (prototype_contains_floating_point_type): Likewise.
        (contains_floating_point_type): Likewise.
        (c_parser_declaration_or_fndef): Throw an error if -fno-float is
        specified by user and a variable is declared of type float or of a
        type containing a float. Same for parameters of a function definition.
        (c_parser_cast_expression): Likewise for casts.
        (c_parser_postfix_expression): Throw an error if -fno-float is
        specified by user and a float litteral is found.
        (c_parser_postfix_expression): Throw an error if -fno-float is
        specified by user and a compound litteral or a va_arg is found with a
        float type or a type containing a float.


*** gcc/c-family/ChangeLog ***

2014-09-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * c-cppbuiltin.c (c_cpp_builtins): Define __GCC_NO_FLOAT when
        -fno-float is in effect.
        * c.opt (ffloat): New option.


*** gcc/testsuite/ChangeLog ***

2014-10-23  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * gcc.dg/fno-float.c: New testcase.
        * gcc.target/arm/fno-float-1.c: Likewise.

diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 7e2ae67..7457945 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1163,7 +1163,10 @@ c_cpp_builtins (cpp_reader *pfile)
     cpp_define (pfile, "__WCHAR_UNSIGNED__");
 
   cpp_atomic_builtins (pfile);
-    
+
+  if (flag_no_float)
+    cpp_define (pfile, "__GCC_NO_FLOAT");
+
 #ifdef DWARF2_UNWIND_INFO
   if (dwarf2out_do_cfi_asm ())
     cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 4f96cf8..b35ae21 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1122,6 +1122,10 @@ fnil-receivers
 ObjC ObjC++ Var(flag_nil_receivers) Init(1)
 Assume that receivers of Objective-C messages may be nil
 
+ffloat
+C LTO Var(flag_no_float, 0)
+Allow floating point data types to be used in C
+
 flocal-ivars
 ObjC ObjC++ Var(flag_local_ivars) Init(1)
 Allow access to instance variables as if they were local declarations within instance method implementations.
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index b18da48..459c24b 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -10009,7 +10009,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
 	  specs->decl_attr = DECL_ATTRIBUTES (type);
 	  specs->typedef_p = true;
 	  specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
-	  specs->locations[cdw_typedef] = loc;
+	  specs->locations[cdw_typespec] = specs->locations[cdw_typedef] = loc;
 
 	  /* If this typedef name is defined in a struct, then a C++
 	     lookup would return a different value.  */
@@ -10054,6 +10054,8 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
 	      specs->expr_const_operands &= spec.expr_const_operands;
 	    }
 	}
+      if (TREE_CODE (type) != ERROR_MARK)
+	specs->locations[cdw_typespec] = loc;
       specs->type = type;
     }
 
@@ -10256,6 +10258,7 @@ finish_declspecs (struct c_declspecs *specs)
       else if (specs->complex_p)
 	{
 	  specs->typespec_word = cts_double;
+	  specs->locations[cdw_typespec] = specs->locations[cdw_complex];
 	  pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
 		   "ISO C does not support plain %<complex%> meaning "
 		   "%<double complex%>");
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index fa146de..b00218a 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1122,6 +1122,57 @@ restore_extension_diagnostics (int flags)
   warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
 }
 
+static bool contains_floating_point_type (tree type);
+
+/* Return true if TYPE is a structure that contains a floating point data
+   type.  */
+
+static bool
+struct_contains_floating_point_type (tree type)
+{
+  tree fields;
+
+  for (fields = TYPE_FIELDS (type); fields; fields = DECL_CHAIN (fields))
+    if (contains_floating_point_type (TREE_TYPE (fields)))
+      return true;
+  return false;
+}
+
+/* Return true if TYPE is a prototype that contains a floating point data type
+   in its parameters.  */
+
+static bool
+prototype_contains_floating_point_type (tree fct_decl)
+{
+  tree parms;
+
+  if (contains_floating_point_type (TREE_TYPE (fct_decl)))
+    return true;
+
+  for (parms = TYPE_ARG_TYPES (fct_decl); parms; parms = TREE_CHAIN (parms))
+    if (contains_floating_point_type (TREE_VALUE (parms)))
+      return true;
+  return false;
+}
+
+/* Return true if TYPE is a type that contains a floating point data type.  */
+
+static bool
+contains_floating_point_type (tree type)
+{
+  if (FLOAT_TYPE_P (type))
+    return true;
+  else if (FUNCTION_POINTER_TYPE_P (type))
+    return prototype_contains_floating_point_type (TREE_TYPE (type));
+  else if (POINTER_TYPE_P (type))
+    return contains_floating_point_type (TREE_TYPE (type));
+  else if (TREE_CODE (type) == ARRAY_TYPE)
+    return contains_floating_point_type (TREE_TYPE (type));
+  else if (RECORD_OR_UNION_TYPE_P (type))
+    return struct_contains_floating_point_type (type);
+  return false;
+}
+
 /* Possibly kinds of declarator to parse.  */
 typedef enum c_dtr_syn {
   /* A normal declarator with an identifier.  */
@@ -1874,6 +1925,12 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	    }
 	  else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
 	    {
+	      /* Forbidden declaration of floating point variable.  */
+	      if (flag_no_float && declarator->kind != cdk_function
+		&& contains_floating_point_type (specs->type))
+		error_at (specs->locations[cdw_typespec],
+		  "use of floating point data types forbidden in this "
+		  "translation unit");
 	      c_parser_consume_token (parser);
 	      return;
 	    }
@@ -1913,6 +1970,21 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	  pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
 	  c_push_function_context ();
 	}
+      if (flag_no_float)
+	{
+	  tree parms;
+
+	  if (contains_floating_point_type (specs->type))
+	    error_at (specs->locations[cdw_typespec],
+		  "use of floating point data types forbidden in this "
+		  "translation unit");
+	  parms = (*declarator->u.arg_info).parms;
+	  for (; parms; parms = DECL_CHAIN (parms))
+	    if (contains_floating_point_type (TREE_TYPE (parms)))
+	      error_at (DECL_SOURCE_LOCATION (parms),
+			"use of floating point data types forbidden in this "
+			"translation unit");
+	}
       if (!start_function (specs, declarator, all_prefix_attrs))
 	{
 	  /* This can appear in many cases looking nothing like a
@@ -6352,6 +6424,12 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
 	  return ret;
 	}
 
+      if (flag_no_float && contains_floating_point_type
+				(type_name->specs->type))
+	error_at (type_name->specs->locations[cdw_typespec],
+		  "use of floating point data types forbidden in this "
+		  "translation unit");
+
       /* Save casted types in the function's used types hash table.  */
       used_types_insert (type_name->specs->type);
 
@@ -7024,6 +7102,9 @@ c_parser_postfix_expression (c_parser *parser)
 	  error_at (loc, "fixed-point types not supported for this target");
 	  expr.value = error_mark_node;
 	}
+      if (flag_no_float && TREE_CODE (expr.value) == REAL_CST)
+	error_at (loc, "use of floating point data types forbidden in this "
+		       "translation unit");
       break;
     case CPP_CHAR:
     case CPP_CHAR16:
@@ -7139,9 +7220,16 @@ c_parser_postfix_expression (c_parser *parser)
 	      expr.value = error_mark_node;
 	    }
 	  else
-	    expr = c_parser_postfix_expression_after_paren_type (parser,
-								 type_name,
-								 loc);
+	    {
+	      if (flag_no_float && contains_floating_point_type
+					(type_name->specs->type))
+		error_at (type_name->specs->locations[cdw_typespec],
+			  "use of floating point data types forbidden in this "
+			  "translation unit");
+	      expr = c_parser_postfix_expression_after_paren_type (parser,
+								   type_name,
+								   loc);
+	    }
 	}
       else
 	{
@@ -7211,6 +7299,11 @@ c_parser_postfix_expression (c_parser *parser)
 	  else
 	    {
 	      tree type_expr = NULL_TREE;
+	      if (flag_no_float && contains_floating_point_type
+					(t1->specs->type))
+		error_at (t1->specs->locations[cdw_typespec],
+			  "use of floating point data types forbidden in this "
+			  "translation unit");
 	      expr.value = c_build_va_arg (loc, e1.value,
 					   groktypename (t1, &type_expr, NULL));
 	      if (type_expr)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 23f272f..5564cfe 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -169,7 +169,7 @@ in the following sections.
 -aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
 -fno-asm  -fno-builtin  -fno-builtin-@var{function} @gol
 -fhosted  -ffreestanding -fopenmp -fopenmp-simd -fms-extensions @gol
--fplan9-extensions -trigraphs  -traditional  -traditional-cpp @gol
+-fno-float -fplan9-extensions -trigraphs  -traditional  -traditional-cpp @gol
 -fallow-single-precision  -fcond-mismatch -flax-vector-conversions @gol
 -fsigned-bitfields  -fsigned-char @gol
 -funsigned-bitfields  -funsigned-char}
@@ -1935,6 +1935,15 @@ fields within structs/unions}, for details.
 
 Note that this option is off for all targets but i?86 and x86_64
 targets using ms-abi.
+
+@item -fno-float
+@opindex fno-float
+Allows the compiler to assume that there is no floating point code in
+the translation unit, causing any use of floating point data types
+detected to be treated as an error.  Additional action can then be
+taken, such as marking the code unaffected by the choice of floating
+point ABI.
+
 @item -fplan9-extensions
 Accept some non-standard constructs used in Plan 9 code.
 
diff --git a/gcc/testsuite/gcc.dg/fno-float.c b/gcc/testsuite/gcc.dg/fno-float.c
new file mode 100644
index 0000000..312a204
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fno-float.c
@@ -0,0 +1,313 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-float" } */
+/* { dg-prune-output "decimal floating point not supported for this target" } */
+/* { dg-prune-output "'float' is promoted to 'double' when passed through '...'" } */
+
+/* Check macro definition.  */
+#ifndef __GCC_NO_FLOAT
+#error __GCC_NO_FLOAT macro not defined
+#endif
+
+
+/* Check float detection in struct fields declaration.  */
+struct fstruct {
+  float f; /* { dg-bogus "use of floating point data types forbidden" } */
+  double d; /* { dg-bogus "use of floating point data types forbidden" } */
+  long double ld; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Decimal32 d32; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Decimal64 d64; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Decimal128 d128; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Complex float cf; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Complex double cd; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Complex long double cld; /* { dg-bogus "use of floating point data types forbidden" } */
+
+  /* Check float detection of auto double complex in struct field declaration.  */
+  _Complex c; /* { dg-bogus "use of floating point data types forbidden" } */
+};
+
+/* Check float detection in union fields declaration.  */
+union funion {
+  float f; /* { dg-bogus "use of floating point data types forbidden" } */
+  double d; /* { dg-bogus "use of floating point data types forbidden" } */
+  long double ld; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Decimal32 d32; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Decimal64 d64; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Decimal128 d128; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Complex float cf; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Complex double cd; /* { dg-bogus "use of floating point data types forbidden" } */
+  _Complex long double cld; /* { dg-bogus "use of floating point data types forbidden" } */
+
+  /* Check float detection of auto double complex in union field declaration.  */
+  _Complex c; /* { dg-bogus "use of floating point data types forbidden" } */
+};
+
+struct fstructstruct {
+  struct fstruct fs; /* { dg-bogus "use of floating point data types forbidden" } */
+};
+
+struct funionstruct {
+  union funion fu; /* { dg-bogus "use of floating point data types forbidden" } */
+};
+
+union fstructunion {
+  struct fstruct fs; /* { dg-bogus "use of floating point data types forbidden" } */
+  union funion fu; /* { dg-bogus "use of floating point data types forbidden" } */
+};
+
+
+/* Check float detection in global declaration.  */
+float f_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+double d_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+long double ld_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+_Decimal32 d32_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+_Decimal64 d64_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+_Decimal128 d128_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+_Complex float cf_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+_Complex double cd_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+_Complex long double cld_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check float detection of auto double complex in global declaration.  */
+_Complex c_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check embedded float detection in global declaration.  */
+struct fstructstruct fss_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+struct funionstruct fus_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+union fstructunion fsu_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+
+
+/* Check float detection in typeof with typename.  */
+typeof (float) f_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (double) d_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (long double) ld_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (_Decimal32) d32_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (_Decimal64) d64_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (_Decimal128) d128_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (_Complex float) cf_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (_Complex double) cd_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (_Complex long double) cld_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check float detection of auto double complex in typeof with typename.  */
+typeof (_Complex) c_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check embedded float detection in typeof with typename.  */
+typeof (struct fstructstruct) fss_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (struct funionstruct) fus_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+typeof (union fstructunion) fsu_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+
+
+/* Check float detection in typeof with variable.  */
+typeof (f_glob_2) f_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (d_glob_2) d_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (ld_glob_2) ld_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (d32_glob_2) d32_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (d64_glob_2) d64_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (d128_glob_2) d128_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (cf_glob_2) cf_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (cd_glob_2) cd_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (cld_glob_2) cld_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check float detection of auto double complex in typeof with variable.  */
+typeof (c_glob_2) c_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check embedded float detection in typeof with variable.  */
+typeof (fss_glob_2) fss_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (fus_glob_2) fus_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+typeof (fsu_glob_2) fsu_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+
+
+int
+f (int n, ...)
+{
+  __builtin_va_list ap;
+
+  /* Check float detection in local declaration.  */
+  float f; /* { dg-error "use of floating point data types forbidden" } */
+  double d; /* { dg-error "use of floating point data types forbidden" } */
+  long double ld; /* { dg-error "use of floating point data types forbidden" } */
+  _Decimal32 d32; /* { dg-error "use of floating point data types forbidden" } */
+  _Decimal64 d64; /* { dg-error "use of floating point data types forbidden" } */
+  _Decimal128 d128; /* { dg-error "use of floating point data types forbidden" } */
+  _Complex float cf; /* { dg-error "use of floating point data types forbidden" } */
+  _Complex double cd; /* { dg-error "use of floating point data types forbidden" } */
+  _Complex long double cld; /* { dg-error "use of floating point data types forbidden" } */
+
+  /* Check float detection of auto double complex in local declaration.  */
+  _Complex c; /* { dg-error "use of floating point data types forbidden" } */
+
+  /* Check embedded float detection in typeof with variable.  */
+  struct fstructstruct fss; /* { dg-error "use of floating point data types forbidden" } */
+  struct funionstruct fus; /* { dg-error "use of floating point data types forbidden" } */
+  union fstructunion fsu; /* { dg-error "use of floating point data types forbidden" } */
+
+
+  __builtin_va_start (ap, n);
+
+
+  /* Check float detection in cast.  */
+  f = (float) 4; /* { dg-error "use of floating point data types forbidden" } */
+  d = (double) 4; /* { dg-error "use of floating point data types forbidden" } */
+  ld = (long double) 4; /* { dg-error "use of floating point data types forbidden" } */
+  d32 = (_Decimal32) 4; /* { dg-error "use of floating point data types forbidden" } */
+  d64 = (_Decimal64) 4; /* { dg-error "use of floating point data types forbidden" } */
+  d128 = (_Decimal128) 4; /* { dg-error "use of floating point data types forbidden" } */
+  cf = (_Complex float) cf_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+  cd = (_Complex double) cd_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+  cld = (_Complex long double) cld_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+
+  /* Check float detection of auto double complex in cast.  */
+  c = (_Complex) cf; /* { dg-error "use of floating point data types forbidden" } */
+
+  /* Check embedded float detection in cast.  */
+  fss = (struct fstructstruct) fss_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+  fus = (struct funionstruct) fus_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+  fsu = (union fstructunion) fsu_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+
+
+  {
+    /* Check float detection in local declaration within block.  */
+    float f; /* { dg-error "use of floating point data types forbidden" } */
+    double d; /* { dg-error "use of floating point data types forbidden" } */
+    long double ld; /* { dg-error "use of floating point data types forbidden" } */
+    _Decimal32 d32; /* { dg-error "use of floating point data types forbidden" } */
+    _Decimal64 d64; /* { dg-error "use of floating point data types forbidden" } */
+    _Decimal128 d128; /* { dg-error "use of floating point data types forbidden" } */
+    _Complex float cf; /* { dg-error "use of floating point data types forbidden" } */
+    _Complex double cd; /* { dg-error "use of floating point data types forbidden" } */
+    _Complex long double cld; /* { dg-error "use of floating point data types forbidden" } */
+
+    /* Check float detection of auto double complex in local declaration within block.  */
+    _Complex c; /* { dg-error "use of floating point data types forbidden" } */
+
+    /* Check embedded float detection in typeof with variable within block.  */
+    struct fstructstruct fss; /* { dg-error "use of floating point data types forbidden" } */
+    struct funionstruct fus; /* { dg-error "use of floating point data types forbidden" } */
+    union fstructunion fsu; /* { dg-error "use of floating point data types forbidden" } */
+
+
+    /* Check float detection in compound litterals.  */
+    f = (float) {4}; /* { dg-error "use of floating point data types forbidden" } */
+    d = (double) {4}; /* { dg-error "use of floating point data types forbidden" } */
+    ld = (long double) {4}; /* { dg-error "use of floating point data types forbidden" } */
+    d32 = (_Decimal32) {4}; /* { dg-error "use of floating point data types forbidden" } */
+    d64 = (_Decimal64) {4}; /* { dg-error "use of floating point data types forbidden" } */
+    d128 = (_Decimal128) {4}; /* { dg-error "use of floating point data types forbidden" } */
+    cf = (_Complex float) {4}; /* { dg-error "use of floating point data types forbidden" } */
+    cd = (_Complex double) {4}; /* { dg-error "use of floating point data types forbidden" } */
+    cld = (_Complex long double) {4}; /* { dg-error "use of floating point data types forbidden" } */
+
+    /* Check float detection of auto double complex in compound litterals.  */
+    c = (_Complex) {4}; /* { dg-error "use of floating point data types forbidden" } */
+
+    /* Check embedded float detection in compound litterals.  */
+    fss = (struct fstructstruct) {fss_glob_1.fs}; /* { dg-error "use of floating point data types forbidden" } */
+    fus = (struct funionstruct) {fus_glob_1.fu}; /* { dg-error "use of floating point data types forbidden" } */
+    fsu = (union fstructunion) {fsu_glob_1.fs}; /* { dg-error "use of floating point data types forbidden" } */
+  }
+
+
+  /* Check float detection in va_arg.  */
+  f = __builtin_va_arg (ap, float); /* { dg-error "use of floating point data types forbidden" } */
+  d = __builtin_va_arg (ap, double); /* { dg-error "use of floating point data types forbidden" } */
+  ld = __builtin_va_arg (ap, long double); /* { dg-error "use of floating point data types forbidden" } */
+  d32 = __builtin_va_arg (ap, _Decimal32); /* { dg-error "use of floating point data types forbidden" } */
+  d64 = __builtin_va_arg (ap, _Decimal64); /* { dg-error "use of floating point data types forbidden" } */
+  d128 = __builtin_va_arg (ap, _Decimal128); /* { dg-error "use of floating point data types forbidden" } */
+  cf = __builtin_va_arg (ap, _Complex float); /* { dg-error "use of floating point data types forbidden" } */
+  cd = __builtin_va_arg (ap, _Complex double); /* { dg-error "use of floating point data types forbidden" } */
+  cld = __builtin_va_arg (ap, _Complex long double); /* { dg-error "use of floating point data types forbidden" } */
+
+  /* Check float detection of auto double complex in va_arg.  */
+  c = __builtin_va_arg (ap, _Complex); /* { dg-error "use of floating point data types forbidden" } */
+
+  /* Check embedded float detection in va_arg.  */
+  fss = __builtin_va_arg (ap, struct fstructstruct); /* { dg-error "use of floating point data types forbidden" } */
+  fus = __builtin_va_arg (ap, struct funionstruct); /* { dg-error "use of floating point data types forbidden" } */
+  fsu = __builtin_va_arg (ap, union fstructunion); /* { dg-error "use of floating point data types forbidden" } */
+
+
+  __builtin_va_end (ap);
+
+
+  /* Check float detection in litterals.  */
+  return (int) 4.5; /* { dg-error "use of floating point data types forbidden" } */
+}
+
+
+/* Check float detection in function parameter.  */
+int float_param (float a) { return (int) a;} /* { dg-error "use of floating point data types forbidden" } */
+int double_param (double a) { return (int) a;} /* { dg-error "use of floating point data types forbidden" } */
+int long_double_param (long double a) { return (int) a;} /* { dg-error "use of floating point data types forbidden" } */
+int decimal32_param (_Decimal32 a) { return (int) a;} /* { dg-error "use of floating point data types forbidden" } */
+int decimal64_param (_Decimal64 a) { return (int) a;} /* { dg-error "use of floating point data types forbidden" } */
+int decimal128_param (_Decimal128 a) { return (int) a;} /* { dg-error "use of floating point data types forbidden" } */
+int complex_float_param (_Complex float a) { return (int) __real__ a;} /* { dg-error "use of floating point data types forbidden" } */
+int complex_double_param (_Complex double a) { return (int) __real__ a;} /* { dg-error "use of floating point data types forbidden" } */
+int complex_long_double_param (_Complex long double a) { return (int) __real__ a;} /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check float detection of auto double complex in function parameter.  */
+int complex_param (_Complex a) { return (int) __real__ a;} /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check embedded float detection in function parameter.  */
+int float_struct_struct_param (struct fstructstruct a) {return (int) a.fs.f;}; /* { dg-error "use of floating point data types forbidden" } */
+int float_union_struct_param (struct funionstruct a) {return (int) a.fu.f;}; /* { dg-error "use of floating point data types forbidden" } */
+int float_struct_union_param (union fstructunion a) {return (int) a.fs.f;}; /* { dg-error "use of floating point data types forbidden" } */
+
+
+/* Check float detection in function return parameter.  */
+float float_return (void) { return f_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+double double_return (void) { return d_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+long double long_double_return (void) { return ld_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+_Decimal32 decimal32_return (void) { return f_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+_Decimal64 decimal64_return (void) { return f_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+_Decimal128 decimal128_return (void) { return f_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+_Complex float complex_float_return (void) { return cf_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+_Complex double complex_double_return (void) { return cd_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+_Complex long double complex_long_double_return (void) { return cld_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check float detection of auto double complex in function return parameter.  */
+_Complex complex_return (void) { return c_glob_1;} /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check embedded float detection in function return parameter.  */
+struct fstructstruct float_struct_struct_return (void) {return fss_glob_1;}; /* { dg-error "use of floating point data types forbidden" } */
+struct funionstruct float_union_struct_return (void) {return fus_glob_1;}; /* { dg-error "use of floating point data types forbidden" } */
+union fstructunion float_struct_union_return (void) {return fsu_glob_1;}; /* { dg-error "use of floating point data types forbidden" } */
+
+
+/* Check float detection in function prototype parameter.  */
+int float_param (float a); /* { dg-bogus "use of floating point data types forbidden" } */
+int double_param (double a); /* { dg-bogus "use of floating point data types forbidden" } */
+int long_double_param (long double a); /* { dg-bogus "use of floating point data types forbidden" } */
+int decimal32_param (_Decimal32 a); /* { dg-bogus "use of floating point data types forbidden" } */
+int decimal64_param (_Decimal64 a); /* { dg-bogus "use of floating point data types forbidden" } */
+int decimal128_param (_Decimal128 a); /* { dg-bogus "use of floating point data types forbidden" } */
+int complex_float_param (_Complex float a); /* { dg-bogus "use of floating point data types forbidden" } */
+int complex_double_param (_Complex double a); /* { dg-bogus "use of floating point data types forbidden" } */
+int complex_long_double_param (_Complex long double a); /* { dg-bogus "use of floating point data types forbidden" } */
+
+/* Check float detection of auto double complex in function prototype parameter.  */
+int complex_param (_Complex a); /* { dg-bogus "use of floating point data types forbidden" } */
+
+/* Check embedded float detection in function prototype parameter.  */
+int float_struct_struct_param (struct fstructstruct a); /* { dg-bogus "use of floating point data types forbidden" } */
+int float_union_struct_param (struct funionstruct a); /* { dg-bogus "use of floating point data types forbidden" } */
+int float_struct_union_param (union fstructunion a); /* { dg-bogus "use of floating point data types forbidden" } */
+
+
+/* Check float detection in function prototype return parameter.  */
+float float_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+double double_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+long double long_double_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+_Decimal32 decimal32_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+_Decimal64 decimal64_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+_Decimal128 decimal128_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+_Complex float complex_float_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+_Complex double complex_double_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+_Complex long double complex_long_double_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+
+/* Check float detection of auto double complex in function prototype return parameter.  */
+_Complex complex_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+
+/* Check embedded float detection in function prototype return parameter.  */
+struct fstructstruct float_struct_struct_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+struct funionstruct float_union_struct_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
+union fstructunion float_struct_union_return (void); /* { dg-bogus "use of floating point data types forbidden" } */
diff --git a/gcc/testsuite/gcc.target/arm/fno-float-1.c b/gcc/testsuite/gcc.target/arm/fno-float-1.c
new file mode 100644
index 0000000..3460bbf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/fno-float-1.c
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-float -mfp16-format=alternative" } */
+/* { dg-add-options "arm_neon_fp16" } */
+
+/* Check float detection in struct fields declaration.  */
+struct fstruct {
+  /* Check float detection of builtin typedef in struct field declaration.  */
+  __fp16 fp16; /* { dg-bogus "use of floating point data types forbidden" } */
+};
+
+/* Check float detection in union fields declaration.  */
+union funion {
+  /* Check float detection of builtin typedef in union field declaration.  */
+  __fp16 fp16; /* { dg-bogus "use of floating point data types forbidden" } */
+};
+
+/* Check float detection of builtin typedef in global declaration.  */
+  __fp16 fp16_glob_1; /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check float detection of builtin typedef in typeof with typename.  */
+typeof (__fp16) fp16_glob_2; /* { dg-error "use of floating point data types forbidden" } */
+
+/* Check float detection of builtin typedef in typeof with variable.  */
+typeof (fp16_glob_2) fp16_glob_3; /* { dg-error "use of floating point data types forbidden" } */
+
+int
+f (int n, ...)
+{
+  __builtin_va_list ap;
+
+  /* Check float detection of builtin typedef in local declaration.  */
+  __fp16 fp16; /* { dg-error "use of floating point data types forbidden" } */
+
+  __builtin_va_start (ap, n);
+
+
+  /* Check float detection of builtin typedef in cast.  */
+  fp16 = (__fp16) 4; /* { dg-error "use of floating point data types forbidden" } */
+
+  {
+    /* Check float detection of builtin typedef in local declaration within block.  */
+    __fp16 fp16; /* { dg-error "use of floating point data types forbidden" } */
+
+    /* Check float detection of builtin typedef in compound litterals.  */
+    fp16 = (__fp16) {4}; /* { dg-error "use of floating point data types forbidden" } */
+  }
+
+  /* Check float detection of builtin typedef in va_arg.  */
+  fp16 = __builtin_va_arg (ap, __fp16); /* { dg-error "use of floating point data types forbidden" } */
+
+  __builtin_va_end (ap);
+
+  /* Check float detection in litterals.  */
+  return 4;
+}
+
+/* Function parameters cannot have __fp16 type.  */
+
+/* Functions cannot return __fp16 type.  */
+
+/* Function parameters cannot have __fp16 type.  */
+
+/* Functions cannot return __fp16 type.  */


Comments much welcome.

Best regards,

Thomas



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH, RFC, C] Add -fno-float to forbid floating point data types
  2014-11-12 16:31 [PATCH, RFC, C] Add -fno-float to forbid floating point data types Thomas Preud'homme
@ 2014-11-12 22:13 ` Joseph Myers
  2014-11-13  8:57   ` Thomas Preud'homme
  0 siblings, 1 reply; 5+ messages in thread
From: Joseph Myers @ 2014-11-12 22:13 UTC (permalink / raw)
  To: Thomas Preud'homme; +Cc: gcc-patches

On Wed, 12 Nov 2014, Thomas Preud'homme wrote:

> In several occasions (see [1][2] people requested a switch to tell GCC 
> that a given compilation unit should not contain any float and that GCC 
> should warn about any violation of this assumption. Such a switch would 
> ensure that no softfloat library is going to be pulled in by the linker 
> and would also allow to notify the linker that the resulting file is 
> float ABI independent (a feature useful for [3]). A previous patch was 
> posted here [4] and this patch tries to address all the comments that 
> were done.
> 
> [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60070
> [2] https://answers.launchpad.net/gcc-arm-embedded/+question/254345
> [3] http://jira.arm.com/browse/GCC32RM-276
> [4] https://gcc.gnu.org/ml/gcc-patches/2014-08/msg01099.html
> 
> This patch modifies the C parser to give an error if:
>   - any variable or function parameter is declared with a float type or 
> a type containing a float (prototype are ignored)

But if you ignore prototypes at the time of declaration, don't you need to 
diagnose if a function with a floating-point parameter or return type gets 
called?  I don't see anything to do that.  (This includes the 
__builtin_sqrt case from the previous discussion.)

>         specified by user and a float litteral is found.

"literal" (throughout).

> @@ -1874,6 +1925,12 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
>  	    }
>  	  else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
>  	    {
> +	      /* Forbidden declaration of floating point variable.  */
> +	      if (flag_no_float && declarator->kind != cdk_function
> +		&& contains_floating_point_type (specs->type))
> +		error_at (specs->locations[cdw_typespec],
> +		  "use of floating point data types forbidden in this "
> +		  "translation unit");
>  	      c_parser_consume_token (parser);
>  	      return;
>  	    }

No, this is wrong.  (a) By tying this to CPP_SEMICOLON you'll only catch 
it if the variable is last in the list of declarators (consider "float f, 
g (void);", where what comes before the semicolon is a function 
declaration); better to check on each declarator, not just the last.  (b) 
declarator->kind reflects the outermost declarator, but what determines 
whether it's a function declaration is the innermost declarator (other 
than cdk_id or cdk_attrs declarators), so this looks like it would give an 
error for "float *f(void);" (wrongly treating it as a variable because the 
outermost declarator is cdk_pointer), but not for "float (*f)(void);" 
(wrongly treating it as a function because the outermost declarator is 
cdk_function ... you could of course decide that function pointers 
involving floating-point types are OK if you want).  (c) specs->type only 
covers the type specifiers, so if you want to diagnose function pointer 
variables you need to allow for "int (*f)(float);" where the declaration's 
type involves floating point but the type specifiers don't.  (d) What do 
you want to do with typedef declarations (right now it looks like they'll 
be handled as variables, but your testcases don't consider them)?

I'd also suggest some refactoring: have a function that takes as arguments 
a location and a type, and does the

if (flag_no_float && contains_floating_point_type (type))
  error_at (loc, ...);

to avoid repeating that pattern in several places.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH, RFC, C] Add -fno-float to forbid floating point data types
  2014-11-12 22:13 ` Joseph Myers
@ 2014-11-13  8:57   ` Thomas Preud'homme
  2014-11-13 21:33     ` Joseph Myers
  0 siblings, 1 reply; 5+ messages in thread
From: Thomas Preud'homme @ 2014-11-13  8:57 UTC (permalink / raw)
  To: 'Joseph Myers'; +Cc: gcc-patches

> From: Joseph Myers [mailto:joseph@codesourcery.com]
> Sent: Wednesday, November 12, 2014 10:11 PM
> >
> > This patch modifies the C parser to give an error if:
> >   - any variable or function parameter is declared with a float type or
> > a type containing a float (prototype are ignored)
> 
> But if you ignore prototypes at the time of declaration, don't you need to
> diagnose if a function with a floating-point parameter or return type gets
> called?  I don't see anything to do that.  (This includes the
> __builtin_sqrt case from the previous discussion.)

It would work by transitivity. To call a function with a float you'd have to
either declare a float variable or pass it a float literal.

> 
> >         specified by user and a float litteral is found.
> 
> "literal" (throughout).

Thanks. You'll have guessed that I'm not a native English speaker.

> 
> No, this is wrong.  (a) By tying this to CPP_SEMICOLON you'll only catch
> it if the variable is last in the list of declarators (consider "float f,
> g (void);", where what comes before the semicolon is a function
> declaration); better to check on each declarator, not just the last.

Indeed. I meant to do that at some point and I forgot about it.

> (b)
> declarator->kind reflects the outermost declarator, but what determines
> whether it's a function declaration is the innermost declarator (other
> than cdk_id or cdk_attrs declarators), so this looks like it would give an
> error for "float *f(void);" (wrongly treating it as a variable because the
> outermost declarator is cdk_pointer), but not for "float (*f)(void);"
> (wrongly treating it as a function because the outermost declarator is
> cdk_function ... you could of course decide that function pointers
> involving floating-point types are OK if you want). 

I see. I must say it's the first time I look at any GCC frontend so I missed
this important bit.

(c) specs->type only
> covers the type specifiers, so if you want to diagnose function pointer
> variables you need to allow for "int (*f)(float);" where the declaration's
> type involves floating point but the type specifiers don't.

Ok.

(d) What do
> you want to do with typedef declarations (right now it looks like they'll
> be handled as variables, but your testcases don't consider them)?

Because typedef can be used in header, these types should be dealt when
actually used, so at declaration type like the rest. I'll make sure to add some
testcase for this.

> 
> I'd also suggest some refactoring: have a function that takes as
> arguments
> a location and a type, and does the
> 
> if (flag_no_float && contains_floating_point_type (type))
>   error_at (loc, ...);
> 
> to avoid repeating that pattern in several places.

Right.

Thanks a lot for the review. Except on the patch itself, what do you think of
the general approach? Do you think doing this in the frontend is the right
approach?

Best regards,

Thomas 




^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH, RFC, C] Add -fno-float to forbid floating point data types
  2014-11-13  8:57   ` Thomas Preud'homme
@ 2014-11-13 21:33     ` Joseph Myers
  2014-11-14  1:12       ` Jeff Law
  0 siblings, 1 reply; 5+ messages in thread
From: Joseph Myers @ 2014-11-13 21:33 UTC (permalink / raw)
  To: Thomas Preud'homme; +Cc: gcc-patches

On Thu, 13 Nov 2014, Thomas Preud'homme wrote:

> > From: Joseph Myers [mailto:joseph@codesourcery.com]
> > Sent: Wednesday, November 12, 2014 10:11 PM
> > >
> > > This patch modifies the C parser to give an error if:
> > >   - any variable or function parameter is declared with a float type or
> > > a type containing a float (prototype are ignored)
> > 
> > But if you ignore prototypes at the time of declaration, don't you need to
> > diagnose if a function with a floating-point parameter or return type gets
> > called?  I don't see anything to do that.  (This includes the
> > __builtin_sqrt case from the previous discussion.)
> 
> It would work by transitivity. To call a function with a float you'd have to
> either declare a float variable or pass it a float literal.

Or pass in an integer value, which gets implicitly converted to floating 
point because of the prototype.  Detecting that case requires checking 
calls.

> Thanks a lot for the review. Except on the patch itself, what do you think of
> the general approach? Do you think doing this in the frontend is the right
> approach?

If you want to define a language subset, where it is predictable what is 
accepted, then doing it in the front end is right.

If you want to accept as much code as possible and only give errors if 
floating-point code would actually be generated - for example, if you want 
to be able to #include <stdlib.h> with glibc (where it defines an inline 
version of atof) - then you need to look at GIMPLE after optimization, 
taking into account which functions will actually be output so as to 
ignore unused inline functions.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH, RFC, C] Add -fno-float to forbid floating point data types
  2014-11-13 21:33     ` Joseph Myers
@ 2014-11-14  1:12       ` Jeff Law
  0 siblings, 0 replies; 5+ messages in thread
From: Jeff Law @ 2014-11-14  1:12 UTC (permalink / raw)
  To: Joseph Myers, Thomas Preud'homme; +Cc: gcc-patches

On 11/13/14 14:01, Joseph Myers wrote:
>
> If you want to accept as much code as possible and only give errors if
> floating-point code would actually be generated - for example, if you want
> to be able to #include <stdlib.h> with glibc (where it defines an inline
> version of atof) - then you need to look at GIMPLE after optimization,
> taking into account which functions will actually be output so as to
> ignore unused inline functions.
When presented with related issues in the past (FP instructions showing 
up in kernel code where we had declared them strictly verboten), we've 
added options to disable the entire FP register file on the target.

So the only time we got a compile-time error was if some FP bits 
survived all the way through to register allocation.

The obvious downside is it has to be done on a per-target basis and 
there's no standardized set of options.

jeff

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-11-14  1:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-12 16:31 [PATCH, RFC, C] Add -fno-float to forbid floating point data types Thomas Preud'homme
2014-11-12 22:13 ` Joseph Myers
2014-11-13  8:57   ` Thomas Preud'homme
2014-11-13 21:33     ` Joseph Myers
2014-11-14  1:12       ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).