I disagree in that I'm splitting hairs and it's friday and I feel like
posting.
This must be Friday. I never could get the hang of Fridays.
It's well defined what the default promotions are so calling pow()
without a prototype is not UB. What pow() does with it's parameters
is UB.
The hair, I think, remains un-split (thanks to that expensive
shampoo-conditioner-gunk the salon employee applied.)
The Standard says only that "the behavior is undefined" when
the faulty call executes, not that the behavior is defined up to
some specified moment and undefined thereafter. There's no way
to decide whether the call is OK and the UB only begins somewhere
inside pow(), or whether the call itself goes off the rails. Nor
can I see that such a localization of UB would make any difference,
since it's clear that UB has occurred by the time pow() returns to
the caller (if it returns at all).
It is possible, though silly, to call pow() without a prototype
and have well-defined behavior. Two conditions must be met:
- The type of the function pointer in the calling expression
must be compatible with the actual type of pow(). Since the
actual pow() returns a double, and since an undeclared pow()
is assumed to return an int (in C90), pow() must be declared
prior to the point of the call. The original code did not
declare pow() at all, so it gets UB.
- The number and as-promoted types of the argument expressions
must be compatible with the actual parameters of pow(). Since
pow() takes two doubles, two double arguments must be supplied
(because no other type promotes to double). The original code
provides two int values, which do not promote to doubles --
once again, we have UB.
;-)