Everything
11.10 Usage of math.h functions (frexp, ldex, scalbn and remquo) in C++ language (including EC++)

When certain arguments of the frexp, ldexp, scalbn, and remquo functions in math.h are of the int type, compiling the C++ or EC++ program generates object code that will enter an endless loop.

 

Conditions:

This problem occurs when both (1) and (2) are satisfied.

(1)

The program is in C++ or the -lang=cpp option is effective.

(2)

math.h is included and any of the following functions is called.

(a)

frexp(double, long*) with 'int *' type second argument (except when the first argument is float-type and the
-dbl_size=8 option is effective).

(b)

lldexp(double, long) with int type second argument (except when the first argument is float-type and the
-dbl_size=8 option is effective).

(c)

scalbn(double, long) with int type second argument (except when the first argument is float-type and the
-dbl_size=8 option is effective).

(d)

remquo(double, double, long*) with 'int *' type third argument (except when the both the first and second
arguments are float-type and the -dbl_size=8 option is effective).

 

Examples:

file.cpp:

  // Example of compiling C++ source that generates an endless loop
  #include <math.h>
  double d1,d2;
  int i;
  void func(void)
  {
    d2 = frexp(d1, &i);
  }

 

Command Line:

  ccrx -cpu=rx600 -output=src file.cpp

 

file.src: Example of the generated assembly program

  _func:
    ; ...(Omitted)
      ; Calling substitute function of frexp
    BSR __$frexp__tm__2_f__FZ1ZPi_Q2_21_Real_type__tm__4_Z1Z5_Type
    ; ...(Omitted)
 
  __$frexp__tm__2_f__FZ1ZPi_Q2_21_Real_type__tm__4_Z1Z5_Type:
  L11:
    BRA L11 ; Calls itself ==> endless loop

 

Countermeasures:

Select one of the following ways to avoid the problem.

(1)

Compile the program with the -lang=c or -lang=c99 option.

(2)

Change int and int * into long and long *.

(3)

Append the following declarations to each function that is being used.

      /* For the frexp function */
      static inline double frexp(double x, int *y)
      { long v = *y; double d = frexp(x,&v); *y = v; return (d); }
      /* For the ldexp function */
      static inline double ldexp(double x, int y)
      { long v = y; double d = ldexp(x,v); return (d); }
      /* For the scalbn function */
      static inline double scalbn(double x, int y)
      { long v = y; double d = scalbn(x,v); return (d); }
      /* For the remquo function */
      static inline double remquo(double x, double y, int *z)
      { long v = *z; double d = remquo(x,y,&v); *z = v; return (d); }

 

Example of (2):

Change in file.cpp:

  #include <math.h>
  double d1,d2;
  int i;
  void func(void)
  {
    long x = i; /* Accept as long type temporary */
    d2 = frexp(d1, &x); /* Call with long type argument */
    i = x; /* Set the result for variable 'i' */
  }

 

Example of (3):

Change in file.cpp:

  #include <math.h>
  /* Append declaration */
  static inline double frexp(double x, int *y)
  { long v = *y; double d = frexp(x,&v); *y = v; return (d); }
  double d1,d2;
  int i;
  void func(void)
  {
    d2 = frexp(d1, &i);
  }