Topic: Value-returning functions & exceptions


Author: jpsa@apollo.uk.gdscorp.com (John Aldridge)
Date: 1996/05/21
Raw View
A week ago I asked whether a compiler was entitled to refuse to compile
code like:

   int fred (void) { throw "Wrong type"; }

on the grounds that it does not return a value.

I got one response (from jason@cygnus.com) saying that the code was
legal and should compile, and another (from clamage@eng.sun.com) saying
that the behaviour was undefined.

Since it seems that the existing wording in the WP is open to
misinterpretation, can I ask the committee members reading this
to get the wording clarified?

Thanks,
John
jpsa@uk.gdscorp.com


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Rob Stewart <stew@datalytics.com>
Date: 1996/05/21
Raw View
John Aldridge wrote:
>
> The HP C++ compiler issues an error message and refuses to generate
> code when a function declared to return a value actually always
> returns by throwing an exception.  This can easily occur in real code
> in cases like the following:
>
>    class P {
>    public:
>       virtual int fred (void) { throw "Wrong type"; }
>    };[snipped derived classes]
>
> which gives the messages:
>
>    CC: "z.cc", line 1: error: no value returned from P::fred() (1404)
>
> HP's response to my logging this as a fault was:
> [snip]
>
> Are they right?

Other replies have answered the "are they right?" question.  Let
me explain a workaround, since you need to compile code in the
meantime.

After throwing your exception, add a dummy line that returns a
value.  In P::fred, add "return 0;" or something after 'throw
"Wrong Type";.'

--
Robert Stewart  | My opinions are usually my own.
Datalytics, Inc. | stew@datalytics.com
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: jason@cygnus.com (Jason Merrill)
Date: 1996/05/22
Raw View
>>>>> John Aldridge <jpsa@apollo.uk.gdscorp.com> writes:

> A week ago I asked whether a compiler was entitled to refuse to compile
> code like:

>    int fred (void) { throw "Wrong type"; }

> on the grounds that it does not return a value.

> I got one response (from jason@cygnus.com) saying that the code was
> legal and should compile, and another (from clamage@eng.sun.com) saying
> that the behaviour was undefined.

I don't think Steve and I were disagreeing.  The behavior is undefined if
and only if control flows off the end of the function, a condition which is
not always decidable.  The compiler can only give a compile-time error
(one of the valid interpretations of undefined behavior) if it can be
*sure* that control will, in fact, flow off the end of the function.  This
is obviously not the case for your example.

The wording was changed from ill-formed (in the ARM) to undefined (now)
because compilers can't always determine whether or not control will flow
off the end of the function (such a test being equivalent to the halting
problem), so they were being over-conservative, giving an error for code
where it does not happen.  Now compilers are free to ignore this condition,
though good ones will give a warning, or perhaps an error for blatant
situations like

 int fred (void) { 2*2; }

Jason
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Nathan Myers <ncm@cantrip.org>
Date: 1996/05/22
Raw View
John Aldridge wrote:
>
> A week ago I asked whether a compiler was entitled to refuse to compile
> code like:
>
>    int fred (void) { throw "Wrong type"; }
>
> on the grounds that it does not return a value.
>
> I got one response (from jason@cygnus.com) saying that the code was
> legal and should compile, and another (from clamage@eng.sun.com) saying
> that the behaviour was undefined.

The effect is undefined if you run off the end of the function,
but you aren't doing that; you are throwing before you get to
the end.  This is legal, and a compiler might warn that you have
no return statement, but must accept the code.

Nathan Myers
ncm@cantrip.org
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jpsa@apollo.uk.gdscorp.com (John Aldridge)
Date: 1996/05/14
Raw View
The HP C++ compiler issues an error message and refuses to generate
code when a function declared to return a value actually always
returns by throwing an exception.  This can easily occur in real code
in cases like the following:

   class P {
   public:
      virtual int fred (void) { throw "Wrong type"; }
   };

   class D1: public P {
   public:
      // Inherit P's failure behaviour for fred()
   };

   class D2: public P {
   public:
      virtual int fred (void) { return 42; } // Ah - this one does something
   };

which gives the messages:

   CC: "z.cc", line 1: error: no value returned from P::fred() (1404)

HP's response to my logging this as a fault was:

>  I think this is a user misunderstanding.  Throwing an exception
>  does not fulfill the requirement of returning a value.  Functions
>  that are declared to return a value must return a value.

>  In C++, the absence of a return value from a function that is
>  declared to return a value is a compile time error; see 6.6.3 in
>  the ARM.  (In ANSI C, this behavior is undefined.)

>  Throwing an exception does not satisfy this requirement.

Are they right?

Cheers,
John Aldridge
jpsa@uk.gdscorp.com
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jason@cygnus.com (Jason Merrill)
Date: 1996/05/14
Raw View
>>>>> John Aldridge <jpsa@apollo.uk.gdscorp.com> writes:

> HP's response to my logging this as a fault was:

>> In C++, the absence of a return value from a function that is
>> declared to return a value is a compile time error; see 6.6.3 in
>> the ARM.  (In ANSI C, this behavior is undefined.)

> Are they right?

No.  The words used (even in the ARM) are "flowing off the end", which does
not happen if you throw an exception.  Also, 'illegal' in the ARM has been
changed to 'undefined behavior' in the latest draft.

  6.6.3  The return statement                              [stmt.return]

            Flowing  off the end of a
  function is equivalent to a return with  no  value;  this  results  in
  undefined behavior in a value-returning function.

Jason


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: clamage@Eng.sun.com (Steve Clamage)
Date: 1996/05/14
Raw View
In article fsf@yorick.cygnus.com, jason@cygnus.com (Jason Merrill) writes:
>>>>>> John Aldridge <jpsa@apollo.uk.gdscorp.com> writes:
>
>> HP's response to my logging this as a fault was:
>
>>> In C++, the absence of a return value from a function that is
>>> declared to return a value is a compile time error; see 6.6.3 in
>>> the ARM.  (In ANSI C, this behavior is undefined.)
>
>> Are they right?
>
>No.  The words used (even in the ARM) are "flowing off the end", which does
>not happen if you throw an exception.  Also, 'illegal' in the ARM has been
>changed to 'undefined behavior' in the latest draft.

I believe the intent is even for the example cases to have undefined
behavior. In general, the compiler cannot determine whether the function
will flow off the end (it involves solving the halting problem), and so
should not be required to make that evaluation. Example:

 int foo()
 {
  if( sqrt(2.0) < 2.0*cos(0.0) ) {
   throw "up";
 }

Should the compiler be required to determine that the condition is
always true and so no return is needed?
---
Steve Clamage, stephen.clamage@eng.sun.com




[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: jpsa@apollo.uk.gdscorp.com (John Aldridge)
Date: 1996/05/15
Raw View
In article <4nb2m6$9lo@engnews1.Eng.Sun.COM>, clamage@Eng.sun.com
(Steve Clamage) writes:

>>>>>>> John Aldridge <jpsa@apollo.uk.gdscorp.com> writes

   :
   virtual int fred (void) { throw "Wrong type"; }
   :

>>> HP's response to my logging this as a fault was:
>>
>>>> In C++, the absence of a return value from a function that is
>>>> declared to return a value is a compile time error; see 6.6.3 in
>>>> the ARM.  (In ANSI C, this behavior is undefined.)
>>
>>> Are they right?
>
> I believe the intent is even for the example cases to have undefined
> behavior. In general, the compiler cannot determine whether the function
> will flow off the end (it involves solving the halting problem), and so
> should not be required to make that evaluation. Example:
>
>  int foo()
>  {
>   if( sqrt(2.0) < 2.0*cos(0.0) ) {
>    throw "up";
>  }
>
> Should the compiler be required to determine that the condition is
> always true and so no return is needed?

It would clearly be unreasonable to require the compiler to determine
at compile time whether control will flow off the end of a function.

However, at least in my reading of the ARM and the April WP, the
undefined behaviour is only provoked if control does, in fact, flow
off the end.

In other words, the onus is the other way round - the compiler is not
entitled to refuse to compile the code unless its flow control analysis
is sophisticated enough to prove that control definitely _will_ flow
off the end.

[Note - the compiler is not issuing a warning message and continuing,
but an error message without a resulting ".o" file].

Cheers,
John
jpsa@uk.gdscorp.com
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]