This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Target FP: Use target format throughout expression parsing


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=edd079d9f6ca2f9ad21322b742269aec5de61190

commit edd079d9f6ca2f9ad21322b742269aec5de61190
Author: Ulrich Weigand <ulrich.weigand@de.ibm.com>
Date:   Wed Oct 25 15:32:23 2017 +0200

    Target FP: Use target format throughout expression parsing
    
    When parsing floating-point literals, the language parsers currently
    use parse_float or some equivalent routine to parse the input string
    into a DOUBLEST, which is then stored within a OP_DOUBLE expression
    node.  When evaluating the expression, the OP_DOUBLE is finally
    converted into a value in target format.
    
    On the other hand, *decimal* floating-point literals are parsed
    directly into target format and stored that way in a OP_DECFLOAT
    expression node.  In order to eliminate the DOUBLEST, this patch
    therefore unifies the handling of binary and decimal floating-
    point literals and stores them both in target format within a
    new OP_FLOAT expression node, replacing both OP_DOUBLE and
    OP_DECFLOAT.
    
    In order to store literals in target format, the parse_float
    routine needs to know the type of the literal.  All parsers
    therefore need to be changed to determine the appropriate type
    (e.g. by detecting suffixes) *before* calling parse_float,
    instead of after it as today.  However, this change is mostly
    straightforward -- again, this is already done for decimal FP
    today.
    
    The core of the literal parsing is moved into a new routine
    floatformat_from_string, mirroring floatformat_to_string.
    The parse_float routine now calls either floatformat_from_string
    or decimal_from_sting, allowing it to handle any type of FP
    literal.
    
    All language parsers need to be updated.  Some notes on
    specific changes to the various languages:
    
    - C: Decimal FP is now handled in parse_float, and no longer
      needs to be handled specially.
    
    - D: Straightforward.
    
    - Fortran: Still used a hard-coded "atof", also replaced by
      parse_float now.  Continues to always use builtin_real_s8
      as the type of literal, even though this is probably wrong.
    
    - Go: This used to handle "f" and "l" suffixes, even though
      the Go language actually doesn't support those.  I kept this
      support for now -- maybe revisit later.  Note the the GDB
      test suite for some reason actually *verifies* that GDB supports
      those unsupported suffixes ...
    
    - Pascal: Likewise -- this handles suffixes that are not
      supported in the language standard.
    
    - Modula-2: Like Fortran, used to use "atof".
    
    - Rust: Mostly straightforward, except for a unit-testing hitch.
      The code use to set a special "unit_testing" flag which would
      cause "rust_type" to always return NULL.  This makes it not
      possible to encode a literal into target format (which type?).
      The reason for this flag appears to have been that during
      unit testing, there is no "rust_parser" context set up, which
      means no "gdbarch" is available to use its types.  To fix this,
      I removed the unit_testing flag, and instead simply just set up
      a dummy rust_parser context during unit testing.
    
    - Ada: This used to check sizeof (DOUBLEST) to determine which
      type to use for floating-point literal.  This seems questionable
      to begin with (since DOUBLEST is quite unrelated to target formats),
      and in any case we need to get rid of DOUBLEST.  I'm now simply
      always using the largest type (builtin_long_double).
    
    gdb/ChangeLog:
    2017-10-25  Ulrich Weigand  <uweigand@de.ibm.com>
    
    	* doublest.c (floatformat_from_string): New function.
    	* doublest.h (floatformat_from_string): Add prototype.
    
    	* std-operator.def (OP_DOUBLE, OP_DECFLOAT): Remove, replace by ...
    	(OP_FLOAT): ... this.
    	* expression.h: Do not include "doublest.h".
    	(union exp_element): Replace doubleconst and decfloatconst by
    	new element floatconst.
    	* ada-lang.c (resolve_subexp): Handle OP_FLOAT instead of OP_DOUBLE.
    	(ada_evaluate_subexp): Likewise.
    	* eval.c (evaluate_subexp_standard): Handle OP_FLOAT instead of
    	OP_DOUBLE and OP_DECFLOAT.
    	* expprint.c (print_subexp_standard): Likewise.
    	(dump_subexp_body_standard): Likewise.
    	* breakpoint.c (watchpoint_exp_is_const): Likewise.
    
    	* parse.c: Include "dfp.h".
    	(write_exp_elt_dblcst, write_exp_elt_decfloatcst): Remove.
    	(write_exp_elt_floatcst): New function.
    	(operator_length_standard): Handle OP_FLOAT instead of OP_DOUBLE
    	and OP_DECFLOAT.
    	(operator_check_standard): Likewise.
    	(parse_float): Do not accept suffix.  Take type as input.  Return bool.
    	Return target format buffer instead of host DOUBLEST.
    	Use floatformat_from_string and decimal_from_string to parse
    	either binary or decimal floating-point types.
    	(parse_c_float): Remove.
    	* parser-defs.h: Do not include "doublest.h".
    	(write_exp_elt_dblcst, write_exp_elt_decfloatcst): Remove.
    	(write_exp_elt_floatcst): Add prototype.
    	(parse_float): Update prototype.
    	(parse_c_float): Remove.
    
    	* c-exp.y: Do not include "dfp.h".
    	(typed_val_float): Use byte buffer instead of DOUBLEST.
    	(typed_val_decfloat): Remove.
    	(DECFLOAT): Remove.
    	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
    	(parse_number): Update to new parse_float interface.
    	Parse suffixes and determine type before calling parse_float.
    	Handle decimal and binary FP types the same way.
    
    	* d-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
    	(FLOAT_LITERAL): Use OP_FLOAT and write_exp_elt_floatcst.
    	(parse_number): Update to new parse_float interface.
    	Parse suffixes and determine type before calling parse_float.
    
    	* f-exp.y: Replace dval by typed_val_float.
    	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
    	(parse_number): Use parse_float instead of atof.
    
    	* go-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
    	(parse_go_float): Remove.
    	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
    	(parse_number): Call parse_float instead of parse_go_float.
    	Parse suffixes and determine type before calling parse_float.
    
    	* p-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
    	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
    	(parse_number): Update to new parse_float interface.
    	Parse suffixes and determine type before calling parse_float.
    
    	* m2-exp.y: Replace dval by byte buffer val.
    	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
    	(parse_number): Call parse_float instead of atof.
    
    	* rust-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
    	(lex_number): Call parse_float instead of strtod.
    	(ast_dliteral): Use OP_FLOAT instead of OP_DOUBLE.
    	(convert_ast_to_expression): Handle OP_FLOAT instead of OP_DOUBLE.
    	Use write_exp_elt_floatcst.
    	(unit_testing): Remove static variable.
    	(rust_type): Do not check unit_testing.
    	(rust_lex_tests): Do not set uint_testing.  Set up dummy rust_parser.
    
    	* ada-exp.y (type_float, type_double): Remove.
    	(typed_val_float): Use byte buffer instead of DOUBLEST.
    	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
    	* ada-lex.l (processReal): Use parse_float instead of sscanf.

Diff:
---
 gdb/ChangeLog        | 82 ++++++++++++++++++++++++++++++++++++++++++++++
 gdb/ada-exp.y        | 24 +++-----------
 gdb/ada-lang.c       |  6 ++--
 gdb/ada-lex.l        | 14 +++-----
 gdb/breakpoint.c     |  3 +-
 gdb/c-exp.y          | 79 +++++++++++++++++++++------------------------
 gdb/d-exp.y          | 73 ++++++++++++++++++++---------------------
 gdb/doublest.c       | 29 +++++++++++++++++
 gdb/doublest.h       |  2 ++
 gdb/eval.c           | 11 ++-----
 gdb/expprint.c       | 13 ++++----
 gdb/expression.h     |  4 +--
 gdb/f-exp.y          | 29 ++++++++++-------
 gdb/go-exp.y         | 60 ++++++++++++++++++----------------
 gdb/m2-exp.y         | 16 +++++----
 gdb/p-exp.y          | 35 ++++++++++++++++----
 gdb/parse.c          | 91 ++++++++++------------------------------------------
 gdb/parser-defs.h    | 12 ++-----
 gdb/rust-exp.y       | 33 ++++++++-----------
 gdb/std-operator.def | 11 ++-----
 20 files changed, 332 insertions(+), 295 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2107679..8835572 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,85 @@
+2017-10-25  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	* doublest.c (floatformat_from_string): New function.
+	* doublest.h (floatformat_from_string): Add prototype.
+
+	* std-operator.def (OP_DOUBLE, OP_DECFLOAT): Remove, replace by ...
+	(OP_FLOAT): ... this.
+	* expression.h: Do not include "doublest.h".
+	(union exp_element): Replace doubleconst and decfloatconst by
+	new element floatconst.
+	* ada-lang.c (resolve_subexp): Handle OP_FLOAT instead of OP_DOUBLE.
+	(ada_evaluate_subexp): Likewise.
+	* eval.c (evaluate_subexp_standard): Handle OP_FLOAT instead of
+	OP_DOUBLE and OP_DECFLOAT.
+	* expprint.c (print_subexp_standard): Likewise.
+	(dump_subexp_body_standard): Likewise.
+	* breakpoint.c (watchpoint_exp_is_const): Likewise.
+
+	* parse.c: Include "dfp.h".
+	(write_exp_elt_dblcst, write_exp_elt_decfloatcst): Remove.
+	(write_exp_elt_floatcst): New function.
+	(operator_length_standard): Handle OP_FLOAT instead of OP_DOUBLE
+	and OP_DECFLOAT.
+	(operator_check_standard): Likewise.
+	(parse_float): Do not accept suffix.  Take type as input.  Return bool.
+	Return target format buffer instead of host DOUBLEST.
+	Use floatformat_from_string and decimal_from_string to parse
+	either binary or decimal floating-point types.
+	(parse_c_float): Remove.
+	* parser-defs.h: Do not include "doublest.h".
+	(write_exp_elt_dblcst, write_exp_elt_decfloatcst): Remove.
+	(write_exp_elt_floatcst): Add prototype.
+	(parse_float): Update prototype.
+	(parse_c_float): Remove.
+
+	* c-exp.y: Do not include "dfp.h".
+	(typed_val_float): Use byte buffer instead of DOUBLEST.
+	(typed_val_decfloat): Remove.
+	(DECFLOAT): Remove.
+	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+	(parse_number): Update to new parse_float interface.
+	Parse suffixes and determine type before calling parse_float.
+	Handle decimal and binary FP types the same way.
+
+	* d-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
+	(FLOAT_LITERAL): Use OP_FLOAT and write_exp_elt_floatcst.
+	(parse_number): Update to new parse_float interface.
+	Parse suffixes and determine type before calling parse_float.
+
+	* f-exp.y: Replace dval by typed_val_float.
+	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+	(parse_number): Use parse_float instead of atof.
+
+	* go-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
+	(parse_go_float): Remove.
+	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+	(parse_number): Call parse_float instead of parse_go_float.
+	Parse suffixes and determine type before calling parse_float.
+
+	* p-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
+	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+	(parse_number): Update to new parse_float interface.
+	Parse suffixes and determine type before calling parse_float.
+
+	* m2-exp.y: Replace dval by byte buffer val.
+	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+	(parse_number): Call parse_float instead of atof.
+
+	* rust-exp.y (typed_val_float): Use byte buffer instead of DOUBLEST.
+	(lex_number): Call parse_float instead of strtod.
+	(ast_dliteral): Use OP_FLOAT instead of OP_DOUBLE.
+	(convert_ast_to_expression): Handle OP_FLOAT instead of OP_DOUBLE.
+	Use write_exp_elt_floatcst.
+	(unit_testing): Remove static variable.
+	(rust_type): Do not check unit_testing.
+	(rust_lex_tests): Do not set uint_testing.  Set up dummy rust_parser.
+
+	* ada-exp.y (type_float, type_double): Remove.
+	(typed_val_float): Use byte buffer instead of DOUBLEST.
+	(FLOAT): Use OP_FLOAT and write_exp_elt_floatcst.
+	* ada-lex.l (processReal): Use parse_float instead of sscanf.
+
 2017-10-25  Alan Hayward  <alan.hayward@arm.com>
 
 	* aarch64-tdep.h (enum aarch64_regnum): Remove.
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 4c1ff7b..3014a31 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -106,10 +106,6 @@ static struct type *type_long (struct parser_state *);
 
 static struct type *type_long_long (struct parser_state *);
 
-static struct type *type_float (struct parser_state *);
-
-static struct type *type_double (struct parser_state *);
-
 static struct type *type_long_double (struct parser_state *);
 
 static struct type *type_char (struct parser_state *);
@@ -128,7 +124,7 @@ static struct type *type_system_address (struct parser_state *);
       struct type *type;
     } typed_val;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct type *tval;
@@ -553,10 +549,10 @@ primary	:	CHARLIT
 	;
 
 primary	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate, $1.type);
-			  write_exp_elt_dblcst (pstate, $1.dval);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE);
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT);
 			}
 	;
 
@@ -1440,18 +1436,6 @@ type_long_long (struct parser_state *par_state)
 }
 
 static struct type *
-type_float (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_float;
-}
-
-static struct type *
-type_double (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_double;
-}
-
-static struct type *
 type_long_double (struct parser_state *par_state)
 {
   return parse_type (par_state)->builtin_long_double;
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 7409496..b8636e6 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -3384,7 +3384,7 @@ resolve_subexp (struct expression **expp, int *pos, int deprocedure_p,
       break;
 
     case OP_LONG:
-    case OP_DOUBLE:
+    case OP_FLOAT:
     case OP_VAR_VALUE:
     case OP_VAR_MSYM_VALUE:
       *pos += 4;
@@ -10421,7 +10421,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
       if (noside == EVAL_NORMAL)
 	arg1 = unwrap_value (arg1);
 
-      /* If evaluating an OP_DOUBLE and an EXPECT_TYPE was provided,
+      /* If evaluating an OP_FLOAT and an EXPECT_TYPE was provided,
          then we need to perform the conversion manually, because
          evaluate_subexp_standard doesn't do it.  This conversion is
          necessary in Ada because the different kinds of float/fixed
@@ -10429,7 +10429,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
 
          Similarly, we need to perform the conversion from OP_LONG
          ourselves.  */
-      if ((op == OP_DOUBLE || op == OP_LONG) && expect_type != NULL)
+      if ((op == OP_FLOAT || op == OP_LONG) && expect_type != NULL)
         arg1 = ada_value_cast (expect_type, arg1, noside);
 
       return arg1;
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index fe97352..ce8de69 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -403,16 +403,12 @@ processInt (struct parser_state *par_state, const char *base0,
 static int
 processReal (struct parser_state *par_state, const char *num0)
 {
-  sscanf (num0, "%" DOUBLEST_SCAN_FORMAT, &yylval.typed_val_float.dval);
-
-  yylval.typed_val_float.type = type_float (par_state);
-  if (sizeof(DOUBLEST) >= gdbarch_double_bit (parse_gdbarch (par_state))
-			    / TARGET_CHAR_BIT)
-    yylval.typed_val_float.type = type_double (par_state);
-  if (sizeof(DOUBLEST) >= gdbarch_long_double_bit (parse_gdbarch (par_state))
-			    / TARGET_CHAR_BIT)
-    yylval.typed_val_float.type = type_long_double (par_state);
+  yylval.typed_val_float.type = type_long_double (par_state);
 
+  bool parsed = parse_float (num0, strlen (num0),
+			     yylval.typed_val_float.type,
+			     yylval.typed_val_float.val);
+  gdb_assert (parsed);
   return FLOAT;
 }
 
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 32ceea7..e16cfb6 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -10121,8 +10121,7 @@ watchpoint_exp_is_const (const struct expression *exp)
 	case TERNOP_SLICE:
 
 	case OP_LONG:
-	case OP_DOUBLE:
-	case OP_DECFLOAT:
+	case OP_FLOAT:
 	case OP_LAST:
 	case OP_COMPLEX:
 	case OP_STRING:
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 18c74d8..8eaf7c0 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -48,7 +48,6 @@
 #include "charset.h"
 #include "block.h"
 #include "cp-support.h"
-#include "dfp.h"
 #include "macroscope.h"
 #include "objc-lang.h"
 #include "typeprint.h"
@@ -88,13 +87,9 @@ static int type_aggregate_p (struct type *);
       struct type *type;
     } typed_val_int;
     struct {
-      DOUBLEST dval;
-      struct type *type;
-    } typed_val_float;
-    struct {
       gdb_byte val[16];
       struct type *type;
-    } typed_val_decfloat;
+    } typed_val_float;
     struct type *tval;
     struct stoken sval;
     struct typed_stoken tsval;
@@ -142,7 +137,6 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
 
 %token <typed_val_int> INT
 %token <typed_val_float> FLOAT
-%token <typed_val_decfloat> DECFLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -749,17 +743,10 @@ exp	:	NAME_OR_INT
 
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate, $1.type);
-			  write_exp_elt_dblcst (pstate, $1.dval);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
-	;
-
-exp	:	DECFLOAT
-			{ write_exp_elt_opcode (pstate, OP_DECFLOAT);
-			  write_exp_elt_type (pstate, $1.type);
-			  write_exp_elt_decfloatcst (pstate, $1.val);
-			  write_exp_elt_opcode (pstate, OP_DECFLOAT); }
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -1792,43 +1779,49 @@ parse_number (struct parser_state *par_state,
 
   if (parsed_float)
     {
-      /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
-         point.  Return DECFLOAT.  */
-
+      /* Handle suffixes for decimal floating-point: "df", "dd" or "dl".  */
       if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'f')
 	{
-	  putithere->typed_val_decfloat.type
+	  putithere->typed_val_float.type
 	    = parse_type (par_state)->builtin_decfloat;
-	  decimal_from_string (putithere->typed_val_decfloat.val, 4,
-			       gdbarch_byte_order (parse_gdbarch (par_state)),
-			       std::string (p, len - 2));
-	  return DECFLOAT;
+	  len -= 2;
 	}
-
-      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
+      else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'd')
 	{
-	  putithere->typed_val_decfloat.type
+	  putithere->typed_val_float.type
 	    = parse_type (par_state)->builtin_decdouble;
-	  decimal_from_string (putithere->typed_val_decfloat.val, 8,
-			       gdbarch_byte_order (parse_gdbarch (par_state)),
-			       std::string (p, len - 2));
-	  return DECFLOAT;
+	  len -= 2;
 	}
-
-      if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
+      else if (len >= 2 && p[len - 2] == 'd' && p[len - 1] == 'l')
 	{
-	  putithere->typed_val_decfloat.type
+	  putithere->typed_val_float.type
 	    = parse_type (par_state)->builtin_declong;
-	  decimal_from_string (putithere->typed_val_decfloat.val, 16,
-			       gdbarch_byte_order (parse_gdbarch (par_state)),
-			       std::string (p, len - 2));
-	  return DECFLOAT;
+	  len -= 2;
+	}
+      /* Handle suffixes: 'f' for float, 'l' for long double.  */
+      else if (len >= 1 && tolower (p[len - 1]) == 'f')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_float;
+	  len -= 1;
+	}
+      else if (len >= 1 && tolower (p[len - 1]) == 'l')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_long_double;
+	  len -= 1;
+	}
+      /* Default type for floating-point literals is double.  */
+      else
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_double;
 	}
 
-      if (! parse_c_float (parse_gdbarch (par_state), p, len,
-			   &putithere->typed_val_float.dval,
-			   &putithere->typed_val_float.type))
-	return ERROR;
+      if (!parse_float (p, len,
+			putithere->typed_val_float.type,
+			putithere->typed_val_float.val))
+        return ERROR;
       return FLOAT;
     }
 
diff --git a/gdb/d-exp.y b/gdb/d-exp.y
index 00c9676..0a43bc4 100644
--- a/gdb/d-exp.y
+++ b/gdb/d-exp.y
@@ -86,7 +86,7 @@ static int type_aggregate_p (struct type *);
       struct type *type;
     } typed_val_int;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct symbol *sym;
@@ -540,10 +540,10 @@ PrimaryExpression:
 		  write_exp_elt_longcst (pstate, (LONGEST)($1.val));
 		  write_exp_elt_opcode (pstate, OP_LONG); }
 |	FLOAT_LITERAL
-		{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+		{ write_exp_elt_opcode (pstate, OP_FLOAT);
 		  write_exp_elt_type (pstate, $1.type);
-		  write_exp_elt_dblcst (pstate, $1.dval);
-		  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+		  write_exp_elt_floatcst (pstate, $1.val);
+		  write_exp_elt_opcode (pstate, OP_FLOAT); }
 |	CHARACTER_LITERAL
 		{ struct stoken_vector vec;
 		  vec.len = 1;
@@ -682,8 +682,6 @@ parse_number (struct parser_state *ps, const char *p,
 
   if (parsed_float)
     {
-      const char *suffix;
-      int suffix_len;
       char *s, *sp;
 
       /* Strip out all embedded '_' before passing to parse_float.  */
@@ -698,54 +696,51 @@ parse_number (struct parser_state *ps, const char *p,
       *sp = '\0';
       len = strlen (s);
 
-      if (! parse_float (s, len, &putithere->typed_val_float.dval, &suffix))
-	return ERROR;
-
-      suffix_len = s + len - suffix;
-
-      if (suffix_len == 0)
-	{
-	  putithere->typed_val_float.type
-	    = parse_d_type (ps)->builtin_double;
-	}
-      else if (suffix_len == 1)
+      /* Check suffix for `i' , `fi' or `li' (idouble, ifloat or ireal).  */
+      if (len >= 1 && tolower (s[len - 1]) == 'i')
 	{
-	  /* Check suffix for `f', `l', or `i' (float, real, or idouble).  */
-	  if (tolower (*suffix) == 'f')
+	  if (len >= 2 && tolower (s[len - 2]) == 'f')
 	    {
 	      putithere->typed_val_float.type
-		= parse_d_type (ps)->builtin_float;
+		= parse_d_type (ps)->builtin_ifloat;
+	      len -= 2;
 	    }
-	  else if (tolower (*suffix) == 'l')
+	  else if (len >= 2 && tolower (s[len - 2]) == 'l')
 	    {
 	      putithere->typed_val_float.type
-		= parse_d_type (ps)->builtin_real;
+		= parse_d_type (ps)->builtin_ireal;
+	      len -= 2;
 	    }
-	  else if (tolower (*suffix) == 'i')
+	  else
 	    {
 	      putithere->typed_val_float.type
 		= parse_d_type (ps)->builtin_idouble;
+	      len -= 1;
 	    }
-	  else
-	    return ERROR;
 	}
-      else if (suffix_len == 2)
+      /* Check suffix for `f' or `l'' (float or real).  */
+      else if (len >= 1 && tolower (s[len - 1]) == 'f')
 	{
-	  /* Check suffix for `fi' or `li' (ifloat or ireal).  */
-	  if (tolower (suffix[0]) == 'f' && tolower (suffix[1] == 'i'))
-	    {
-	      putithere->typed_val_float.type
-		= parse_d_type (ps)->builtin_ifloat;
-	    }
-	  else if (tolower (suffix[0]) == 'l' && tolower (suffix[1] == 'i'))
-	    {
-	      putithere->typed_val_float.type
-		= parse_d_type (ps)->builtin_ireal;
-	    }
-	  else
-	    return ERROR;
+	  putithere->typed_val_float.type
+	    = parse_d_type (ps)->builtin_float;
+	  len -= 1;
 	}
+      else if (len >= 1 && tolower (s[len - 1]) == 'l')
+	{
+	  putithere->typed_val_float.type
+	    = parse_d_type (ps)->builtin_real;
+	  len -= 1;
+	}
+      /* Default type if no suffix.  */
       else
+	{
+	  putithere->typed_val_float.type
+	    = parse_d_type (ps)->builtin_double;
+	}
+
+      if (!parse_float (s, len,
+			putithere->typed_val_float.type,
+			putithere->typed_val_float.val))
 	return ERROR;
 
       return FLOAT_LITERAL;
diff --git a/gdb/doublest.c b/gdb/doublest.c
index 27d1c12..fe9fc23 100644
--- a/gdb/doublest.c
+++ b/gdb/doublest.c
@@ -866,6 +866,35 @@ floatformat_to_string (const struct floatformat *fmt,
   floatformat_to_doublest (fmt, in, &doub);
   return string_printf (host_format.c_str (), doub);
 }
+
+/* Parse string STRING into a target floating-number of format FMT and
+   store it as byte-stream ADDR.  Return whether parsing succeeded.  */
+bool
+floatformat_from_string (const struct floatformat *fmt, gdb_byte *out,
+			 const std::string &in)
+{
+  DOUBLEST doub;
+  int n, num;
+#ifdef HAVE_LONG_DOUBLE
+  const char *scan_format = "%Lg%n";
+#else
+  const char *scan_format = "%lg%n";
+#endif
+  num = sscanf (in.c_str (), scan_format, &doub, &n);
+
+  /* The sscanf man page suggests not making any assumptions on the effect
+     of %n on the result, so we don't.
+     That is why we simply test num == 0.  */
+  if (num == 0)
+    return false;
+
+  /* We only accept the whole string.  */
+  if (in[n])
+    return false;
+
+  floatformat_from_doublest (fmt, &doub, out);
+  return true;
+}
 
 /* Extract a floating-point number of type TYPE from a target-order
    byte-stream at ADDR.  Returns the value as type DOUBLEST.  */
diff --git a/gdb/doublest.h b/gdb/doublest.h
index f249352..4b9d6bc 100644
--- a/gdb/doublest.h
+++ b/gdb/doublest.h
@@ -74,6 +74,8 @@ extern const char *floatformat_mantissa (const struct floatformat *,
 extern std::string floatformat_to_string (const struct floatformat *fmt,
 					  const gdb_byte *in,
 					  const char *format = nullptr);
+extern bool floatformat_from_string (const struct floatformat *fmt,
+				     gdb_byte *out, const std::string &in);
 
 /* Return the floatformat's total size in host bytes.  */
 
diff --git a/gdb/eval.c b/gdb/eval.c
index 2587f77..94ddfdb 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -1277,15 +1277,10 @@ evaluate_subexp_standard (struct type *expect_type,
       return value_from_longest (exp->elts[pc + 1].type,
 				 exp->elts[pc + 2].longconst);
 
-    case OP_DOUBLE:
+    case OP_FLOAT:
       (*pos) += 3;
-      return value_from_double (exp->elts[pc + 1].type,
-				exp->elts[pc + 2].doubleconst);
-
-    case OP_DECFLOAT:
-      (*pos) += 3;
-      return value_from_decfloat (exp->elts[pc + 1].type,
-				  exp->elts[pc + 2].decfloatconst);
+      return value_from_contents (exp->elts[pc + 1].type,
+				  exp->elts[pc + 2].floatconst);
 
     case OP_ADL_FUNC:
     case OP_VAR_VALUE:
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 9e04f24..a99832c 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -105,14 +105,14 @@ print_subexp_standard (struct expression *exp, int *pos,
       }
       return;
 
-    case OP_DOUBLE:
+    case OP_FLOAT:
       {
 	struct value_print_options opts;
 
 	get_no_prettyformat_print_options (&opts);
 	(*pos) += 3;
-	value_print (value_from_double (exp->elts[pc + 1].type,
-					exp->elts[pc + 2].doubleconst),
+	value_print (value_from_contents (exp->elts[pc + 1].type,
+					  exp->elts[pc + 2].floatconst),
 		     stream, &opts);
       }
       return;
@@ -871,13 +871,14 @@ dump_subexp_body_standard (struct expression *exp,
 			(long) exp->elts[elt + 1].longconst);
       elt += 3;
       break;
-    case OP_DOUBLE:
+    case OP_FLOAT:
       fprintf_filtered (stream, "Type @");
       gdb_print_host_address (exp->elts[elt].type, stream);
       fprintf_filtered (stream, " (");
       type_print (exp->elts[elt].type, NULL, stream, 0);
-      fprintf_filtered (stream, "), value %g",
-			(double) exp->elts[elt + 1].doubleconst);
+      fprintf_filtered (stream, "), value ");
+      print_floating (exp->elts[elt + 1].floatconst,
+		      exp->elts[elt].type, stream);
       elt += 3;
       break;
     case OP_VAR_VALUE:
diff --git a/gdb/expression.h b/gdb/expression.h
index 9e4ddf5..271baa9 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -22,7 +22,6 @@
 
 
 #include "symtab.h"		/* Needed for "struct block" type.  */
-#include "doublest.h"		/* Needed for DOUBLEST.  */
 
 
 /* Definitions for saved C expressions.  */
@@ -66,8 +65,7 @@ union exp_element
     struct symbol *symbol;
     struct minimal_symbol *msymbol;
     LONGEST longconst;
-    DOUBLEST doubleconst;
-    gdb_byte decfloatconst[16];
+    gdb_byte floatconst[16];
     /* Really sizeof (union exp_element) characters (or less for the last
        element of a string).  */
     char string;
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index 8dcc811..217191a 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -91,7 +91,10 @@ static int match_string_literal (void);
       LONGEST val;
       struct type *type;
     } typed_val;
-    DOUBLEST dval;
+    struct {
+      gdb_byte val[16];
+      struct type *type;
+    } typed_val_float;
     struct symbol *sym;
     struct type *tval;
     struct stoken sval;
@@ -122,7 +125,7 @@ static int parse_number (struct parser_state *, const char *, int,
 %type <tval> ptype
 
 %token <typed_val> INT
-%token <dval> FLOAT
+%token <typed_val_float> FLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -414,12 +417,10 @@ exp	:	NAME_OR_INT
 	;
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
-			  write_exp_elt_type (pstate,
-					      parse_f_type (pstate)
-					      ->builtin_real_s8);
-			  write_exp_elt_dblcst (pstate, $1);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
+			  write_exp_elt_type (pstate, $1.type);
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -647,16 +648,22 @@ parse_number (struct parser_state *par_state,
   if (parsed_float)
     {
       /* It's a float since it contains a point or an exponent.  */
-      /* [dD] is not understood as an exponent by atof, change it to 'e'.  */
+      /* [dD] is not understood as an exponent by parse_float,
+	 change it to 'e'.  */
       char *tmp, *tmp2;
 
       tmp = xstrdup (p);
       for (tmp2 = tmp; *tmp2; ++tmp2)
 	if (*tmp2 == 'd' || *tmp2 == 'D')
 	  *tmp2 = 'e';
-      putithere->dval = atof (tmp);
+
+      /* FIXME: Should this use different types?  */
+      putithere->typed_val_float.type = parse_f_type (pstate)->builtin_real_s8;
+      bool parsed = parse_float (tmp, len,
+				 putithere->typed_val_float.type,
+				 putithere->typed_val_float.val);
       free (tmp);
-      return FLOAT;
+      return parsed? FLOAT : ERROR;
     }
 
   /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index 629093a..9beb511 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -97,7 +97,7 @@ void yyerror (const char *);
       struct type *type;
     } typed_val_int;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct stoken sval;
@@ -115,8 +115,6 @@ void yyerror (const char *);
 /* YYSTYPE gets defined by %union.  */
 static int parse_number (struct parser_state *,
 			 const char *, int, int, YYSTYPE *);
-static int parse_go_float (struct gdbarch *gdbarch, const char *p, int len,
-			   DOUBLEST *d, struct type **t);
 %}
 
 %type <voidval> exp exp1 type_exp start variable lcurly
@@ -436,10 +434,10 @@ exp	:	NAME_OR_INT
 
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate, $1.type);
-			  write_exp_elt_dblcst (pstate, $1.dval);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -634,24 +632,6 @@ name_not_typename
 
 %%
 
-/* Wrapper on parse_c_float to get the type right for Go.  */
-
-static int
-parse_go_float (struct gdbarch *gdbarch, const char *p, int len,
-		DOUBLEST *d, struct type **t)
-{
-  int result = parse_c_float (gdbarch, p, len, d, t);
-  const struct builtin_type *builtin_types = builtin_type (gdbarch);
-  const struct builtin_go_type *builtin_go_types = builtin_go_type (gdbarch);
-
-  if (*t == builtin_types->builtin_float)
-    *t = builtin_go_types->builtin_float32;
-  else if (*t == builtin_types->builtin_double)
-    *t = builtin_go_types->builtin_float64;
-
-  return result;
-}
-
 /* Take care of parsing a number (anything that starts with a digit).
    Set yylval and return the token type; update lexptr.
    LEN is the number of characters in it.  */
@@ -688,10 +668,34 @@ parse_number (struct parser_state *par_state,
 
   if (parsed_float)
     {
-      if (! parse_go_float (parse_gdbarch (par_state), p, len,
-			    &putithere->typed_val_float.dval,
-			    &putithere->typed_val_float.type))
-	return ERROR;
+      const struct builtin_go_type *builtin_go_types
+	= builtin_go_type (parse_gdbarch (par_state));
+
+      /* Handle suffixes: 'f' for float32, 'l' for long double.
+	 FIXME: This appears to be an extension -- do we want this?  */
+      if (len >= 1 && tolower (p[len - 1]) == 'f')
+	{
+	  putithere->typed_val_float.type
+	    = builtin_go_types->builtin_float32;
+	  len--;
+	}
+      else if (len >= 1 && tolower (p[len - 1]) == 'l')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_long_double;
+	  len--;
+	}
+      /* Default type for floating-point literals is float64.  */
+      else
+        {
+	  putithere->typed_val_float.type
+	    = builtin_go_types->builtin_float64;
+        }
+
+      if (!parse_float (p, len,
+			putithere->typed_val_float.type,
+			putithere->typed_val_float.val))
+        return ERROR;
       return FLOAT;
     }
 
diff --git a/gdb/m2-exp.y b/gdb/m2-exp.y
index 02dc36f..3998d2b 100644
--- a/gdb/m2-exp.y
+++ b/gdb/m2-exp.y
@@ -82,7 +82,7 @@ static int number_sign = 1;
   {
     LONGEST lval;
     ULONGEST ulval;
-    DOUBLEST dval;
+    gdb_byte val[16];
     struct symbol *sym;
     struct type *tval;
     struct stoken sval;
@@ -103,7 +103,7 @@ static int number_sign = 1;
 
 %token <lval> INT HEX ERROR
 %token <ulval> UINT M2_TRUE M2_FALSE CHAR
-%token <dval> FLOAT
+%token <val> FLOAT
 
 /* Both NAME and TYPENAME tokens represent symbols in the input,
    and both convey their data as strings.
@@ -474,12 +474,12 @@ exp	:	CHAR
 
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate,
 					      parse_m2_type (pstate)
 					      ->builtin_real);
-			  write_exp_elt_dblcst (pstate, $1);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+			  write_exp_elt_floatcst (pstate, $1);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -650,7 +650,11 @@ parse_number (int olen)
     if (p[c] == '.' && base == 10)
       {
 	/* It's a float since it contains a point.  */
-	yylval.dval = atof (p);
+	if (!parse_float (p, len,
+			  parse_m2_type (pstate)->builtin_real,
+			  yylval.val))
+	  return ERROR;
+
 	lexptr += len;
 	return FLOAT;
       }
diff --git a/gdb/p-exp.y b/gdb/p-exp.y
index eee4fa9..64e8189 100644
--- a/gdb/p-exp.y
+++ b/gdb/p-exp.y
@@ -89,7 +89,7 @@ static char *uptok (const char *, int);
       struct type *type;
     } typed_val_int;
     struct {
-      DOUBLEST dval;
+      gdb_byte val[16];
       struct type *type;
     } typed_val_float;
     struct symbol *sym;
@@ -511,11 +511,11 @@ exp	:	NAME_OR_INT
 
 
 exp	:	FLOAT
-			{ write_exp_elt_opcode (pstate, OP_DOUBLE);
+			{ write_exp_elt_opcode (pstate, OP_FLOAT);
 			  write_exp_elt_type (pstate, $1.type);
 			  current_type = $1.type;
-			  write_exp_elt_dblcst (pstate, $1.dval);
-			  write_exp_elt_opcode (pstate, OP_DOUBLE); }
+			  write_exp_elt_floatcst (pstate, $1.val);
+			  write_exp_elt_opcode (pstate, OP_FLOAT); }
 	;
 
 exp	:	variable
@@ -854,9 +854,30 @@ parse_number (struct parser_state *par_state,
 
   if (parsed_float)
     {
-      if (! parse_c_float (parse_gdbarch (par_state), p, len,
-			   &putithere->typed_val_float.dval,
-			   &putithere->typed_val_float.type))
+      /* Handle suffixes: 'f' for float, 'l' for long double.
+         FIXME: This appears to be an extension -- do we want this?  */
+      if (len >= 1 && tolower (p[len - 1]) == 'f')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_float;
+	  len--;
+	}
+      else if (len >= 1 && tolower (p[len - 1]) == 'l')
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_long_double;
+	  len--;
+	}
+      /* Default type for floating-point literals is double.  */
+      else
+	{
+	  putithere->typed_val_float.type
+	    = parse_type (par_state)->builtin_double;
+	}
+
+      if (!parse_float (p, len,
+			putithere->typed_val_float.type,
+			putithere->typed_val_float.val))
 	return ERROR;
       return FLOAT;
     }
diff --git a/gdb/parse.c b/gdb/parse.c
index 6bbf25f..a4058c3 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -45,6 +45,7 @@
 #include "symfile.h"		/* for overlay functions */
 #include "inferior.h"
 #include "doublest.h"
+#include "dfp.h"
 #include "block.h"
 #include "source.h"
 #include "objfiles.h"
@@ -264,23 +265,13 @@ write_exp_elt_longcst (struct parser_state *ps, LONGEST expelt)
 }
 
 void
-write_exp_elt_dblcst (struct parser_state *ps, DOUBLEST expelt)
-{
-  union exp_element tmp;
-
-  memset (&tmp, 0, sizeof (union exp_element));
-  tmp.doubleconst = expelt;
-  write_exp_elt (ps, &tmp);
-}
-
-void
-write_exp_elt_decfloatcst (struct parser_state *ps, gdb_byte expelt[16])
+write_exp_elt_floatcst (struct parser_state *ps, const gdb_byte expelt[16])
 {
   union exp_element tmp;
   int index;
 
   for (index = 0; index < 16; index++)
-    tmp.decfloatconst[index] = expelt[index];
+    tmp.floatconst[index] = expelt[index];
 
   write_exp_elt (ps, &tmp);
 }
@@ -870,8 +861,7 @@ operator_length_standard (const struct expression *expr, int endpos,
       break;
 
     case OP_LONG:
-    case OP_DOUBLE:
-    case OP_DECFLOAT:
+    case OP_FLOAT:
     case OP_VAR_VALUE:
     case OP_VAR_MSYM_VALUE:
       oplen = 4;
@@ -1338,69 +1328,23 @@ null_post_parser (struct expression **exp, int void_context_p)
 }
 
 /* Parse floating point value P of length LEN.
-   Return 0 (false) if invalid, 1 (true) if valid.
-   The successfully parsed number is stored in D.
-   *SUFFIX points to the suffix of the number in P.
+   Return false if invalid, true if valid.
+   The successfully parsed number is stored in DATA in
+   target format for floating-point type TYPE.
 
    NOTE: This accepts the floating point syntax that sscanf accepts.  */
 
-int
-parse_float (const char *p, int len, DOUBLEST *d, const char **suffix)
-{
-  char *copy;
-  int n, num;
-
-  copy = (char *) xmalloc (len + 1);
-  memcpy (copy, p, len);
-  copy[len] = 0;
-
-  num = sscanf (copy, "%" DOUBLEST_SCAN_FORMAT "%n", d, &n);
-  xfree (copy);
-
-  /* The sscanf man page suggests not making any assumptions on the effect
-     of %n on the result, so we don't.
-     That is why we simply test num == 0.  */
-  if (num == 0)
-    return 0;
-
-  *suffix = p + n;
-  return 1;
-}
-
-/* Parse floating point value P of length LEN, using the C syntax for floats.
-   Return 0 (false) if invalid, 1 (true) if valid.
-   The successfully parsed number is stored in *D.
-   Its type is taken from builtin_type (gdbarch) and is stored in *T.  */
-
-int
-parse_c_float (struct gdbarch *gdbarch, const char *p, int len,
-	       DOUBLEST *d, struct type **t)
+bool
+parse_float (const char *p, int len,
+	     const struct type *type, gdb_byte *data)
 {
-  const char *suffix;
-  int suffix_len;
-  const struct builtin_type *builtin_types = builtin_type (gdbarch);
-
-  if (! parse_float (p, len, d, &suffix))
-    return 0;
-
-  suffix_len = p + len - suffix;
-
-  if (suffix_len == 0)
-    *t = builtin_types->builtin_double;
-  else if (suffix_len == 1)
-    {
-      /* Handle suffixes: 'f' for float, 'l' for long double.  */
-      if (tolower (*suffix) == 'f')
-	*t = builtin_types->builtin_float;
-      else if (tolower (*suffix) == 'l')
-	*t = builtin_types->builtin_long_double;
-      else
-	return 0;
-    }
+  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+    return floatformat_from_string (floatformat_from_type (type),
+				    data, std::string (p, len));
   else
-    return 0;
-
-  return 1;
+    return decimal_from_string (data, TYPE_LENGTH (type),
+				gdbarch_byte_order (get_type_arch (type)),
+				std::string (p, len));
 }
 
 /* Stuff for maintaining a stack of types.  Currently just used by C, but
@@ -1808,8 +1752,7 @@ operator_check_standard (struct expression *exp, int pos,
     {
     case BINOP_VAL:
     case OP_COMPLEX:
-    case OP_DECFLOAT:
-    case OP_DOUBLE:
+    case OP_FLOAT:
     case OP_LONG:
     case OP_SCOPE:
     case OP_TYPE:
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index f7ba7f0..f43fb75 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -23,7 +23,6 @@
 #if !defined (PARSER_DEFS_H)
 #define PARSER_DEFS_H 1
 
-#include "doublest.h"
 #include "vec.h"
 #include "expression.h"
 
@@ -189,9 +188,7 @@ extern void write_exp_elt_sym (struct parser_state *, struct symbol *);
 
 extern void write_exp_elt_longcst (struct parser_state *, LONGEST);
 
-extern void write_exp_elt_dblcst (struct parser_state *, DOUBLEST);
-
-extern void write_exp_elt_decfloatcst (struct parser_state *, gdb_byte *);
+extern void write_exp_elt_floatcst (struct parser_state *, const gdb_byte *);
 
 extern void write_exp_elt_type (struct parser_state *, struct type *);
 
@@ -270,11 +267,8 @@ extern type_instance_flags follow_type_instance_flags ();
 
 extern void null_post_parser (struct expression **, int);
 
-extern int parse_float (const char *p, int len, DOUBLEST *d,
-			const char **suffix);
-
-extern int parse_c_float (struct gdbarch *gdbarch, const char *p, int len,
-			  DOUBLEST *d, struct type **t);
+extern bool parse_float (const char *p, int len,
+			 const struct type *type, gdb_byte *data);
 
 /* During parsing of a C expression, the pointer to the next character
    is in this variable.  */
diff --git a/gdb/rust-exp.y b/gdb/rust-exp.y
index 0cb185c..e372a6e 100644
--- a/gdb/rust-exp.y
+++ b/gdb/rust-exp.y
@@ -54,7 +54,7 @@ struct typed_val_int
 
 struct typed_val_float
 {
-  DOUBLEST dval;
+  gdb_byte val[16];
   struct type *type;
 };
 
@@ -173,10 +173,6 @@ static const char *number_regex_text =
 
 static regex_t number_regex;
 
-/* True if we're running unit tests.  */
-
-static int unit_testing;
-
 /* Obstack for data temporarily allocated during parsing.  Points to
    the obstack in the rust_parser, or to a temporary obstack during
    unit testing.  */
@@ -1068,11 +1064,6 @@ rust_type (const char *name)
 {
   struct type *type;
 
-  /* When unit testing, we don't bother checking the types, so avoid a
-     possibly-failing lookup here.  */
-  if (unit_testing)
-    return NULL;
-
   type = language_lookup_primitive_type (current_parser->language (),
 					 current_parser->arch (),
 					 name);
@@ -1586,8 +1577,11 @@ lex_number (void)
     }
   else
     {
-      rustyylval.typed_val_float.dval = strtod (number.c_str (), NULL);
       rustyylval.typed_val_float.type = type;
+      bool parsed = parse_float (number.c_str (), number.length (),
+				 rustyylval.typed_val_float.type,
+				 rustyylval.typed_val_float.val);
+      gdb_assert (parsed);
     }
 
   return is_integer ? (could_be_decimal ? DECIMAL_INTEGER : INTEGER) : FLOAT;
@@ -1716,7 +1710,7 @@ ast_dliteral (struct typed_val_float val)
 {
   struct rust_op *result = OBSTACK_ZALLOC (work_obstack, struct rust_op);
 
-  result->opcode = OP_DOUBLE;
+  result->opcode = OP_FLOAT;
   result->left.typed_val_float = val;
 
   return result;
@@ -2181,11 +2175,11 @@ convert_ast_to_expression (struct parser_state *state,
       write_exp_elt_opcode (state, OP_LONG);
       break;
 
-    case OP_DOUBLE:
-      write_exp_elt_opcode (state, OP_DOUBLE);
+    case OP_FLOAT:
+      write_exp_elt_opcode (state, OP_FLOAT);
       write_exp_elt_type (state, operation->left.typed_val_float.type);
-      write_exp_elt_dblcst (state, operation->left.typed_val_float.dval);
-      write_exp_elt_opcode (state, OP_DOUBLE);
+      write_exp_elt_floatcst (state, operation->left.typed_val_float.val);
+      write_exp_elt_opcode (state, OP_FLOAT);
       break;
 
     case STRUCTOP_STRUCT:
@@ -2675,7 +2669,10 @@ rust_lex_tests (void)
   scoped_restore obstack_holder = make_scoped_restore (&work_obstack,
 						       &test_obstack);
 
-  unit_testing = 1;
+  // Set up dummy "parser", so that rust_type works.
+  struct parser_state ps;
+  initialize_expout (&ps, 0, &rust_language_defn, target_gdbarch ());
+  rust_parser parser (&ps);
 
   rust_lex_test_one ("", 0);
   rust_lex_test_one ("    \t  \n \r  ", 0);
@@ -2764,8 +2761,6 @@ rust_lex_tests (void)
 
   rust_lex_test_completion ();
   rust_lex_test_push_back ();
-
-  unit_testing = 0;
 }
 
 #endif /* GDB_SELF_TEST */
diff --git a/gdb/std-operator.def b/gdb/std-operator.def
index 344ba25..58ef899 100644
--- a/gdb/std-operator.def
+++ b/gdb/std-operator.def
@@ -114,9 +114,9 @@ OP (MULTI_SUBSCRIPT)
    Thus, the operation occupies four exp_elements.  */
 OP (OP_LONG)
 
-/* OP_DOUBLE is similar but takes a DOUBLEST constant instead of a
-   long.  */
-OP (OP_DOUBLE)
+/* OP_FLOAT is similar but takes a floating-point constant encoded in
+   the target format for the given type instead of a long.  */
+OP (OP_FLOAT)
 
 /* OP_VAR_VALUE takes one struct block * in the following element,
    and one struct symbol * in the following exp_element, followed
@@ -325,11 +325,6 @@ OP (OP_OBJC_NSSTRING)
    ":exp" and ":").  */
 OP (OP_RANGE)
 
-/* OP_DECFLOAT is followed by a type pointer in the next exp_element
-   and a dec long constant value in the following exp_element.
-   Then comes another OP_DECFLOAT.  */
-OP (OP_DECFLOAT)
-
 /* OP_ADL_FUNC specifies that the function is to be looked up in an
    Argument Dependent manner (Koenig lookup).  */
 OP (OP_ADL_FUNC)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]