я не претендую на експерта по знанию стандарта но существует банальная цепочка россуждений которая и приводит меня к моему представлению:
1) елементы массивов идут последовательно даже если елементом масива выступает масив
2) прибавление числа к указателю на некоторый тип смешает указатель на это число
3) разыменование указателя указываюшего на кусок памяти выделеный под вашу програму ub вызвать не способно по определению
что мы имеем с точки зрения компилятора в foo перебор некоторых указателей, на легальной области памяти, да формально мы вышли за пределы масива, он должен состоять из 5ти елементов, но дальше идет память точно так же принадлежащая нам, и компилятор не имеет ничего против, он не анализирует как ты пришел к этому адресу, его волнует только принодлежит эта память тебе или нет, а память принадлижит тебе (смотри пункт первый) так что array + i, ошибка только И ТОЛЬКО логического характера...
Это может быть сколько угодно ошибка логического характера, конечно. Однако undefined behaviour существует для того, чтобы предоставить разработчикам компиляторов возможность для оптимизации. Есть и иные причины, конечно, в виде действительно серьёзных проблем. Однако в целом, основная суть UB в том, что после появления такого в коде это не программа на С++. Стандарт больше не предоставляет никаких гарантий на поведение данного кода. А так как разработчики компиляторов на это закладывается, компилятор может просто выкинуть код, который содержит UB. Кто-то может считать здравым хождение под двумерному массиву как одномерному, кто-то нет, однако в целом, считайте, это зависит от того, кто писал данный кусок компилятора, насколько он хотел соответствовать стандарту и т.д. И если вы отрицаете это, то не удивляйтесь, если в каком-то, пусть совершенно редком случае, но ваш код сделает непонятно что, пусть даже "ну совершенно нет на это причин"