Solution 1:

It's UB because it's not worded in terms of loops, but in terms of (1.10p24):

The implementation may assume that any thread will eventually do one of the following:

  • terminate,
  • make a call to a library I/O function,
  • access or modify a volatile object, or
  • perform a synchronization operation or an atomic operation.

This applies to both, as opposed to the more older formulation in one of the C++0x drafts. (See this question for discussions).

Note that disregarding of that, the behavior can easily be undefined if the recursion exceeds the implementation limit of the number of nested recursive function calls. That has always been the case.

Solution 2:

I don't think the standard says the behavior is undefined, it just says a loop that has no side effects may be assumed to eventually terminate.

So:

int main() {
   while (true) {}
}

May terminate or loop forever.

void foo() {
   foo();
}

int main() {
   foo();
}

May also terminate, loop forever, or possibly run out of stack space (if the compiler does not implement tail recursion).

I don't think either have any right to do anything other than listed, so I don't think the behavior is completely "undefined".