[PATCH] take 3: pragma FLOAT_CONST_DECIMAL64 for decimal float support

Janis Johnson janis187@us.ibm.com
Wed May 6 17:54:00 GMT 2009


On Sun, 2009-03-22 at 16:21 +0000, Joseph S. Myers wrote:

I got distracted by other work, but here's a new patch that addresses
concerns brought up in the last review.  I expect to go back and make
more changes until I get it right.

Previous submission:
http://gcc.gnu.org/ml/gcc-patches/2009-03/msg00826.html

> On Tue, 17 Mar 2009, Janis Johnson wrote:
> 
> >   - Disallow unsuffixed hex and imaginary constants when the pragma is
> >     in effect.
> 
> Disallowing otherwise unsuffixed decimal imaginary constants seems 
> plausible (but I'm not sure it's a good idea; it would prevent using 
> <complex.h>'s definition of _Complex_I using 1.0iF, for example), but for 
> unsuffixed hex constants I'd think it would be natural to follow N1369 and 
> allow them as double.

In this version, pragma FLOAT_CONST_DECIMAL64 does not affect imaginary
and hex constants.

> > Index: gcc/c-cppbuiltin.c
> > ===================================================================
> > --- gcc/c-cppbuiltin.c	(revision 144896)
> > +++ gcc/c-cppbuiltin.c	(working copy)
> > @@ -626,7 +626,7 @@ c_cpp_builtins (cpp_reader *pfile)
> >    if (flag_single_precision_constant)
> >      builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
> >    else
> > -    builtin_define_float_constants ("DBL", "", "%s", double_type_node);
> > +    builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
> 
> The effect of this is to use the new definition unconditionally, in which 
> case you should remove the if and insert a comment explaining the use 
> cases (-fsingle-precision-constant and this pragma) needing the definition 
> as long double and the cast.

Fixed.

The comment says that the cast prevents the predefined macros from being
used in const expressions; if that's a problem we might just leave this
part out and force code that uses these macros to do so within code
blocks that turn off the pragma.

> > +/* Warn about float constants without suffixes.  */
> > +
> > +extern int warn_unsuffixed_float_consts;
> 
> Is this actually needed when the c.opt entry should cause an automatically 
> generated declaration?

No, it isn't, and now it's gone.

> > +	warning (OPT_Wunknown_pragmas,
> > +		 "%<#pragma STDC_FLOAT_CONST_DECIMAL64%> is not supported"
>                                 ^ stray underscore here
> 
> > +	warning (OPT_Wunknown_pragmas,
> > +		 "%<#pragma STDC_FLOAT_CONST_DECIMAL64%> is not supported"
>                                 ^ likewise

Fixed.

> > +Wunsuffixed-float-constants
> > +C ObjC Var(warn_unsuffixed_float_constants) Warning
> > +Warn about unsuffixed float constants
> 
> > +    case OPT_Wunsuffixed_float_constants:
> > +      warn_unsuffixed_float_consts = value;
> > +      break;
> 
> Do you actually need this code, when you used Var in the option definition 
> above?

No, and now it's gone.

> You set current_scope->valid_for_stdc_pragma = false when processing 
> declaration specifiers, but I don't see anything to do so when processing 
> a statement in a scope with no declarations.  Also, do you require the 
> pragmas to come before __label__ declarations?  It would seem natural to 
> do so; either way, a testcase is needed.

The changes to figure out where the pragmas as valid has changed
completely.  There are many more checks in
pragma-float-const-decimal64-8.c, including one after a label.
Oops, there's not one for __label__, I'll look into adding that.

> As I understand it, you are implementing these as non-deferred pragmas 
> which will be handled as soon as the preprocessor lexes them.  Given that 
> I'd expect that as soon as c_parser_compound_statement_nostart looks at 
> the next token, any of these pragmas before that token will be handled.  
> And so the right place to set current_scope->valid_for_stdc_pragma = false 
> would be in c_parser_compound_statement_nostart immediately after we've 
> found the compound statement isn't empty.  Certainly putting the code in 
> that function seems more reliable than basing it on addition of 
> declaration specifiers.  In your test of invalid locations, I think the 
> second pragma it toplevel is OK; it's outside external declarations, and 
> having pragmas between two such declarations is OK.  You do however need 
> to avoid the pragma being in a random place inside an external 
> declaration, e.g. inside a struct definition.  I suppose that 
> c_parser_translation_unit should clear the flag before calling 
> c_parser_external_declaration and set it afterwards (the pragmas outside 
> external declarations would be handled each time it checks if the next 
> token is CPP_EOF).

Outside of a function body, STDC pragmas are now allowed where external
declarations are allowed, but not within a struct or union definition.
It gets a little messier within a function or block, but those checks
are all within c_parser_compound_statement_nostart.

Tested on powerpc64-linux with bootstrap of all languages but Ada,
testing with -m32 and -m64.  OK for trunk?

2009-05-06  Janis Johnson  <janis187@us.ibm.com>

gcc/
	PR c/39037
	* c-common.h (mark_valid_location_for_stdc_pragma,
	valid_location_for_stdc_pragma_p, set_float_const_decimal64,
	clear_float_const_decimal64, float_const_decimal64_p): New.
	* c-common.c (warn_unsuffixed_float_consts): New.
	* c.opt (Wunsuffixed-float-constants): New.
	* c-lex.c (interpret_float): Use pragma FLOAT_CONST_DECIMAL64 for
	unsuffixed float constant, handle new warning.
	* c-cppbuiltin.c (c_cpp_builtins): Use cast for double constants.
	* c-decl.c (c_scope): New flag float_const_decimal64.
	(set_float_const_decimal64, clear_float_const_decimal64,
	float_const_decimal64_p): New.
	(push_scope): Set new flag.
	* c-parser.c (c_parser_translation_unit): Mark when it's valid
	to use STDC pragmas.
	(c_parser_declspecs): Ditto.
	(c_parser_compound_statement_nostart): Ditto.
	* c-pragma.c (valid_location_for_stdc_pragma,
	mark_valid_location_for_stdc_pragma,
	valid_location_for_stdc_pragma_p, handle_stdc_pragma,
	handle_pragma_float_const_decimal64): New.
	(init_pragma): Register new pragma FLOAT_CONST_DECIMAL64.
	* cp/semantics.c (valid_location_for_stdc_pragma_p,
	set_float_const_decimal64, clear_float_const_decimal64,
	float_const_decimal64_p): New dummy functions.
	* doc/invoke.texi (Decimal FLoat): Remove statement that the
	pragma, and suffix for double constants, are not supported.
	* doc/extend.texi (-Wunsuffixed-float-constants): New.

gcc/testsuite
	PR c/39037
	* gcc.dg/Wunsuffixed-float-constants-1.c: New test.
	* gcc.dg/cpp/pragma-float-const-decimal64-1.c: New test.
	* gcc.dg/dfp/float-constant-double.c: New test.
	* gcc.dg/dfp/pragma-float-const-decimal64-1.c: New test.
	* gcc.dg/dfp/pragma-float-const-decimal64-2.c: New test.
	* gcc.dg/dfp/pragma-float-const-decimal64-3.c: New test.
	* gcc.dg/dfp/pragma-float-const-decimal64-4.c: New test.
	* gcc.dg/dfp/pragma-float-const-decimal64-5.c: New test.
	* gcc.dg/dfp/pragma-float-const-decimal64-6.c: New test.
	* gcc.dg/dfp/pragma-float-const-decimal64-7.c: New test.
	* gcc.dg/dfp/pragma-float-const-decimal64-8.c: New test.
	* g++.dg/cpp/pragma-float-const-decimal64-1.C: New test.

Index: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 147110)
+++ gcc/c-common.h	(working copy)
@@ -809,6 +809,11 @@ extern void warn_logical_operator (locat
 extern void check_main_parameter_types (tree decl);
 extern bool c_determine_visibility (tree);
 extern bool same_scalar_type_ignoring_signedness (tree, tree);
+extern void mark_valid_location_for_stdc_pragma (bool);
+extern bool valid_location_for_stdc_pragma_p (void);
+extern void set_float_const_decimal64 (void);
+extern void clear_float_const_decimal64 (void);
+extern bool float_const_decimal64_p (void);
 
 #define c_sizeof(T)  c_sizeof_or_alignof_type (T, true, 1)
 #define c_alignof(T) c_sizeof_or_alignof_type (T, false, 1)
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 147110)
+++ gcc/c-common.c	(working copy)
@@ -416,6 +416,10 @@ int flag_signed_bitfields = 1;
 
 int warn_unknown_pragmas; /* Tri state variable.  */
 
+/* Warn about float constants with suffixes.  */
+
+int warn_unsuffixed_float_consts;
+
 /* Warn about format/argument anomalies in calls to formatted I/O functions
    (*printf, *scanf, strftime, strfmon, etc.).  */
 
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 147110)
+++ gcc/c.opt	(working copy)
@@ -476,6 +476,10 @@ Wunknown-pragmas
 C ObjC C++ ObjC++ Warning
 Warn about unrecognized pragmas
 
+Wunsuffixed-float-constants
+C ObjC Var(warn_unsuffixed_float_constants) Warning
+Warn about unsuffixed float constants
+
 Wunused-macros
 C ObjC C++ ObjC++ Warning
 Warn about macros defined in the main file that are not used
Index: gcc/c-lex.c
===================================================================
--- gcc/c-lex.c	(revision 147110)
+++ gcc/c-lex.c	(working copy)
@@ -617,11 +617,21 @@ interpret_float (const cpp_token *token,
   char *copy;
   size_t copylen;
 
-  /* Default (no suffix) is double.  */
+  /* Default (no suffix) depends on whether the FLOAT_CONST_DECIMAL64
+     pragma has been used and is either double or _Decimal64.  Types
+     that are not allowed with decimal float default to double.  */
   if (flags & CPP_N_DEFAULT)
     {
       flags ^= CPP_N_DEFAULT;
       flags |= CPP_N_MEDIUM;
+
+      if (((flags & CPP_N_HEX) == 0) && ((flags & CPP_N_IMAGINARY) == 0))
+	{
+	  warning (OPT_Wunsuffixed_float_constants,
+		   "unsuffixed float constant");
+	  if (float_const_decimal64_p ())
+	    flags |= CPP_N_DFLOAT;
+	}
     }
 
   /* Decode _Fract and _Accum.  */
Index: gcc/c-cppbuiltin.c
===================================================================
--- gcc/c-cppbuiltin.c	(revision 147110)
+++ gcc/c-cppbuiltin.c	(working copy)
@@ -619,14 +619,12 @@ c_cpp_builtins (cpp_reader *pfile)
                                  TARGET_DEC_EVAL_METHOD);
 
   builtin_define_float_constants ("FLT", "F", "%s", float_type_node);
-  /* Cast the double precision constants when single precision constants are
-     specified. The correct result is computed by the compiler when using 
+  /* Cast the double precision constants.  This is needed when single
+     precision constants are specified or when pragma FLOAT_CONST_DECIMAL64
+     is used.  The correct result is computed by the compiler when using
      macros that include a cast. This has the side-effect of making the value 
      unusable in const expressions. */
-  if (flag_single_precision_constant)
-    builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
-  else
-    builtin_define_float_constants ("DBL", "", "%s", double_type_node);
+  builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
   builtin_define_float_constants ("LDBL", "L", "%s", long_double_type_node);
 
   /* For decfloat.h.  */
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 147110)
+++ gcc/c-decl.c	(working copy)
@@ -342,6 +342,9 @@ struct GTY((chain_next ("%h.outer"))) c_
 
   /* True means make a BLOCK for this scope no matter what.  */
   BOOL_BITFIELD keep : 1;
+
+  /* True means that an unsuffixed float constant is _Decimal64.  */
+  BOOL_BITFIELD float_const_decimal64 : 1;
 };
 
 /* The scope currently in effect.  */
@@ -674,6 +677,30 @@ keep_next_level (void)
   keep_next_level_flag = true;
 }
 
+/* Set the flag for the FLOAT_CONST_DECIMAL64 pragma being ON.  */
+
+void
+set_float_const_decimal64 (void)
+{
+  current_scope->float_const_decimal64 = true;
+}
+
+/* Clear the flag for the FLOAT_CONST_DECIMAL64 pragma.  */
+
+void
+clear_float_const_decimal64 (void)
+{
+  current_scope->float_const_decimal64 = false;
+}
+
+/* Return nonzero if an unsuffixed float constant is _Decimal64.  */
+
+bool
+float_const_decimal64_p (void)
+{
+  return current_scope->float_const_decimal64;
+}
+
 /* Identify this scope as currently being filled with parameters.  */
 
 void
@@ -705,6 +732,13 @@ push_scope (void)
 
       keep_next_level_flag = false;
       next_is_function_body = false;
+
+      /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
+      if (current_scope->outer)
+	current_scope->float_const_decimal64
+	  = current_scope->outer->float_const_decimal64;
+      else
+	current_scope->float_const_decimal64 = false;
     }
   else
     {
@@ -717,6 +751,12 @@ push_scope (void)
       else
 	scope = GGC_CNEW (struct c_scope);
 
+      /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
+      if (current_scope)
+	scope->float_const_decimal64 = current_scope->float_const_decimal64;
+      else
+	scope->float_const_decimal64 = false;
+
       scope->keep          = keep_next_level_flag;
       scope->outer         = current_scope;
       scope->depth	   = current_scope ? (current_scope->depth + 1) : 0;
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(revision 147110)
+++ gcc/c-parser.c	(working copy)
@@ -979,7 +979,9 @@ c_parser_translation_unit (c_parser *par
       do
 	{
 	  ggc_collect ();
+	  mark_valid_location_for_stdc_pragma (true);
 	  c_parser_external_declaration (parser);
+	  mark_valid_location_for_stdc_pragma (false);
 	  obstack_free (&parser_obstack, obstack_position);
 	}
       while (c_parser_next_token_is_not (parser, CPP_EOF));
@@ -1431,6 +1433,7 @@ c_parser_declspecs (c_parser *parser, st
 {
   bool attrs_ok = start_attr_ok;
   bool seen_type = specs->type_seen_p;
+  bool stdc_pragma_save;
   while (c_parser_next_token_is (parser, CPP_NAME)
 	 || c_parser_next_token_is (parser, CPP_KEYWORD)
 	 || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
@@ -1554,9 +1557,12 @@ c_parser_declspecs (c_parser *parser, st
 	    goto out;
 	  attrs_ok = true;
 	  seen_type = true;
+	  stdc_pragma_save = valid_location_for_stdc_pragma_p ();
+	  mark_valid_location_for_stdc_pragma (false);
 	  t = c_parser_struct_or_union_specifier (parser);
           invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
 	  declspecs_add_type (specs, t);
+	  mark_valid_location_for_stdc_pragma (stdc_pragma_save);
 	  break;
 	case RID_TYPEOF:
 	  /* ??? The old parser rejected typeof after other type
@@ -3356,6 +3362,7 @@ c_parser_compound_statement_nostart (c_p
       c_parser_consume_token (parser);
       return;
     }
+  mark_valid_location_for_stdc_pragma (true);
   if (c_parser_next_token_is_keyword (parser, RID_LABEL))
     {
       location_t err_loc = c_parser_peek_token (parser)->location;
@@ -3409,6 +3416,7 @@ c_parser_compound_statement_nostart (c_p
 	    label_loc = c_parser_peek_token (parser)->location;
 	  last_label = true;
 	  last_stmt = false;
+	  mark_valid_location_for_stdc_pragma (false);
 	  c_parser_label (parser);
 	}
       else if (!last_label
@@ -3416,6 +3424,7 @@ c_parser_compound_statement_nostart (c_p
 	{
 	  last_label = false;
 	  c_parser_declaration_or_fndef (parser, true, true, true, true);
+	  mark_valid_location_for_stdc_pragma (false);
 	  if (last_stmt)
 	    pedwarn_c90 (loc, 
 			 (pedantic && !flag_isoc99)
@@ -3489,6 +3498,7 @@ c_parser_compound_statement_nostart (c_p
 	statement:
 	  last_label = false;
 	  last_stmt = true;
+	  mark_valid_location_for_stdc_pragma (false);
 	  c_parser_statement_after_labels (parser);
 	}
 
Index: gcc/c-pragma.c
===================================================================
--- gcc/c-pragma.c	(revision 147110)
+++ gcc/c-pragma.c	(working copy)
@@ -1162,6 +1162,116 @@ handle_pragma_message (cpp_reader *ARG_U
     inform (input_location, "#pragma message: %s", TREE_STRING_POINTER (message));
 }
 
+/* Mark whether the current location is valid for a STDC pragma.  */
+
+static bool valid_location_for_stdc_pragma;
+
+void
+mark_valid_location_for_stdc_pragma (bool flag)
+{
+  valid_location_for_stdc_pragma = flag;
+}
+
+/* Return true if the current location is valid for a STDC pragma.  */
+
+bool
+valid_location_for_stdc_pragma_p (void)
+{
+  return valid_location_for_stdc_pragma;
+}
+
+enum pragma_switch_t { ON, OFF, DEFAULT, BAD };
+
+/* A STDC pragma must appear outside of external declarations or
+   preceding all explicit declarations and statements inside a compound
+   statement; its behavior is undefined if used in any other context.
+   It takes a switch of ON, OFF, or DEFAULT.  */
+
+static enum pragma_switch_t
+handle_stdc_pragma (const char *pname)
+{
+  const char *arg;
+  tree t;
+  enum pragma_switch_t ret;
+
+  if (!valid_location_for_stdc_pragma_p ())
+    {
+      warning (OPT_Wpragmas, "invalid location for %<pragma %s%>, ignored",
+	       pname);
+      return BAD;
+    }
+
+  if (pragma_lex (&t) != CPP_NAME)
+    {
+      warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
+      return BAD;
+    }
+
+  arg = IDENTIFIER_POINTER (t);
+
+  if (!strcmp (arg, "ON"))
+    ret = ON;
+  else if (!strcmp (arg, "OFF"))
+    ret = OFF;
+  else if (!strcmp (arg, "DEFAULT"))
+    ret = DEFAULT;
+  else
+    {
+      warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
+      return BAD;
+    }
+
+  if (pragma_lex (&t) != CPP_EOF)
+    {
+      warning (OPT_Wpragmas, "junk at end of %<#pragma %s%>", pname);
+      return BAD;
+    }
+
+  return ret;
+}
+
+/* #pragma STDC FLOAT_CONST_DECIMAL64 ON
+   #pragma STDC FLOAT_CONST_DECIMAL64 OFF
+   #pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT */
+
+static void
+handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy))
+{
+  if (c_dialect_cxx ())
+    {
+      if (warn_unknown_pragmas > in_system_header)
+	warning (OPT_Wunknown_pragmas,
+		 "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
+		 " for C++");
+      return;
+    }
+
+  if (!targetm.decimal_float_supported_p ())
+    {
+      if (warn_unknown_pragmas > in_system_header)
+	warning (OPT_Wunknown_pragmas,
+		 "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
+		 " on this target");
+      return;
+    }
+
+  pedwarn (input_location, OPT_pedantic,
+	   "ISO C does not support %<#pragma STDC FLOAT_CONST_DECIMAL64%>");
+
+  switch (handle_stdc_pragma ("STDC FLOAT_CONST_DECIMAL64"))
+    {
+    case ON:
+      set_float_const_decimal64 ();
+      break;
+    case OFF:
+    case DEFAULT:
+      clear_float_const_decimal64 ();
+      break;
+    case BAD:
+      break;
+    }
+}
+
 /* A vector of registered pragma callbacks.  */
 
 DEF_VEC_O (pragma_handler);
@@ -1330,6 +1440,9 @@ init_pragma (void)
   c_register_pragma ("GCC", "pop_options", handle_pragma_pop_options);
   c_register_pragma ("GCC", "reset_options", handle_pragma_reset_options);
 
+  c_register_pragma ("STDC", "FLOAT_CONST_DECIMAL64",
+		     handle_pragma_float_const_decimal64);
+
   c_register_pragma_with_expansion (0, "redefine_extname", handle_pragma_redefine_extname);
   c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
 
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 147110)
+++ gcc/cp/semantics.c	(working copy)
@@ -5050,4 +5050,23 @@ finish_trait_expr (cp_trait_kind kind, t
 	  ? boolean_true_node : boolean_false_node);
 }
 
+/* Do-nothing variants of functions to handle pragma FLOAT_CONST_DECIMAL64,
+   which is ignored for C++.  */
+
+void
+set_float_const_decimal64 (void)
+{
+}
+
+void
+clear_float_const_decimal64 (void)
+{
+}
+
+bool
+float_const_decimal64_p (void)
+{
+  return 0;
+}
+
 #include "gt-cp-semantics.h"
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 147110)
+++ gcc/doc/extend.texi	(working copy)
@@ -958,10 +958,6 @@ is incomplete:
 
 @itemize @bullet
 @item
-Pragma @code{FLOAT_CONST_DECIMAL64} is not supported, nor is the @samp{d}
-suffix for literal constants of type @code{double}.
-
-@item
 When the value of a decimal floating type cannot be represented in the
 integer type to which it is being converted, the result is undefined
 rather than the result value specified by the draft technical report.
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 147110)
+++ gcc/doc/invoke.texi	(working copy)
@@ -4218,6 +4218,15 @@ minimum maximum, so we do not diagnose o
 
 This option is implied by @option{-pedantic}, and can be disabled with
 @option{-Wno-overlength-strings}.
+
+@item -Wunsuffixed-float-constants
+@opindex Wunsuffixed-float-constants
+
+GCC will issue a warning for any floating constant that does not have
+a suffix.  When used together with @option{-Wsystem-headers} it will
+warn about such constants in system header files.  This can be useful
+when preparing code to use with the @code{FLOAT_CONST_DECIMAL64} pragma
+from the decimal floating-point extension to C99.
 @end table
 
 @node Debugging Options
Index: gcc/testsuite/gcc.dg/Wunsuffixed-float-constants-1.c
===================================================================
--- gcc/testsuite/gcc.dg/Wunsuffixed-float-constants-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wunsuffixed-float-constants-1.c	(revision 0)
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wunsuffixed-float-constants" } */
+
+#define VAL 0.5;
+
+double a = 1.1d;
+
+/* With FLOAT_CONST_DECIMAL64 switched to ON these would have type
+   _Decimal64.  */
+
+double b = VAL;		/* { dg-warning "unsuffixed float constant" } */
+double c = 1.2;		/* { dg-warning "unsuffixed float constant" } */
+
+/* With FLOAT_CONST_DECIMAL64 switched to ON these are still binary.  */
+
+double d = 0x5.0p1;	/* No warning for hex constant.  */
+double e = 3.1i;	/* No warning for imaginary constant.  */
Index: gcc/testsuite/gcc.dg/cpp/pragma-float-const-decimal64-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/pragma-float-const-decimal64-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/pragma-float-const-decimal64-1.c	(revision 0)
@@ -0,0 +1,5 @@
+/* { dg-do compile { target { ! dfp } } } */
+/* { dg-options "-std=gnu99 -Wunknown-pragmas" } */
+
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-warning "not supported on this target" } */
+double d = 1.0;
Index: gcc/testsuite/gcc.dg/dfp/float-constant-double.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/float-constant-double.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/float-constant-double.c	(revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99" } */
+
+/* Constant float values of type double in <float.h> are suffixed with L
+   and cast to double so they can be used within code that uses pragma
+   FLOAT_CONST_DECIMAL64.  If they were not suffixed then use of the macro
+   would have them interpreted as _Decimal64, leading to errors when used
+   in expressions with other operands of type double.  */
+
+#include <float.h>
+
+extern double a, b, c, d;
+
+void
+foo ()
+{
+  _Pragma ("STDC FLOAT_CONST_DECIMAL64 ON")
+  a = 0.1d * DBL_MAX;
+  b = DBL_EPSILON * 10.0d;
+  c = DBL_MIN * 200.0d;
+}
Index: gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-1.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-1.c	(revision 0)
@@ -0,0 +1,85 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wall" } */
+
+/* N1312 7.1.1: The FLOAT_CONST_DECIMAL64 pragma.
+   C99 6.4.4.2a (New).
+
+   Verify that the pragma has the expected result by using unsuffixed
+   float constants as operands in expressions that would mix binary and
+   decimal operands if the pragma had no effect, or the wrong effect.  */
+
+#pragma STDC FLOAT_CONST_DECIMAL64 ON
+double a = 1.0 * 2.0dd;
+
+double
+f1 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+  double b = 2.0 * 3.0d;
+
+  {
+    double c = 3.0 * 4.0d;
+    b = b + c;
+  }
+
+  {
+#pragma STDC FLOAT_CONST_DECIMAL64 ON
+    double d = 4.0 * 5.0dd;
+
+    b = b + d;
+  }
+
+  {
+     /* Default is OFF.  */
+#pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT
+     double e = 5.0 * 6.0d;
+     b = b + e;
+  }
+
+  return b;
+}
+
+double
+f2 (void)
+{
+  /* Use value from outer scope, which is ON.  */
+  double b = 2.0 * 3.0dd;
+
+  {
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+    double c = 3.0 * 4.0d;
+
+    {
+#pragma STDC FLOAT_CONST_DECIMAL64 ON
+      double d = 4.0 * 5.0dd;
+
+      {
+#pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT
+	double e = 5.0 * 6.0d;
+
+	{
+#pragma STDC FLOAT_CONST_DECIMAL64 ON
+	  double f = 6.0 * 7.0dd;
+
+	  b = a + b + c + d + e + f;
+	}
+      }
+    }
+  }
+  return b;
+}
+
+/* Use previous value from this scope, which is ON.  */
+double f = 6.0 * 7.0dd;
+
+double
+f3 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+  double b = 2.0 * 3.0d;
+
+  return b + f;
+}
+
+/* Return to the state from this scope, which is ON.  */
+double g = 7.0 + 8.0dd;
Index: gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-2.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-2.c	(revision 0)
@@ -0,0 +1,86 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wall" } */
+
+/* N1312 7.1.1: The FLOAT_CONST_DECIMAL64 pragma.
+   C99 6.4.4.2a (New).
+
+   Verify that the pragma has the expected result by using unsuffixed
+   float constants as operands in expressions that would mix binary and
+   decimal operands if the pragma had no effect, or the wrong effect.
+   Use _Pragma rather than #pragma.  */
+
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 ON")
+double a = 1.0 * 2.0dd;
+
+double
+f1 (void)
+{
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 OFF")
+  double b = 2.0 * 3.0d;
+
+  {
+    double c = 3.0 * 4.0d;
+    b = b + c;
+  }
+
+  {
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 ON")
+    double d = 4.0 * 5.0dd;
+
+    b = b + d;
+  }
+
+  {
+     /* Default is OFF.  */
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 DEFAULT")
+     double e = 5.0 * 6.0d;
+     b = b + e;
+  }
+
+  return b;
+}
+
+double
+f2 (void)
+{
+  /* Use value from outer scope, which is ON.  */
+  double b = 2.0 * 3.0dd;
+
+  {
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 OFF")
+    double c = 3.0 * 4.0d;
+
+    {
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 ON")
+      double d = 4.0 * 5.0dd;
+
+      {
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 DEFAULT")
+	double e = 5.0 * 6.0d;
+
+	{
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 ON")
+	  double f = 6.0 * 7.0dd;
+
+	  b = a + b + c + d + e + f;
+	}
+      }
+    }
+  }
+  return b;
+}
+
+/* Use previous value from this scope, which is ON.  */
+double f = 6.0 * 7.0dd;
+
+double
+f3 (void)
+{
+_Pragma ("STDC FLOAT_CONST_DECIMAL64 OFF")
+  double b = 2.0 * 3.0d;
+
+  return b + f;
+}
+
+/* Return to the state from this scope, which is ON.  */
+double g = 7.0 + 8.0dd;
Index: gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-3.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-3.c	(revision 0)
@@ -0,0 +1,83 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wall" } */
+
+/* N1312 7.1.1: The FLOAT_CONST_DECIMAL64 pragma.
+   C99 6.4.4.2a (New).  */
+
+/* Check that defining macros whose names are the same as the tokens used
+   in the pragma doesn't affect use of the pragma.  */
+
+#define ON YES
+#define OFF NO
+#define DEFAULT NOPE
+#define STDC OFFICIAL
+#define FLOAT_CONST_DECIMAL64 NEW_PRAGMA
+
+double a;
+
+void
+f1a (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 ON
+  a = 1.0dd + 2.0;
+}
+
+void
+f1b (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+  a = 2.0d + 3.0;
+}
+
+void
+f1c (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT
+  a = 3.0d + 4.0;
+}
+
+/* Check that a macro can be used for the entire pragma.  */
+
+#define PRAGMA(x) _Pragma (#x)
+#define DEFAULT_FLOAT_IS_DECIMAL PRAGMA(STDC FLOAT_CONST_DECIMAL64 ON)
+#define DEFAULT_FLOAT_IS_BINARY PRAGMA(STDC FLOAT_CONST_DECIMAL64 OFF)
+
+void
+f2a (void)
+{
+  DEFAULT_FLOAT_IS_DECIMAL
+  a = 5.0 * 6.0dd;
+}
+
+void
+f2b (void)
+{
+  DEFAULT_FLOAT_IS_BINARY
+  a = 6.0 * 7.0d;
+}
+
+/* _Pragma can be used with macros, including the use of a macro for the
+    switch.  */
+
+#undef ON
+#undef OFF
+#undef DEFAULT
+#undef STDC
+#undef FLOAT_CONST_DECIMAL64
+
+#define SWITCH ON
+#define FLOAT_CONST_DECIMAL64(x) PRAGMA(STDC FLOAT_CONST_DECIMAL64 x)
+
+void
+f3a (void)
+{
+  FLOAT_CONST_DECIMAL64(SWITCH)
+  a = 1.0 * 7.0dd;
+}
+
+void
+f3b (void)
+{
+  FLOAT_CONST_DECIMAL64(OFF)
+  a = 1.0 + 2.0d;
+}
Index: gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-4.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-4.c	(revision 0)
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99" } */
+
+/* N1312 7.1.1: The FLOAT_CONST_DECIMAL64 pragma.
+   C99 6.4.4.2a (New).
+
+   Check that malformed versions of pragma STDC FLOAT_CONST_DECIMAL64
+   are detected.  */
+
+double a;
+
+void f1 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64	/* { dg-warning "malformed" } */
+  a = 1.0;
+}
+
+void f2 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 DFP	/* { dg-warning "malformed" } */
+  a = 2.0;
+}
+
+void f3 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 ON DFP /* { dg-warning "junk at end" } */
+  a = 3.0;
+}
+
+void f4 (void)
+{
+  _Pragma ( "STDC FLOAT_CONST_DECIMAL64" )	/* { dg-warning "malformed" } */
+  a = 1.0;
+}
+
+void f5 (void)
+{
+  _Pragma ( "STDC FLOAT_CONST_DECIMAL64 DFP" )	/* { dg-warning "malformed" } */
+  a = 2.0;
+}
+
+void f6 (void)
+{
+  _Pragma ( "STDC FLOAT_CONST_DECIMAL64 ON DFP" ) /* { dg-warning "junk at end" } */
+  a = 3.0;
+}
Index: gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-5.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-5.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-5.c	(revision 0)
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic" } */
+
+/* N1312 7.1.1: The FLOAT_CONST_DECIMAL64 pragma.
+   C99 6.4.4.2a (New).
+
+   Check that there is a pedantic warning for the use of pragma
+   STD FLOAT_CONST_DECIMAL64.  */
+
+double a;
+
+void f1 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 ON		/* { dg-warning "ISO C" } */
+  a = 1.0;
+}
+
+void f2 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF		/* { dg-warning "ISO C" } */
+  a = 2.0;
+}
+
+void f3 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT	/* { dg-warning "ISO C" } */
+  a = 3.0;
+}
+
+void f4 (void)
+{
+  _Pragma ("STDC FLOAT_CONST_DECIMAL64 ON")	/* { dg-warning "ISO C" } */
+  a = 1.0;
+}
+
+void f5 (void)
+{
+  _Pragma ("STDC FLOAT_CONST_DECIMAL64 OFF")	/* { dg-warning "ISO C" } */
+  a = 2.0;
+}
+
+void f6 (void)
+{
+  _Pragma ("STDC FLOAT_CONST_DECIMAL64 DEFAULT")	/* { dg-warning "ISO C" } */
+  a = 3.0;
+}
Index: gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-6.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-6.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-6.c	(revision 0)
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+/* N1312 7.1.1: The FLOAT_CONST_DECIMAL64 pragma.
+   C99 6.4.4.2a (New).
+
+   Check that there is a pedantic error for the use of pragma
+   STD FLOAT_CONST_DECIMAL64.  */
+
+double a;
+
+void f1 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 ON		/* { dg-error "ISO C" } */
+  a = 1.0;
+}
+
+void f2 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF		/* { dg-error "ISO C" } */
+  a = 2.0;
+}
+
+void f3 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT	/* { dg-error "ISO C" } */
+  a = 3.0;
+}
+
+void f4 (void)
+{
+  _Pragma ("STDC FLOAT_CONST_DECIMAL64 ON")	/* { dg-error "ISO C" } */
+  a = 1.0;
+}
+
+void f5 (void)
+{
+  _Pragma ("STDC FLOAT_CONST_DECIMAL64 OFF")	/* { dg-error "ISO C" } */
+  a = 2.0;
+}
+
+void f6 (void)
+{
+  _Pragma ("STDC FLOAT_CONST_DECIMAL64 DEFAULT") /* { dg-error "ISO C" } */
+  a = 3.0;
+}
Index: gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-7.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-7.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-7.c	(revision 0)
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wall" } */
+
+/* N1312 7.1.1: The FLOAT_CONST_DECIMAL64 pragma.
+   C99 6.4.4.2a (New).
+
+   Check that when pragma FLOAT_CONST_DECIMAL64 is in effect so that
+   unsuffixed constants are _Decimal64, invalid types are still reported
+   as invalid.  */
+
+double
+f1 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+  double a = 0x1.0p1;
+  double b = 1.0i;
+
+  return a + b;
+}
+
+double
+f2 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+  double a = 0x1.0p1dd;		/* { dg-error "with hex" } */
+  double b = 1.0idd;		/* { dg-error "invalid suffix" } */
+
+  return a + b;
+}
+
+double
+f3 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 ON
+  double a = 0x1.0p1;	/* Hex constant is not affected by pragma.  */
+  double b = 1.0i;	/* Imaginary constant is not affected by pragma.  */
+
+  return a + b;
+}
Index: gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-8.c
===================================================================
--- gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-8.c	(revision 0)
+++ gcc/testsuite/gcc.dg/dfp/pragma-float-const-decimal64-8.c	(revision 0)
@@ -0,0 +1,121 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -Wall" } */
+
+/* N1312 7.1.1: The FLOAT_CONST_DECIMAL64 pragma.
+   C99 6.4.4.2a (New).
+
+   Pragma STDC FLOAT_CONST_DECIMAL64 "shall occur either outside external
+   declarations or preceding all explicit declarations and statements
+   inside a compound statement." */
+
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+
+#define MAX 200
+
+#pragma STDC FLOAT_CONST_DECIMAL64 ON
+
+double a;
+
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+
+struct S1 {
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-warning "invalid location" } */
+  int i;
+  int j;
+};
+
+struct S2 {
+  int i;
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-warning "invalid location" } */
+  int j;
+};
+
+struct S3 {
+  int i;
+  int j;
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-warning "invalid location" } */
+};
+
+enum E1 {
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-error "#pragma" } */
+  one,
+  two
+};
+
+enum E2 {
+  red,
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-error "#pragma" } */
+  blue
+};
+
+enum E3 {
+  cat,
+  dog
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-error "#pragma" } */
+};
+
+double
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF	/* { dg-error "#pragma" } */
+b;
+
+double
+f1 (void)
+{
+#pragma STDC FLOAT_CONST_DECIMAL64 ON
+  return a;
+}
+
+double
+f2 (void)
+{
+  double b;
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-warning "invalid location" } */
+  b = 0.5;
+  return a + b;
+}
+
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF
+
+double
+f3 (void)
+{
+  typedef double b32;
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-warning "invalid location" } */
+  b32 b = 0.5;
+  return b;
+}
+
+double
+f4 (int i)
+{
+top:
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF	/* { dg-warning "invalid location" } */
+  if (i == 0)
+    return a;  
+  a *= 2.;
+  i = 0;
+  goto top;
+}
+
+double
+f5 (int i)
+{
+  a = a * i;
+#pragma STDC FLOAT_CONST_DECIMAL64 OFF	/* { dg-warning "invalid location" } */
+  return a * 2.;
+}
+
+double
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-error "#pragma" } */
+f6 (void)
+{
+  return a;
+}
+
+double
+f7
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	/* { dg-error "#pragma" } */
+(void)					/* { dg-error "before" } */
+{
+  return a;
+}
Index: gcc/testsuite/g++.dg/cpp/pragma-float-const-decimal64-1.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/pragma-float-const-decimal64-1.C	(revision 0)
+++ gcc/testsuite/g++.dg/cpp/pragma-float-const-decimal64-1.C	(revision 0)
@@ -0,0 +1,5 @@
+// { dg-do compile }
+// { dg-options "-Wunknown-pragmas" }
+
+#pragma STDC FLOAT_CONST_DECIMAL64 ON	// { dg-warning "not supported for C\\\+\\\+" }
+double d = 1.0;




More information about the Gcc-patches mailing list