Основная проблема заключается в том, что диагностика компилятора имеет дело с вещами, которые вы не написали .
Чтобы вы получили значимое сообщение об ошибке, компилятор должен угадать, что вы имели в виду , а затем сказать вам, чем ваш код отличается от этого.
Если вы пропустите точку с запятой, компилятор, очевидно, нигде не увидит эту точку с запятой. Конечно, одна из вещей, которые он может сделать, это угадать: «Может быть, пользователь пропустил точку с запятой. В конце концов, это распространенная ошибка». Но где должна быть эта точка с запятой? Поскольку вы допустили ошибку, код не может быть проанализирован в синтаксическом дереве, поэтому нет четкого индикатора, что «этот узел отсутствует в дереве». И может быть более одного места, где точка с запятой может быть вставлена так, чтобы окружающий код был правильно проанализирован. И более того, сколько кода вы собираетесь попытаться проанализировать / перекомпилировать, как только обнаружите, в чем может быть ошибка? Компилятор может вставить точку с запятой, но, по крайней мере, он должен перезапустить анализ этого блока кода. Но, возможно, это привело к ошибкам в коде. Так что, возможно, следует перекомпилировать всю программу, просто чтобы убедиться, что исправление, предложенное компилятором, было действительно правильным. Но вряд ли это вариант. Это занимает слишком много времени.
Скажем, у вас есть такой код:
struct foo {
...
}
void bar();
в чем здесь ошибка? Глядя на это, мы с тобой скажем: «Тебе не хватает точки с запятой после определения класса». Но как компилятор может сказать? void
может быть опечаткой. Возможно, вы действительно намеревались написать имя экземпляра типа foo
. тогда настоящая ошибка заключается в том, что за этим следует то, что сейчас выглядит как вызов функции.
Так что компилятор должен угадать. «Похоже, что это могло быть определением класса, и то, что следует за ним, выглядит как имя типа. Если это так, пользователь пропускает точку с запятой для их разделения».
И гадание не очень точная наука. И это еще более усложняется тем, что каждый раз, когда компилятор пытается быть умным и делает предположение, это только добавляет путаницы, если предположение неверно.
Поэтому иногда может быть лучше вывести короткое, краткое сообщение, в котором говорится только то, в чем мы уверены (скажем, что за определением класса не может следовать имя типа). Это не так полезно, как сказать «вы пропустили точку с запятой после определения класса», но это менее вредно, если компилятор угадает неправильно.
Если вам сообщают, что вы пропустили точку с запятой, а ошибка была на самом деле чем-то другим, это просто вводит вас в заблуждение. Поэтому, возможно, краткое и менее полезное сообщение об ошибке лучше в худшем случае, даже если в лучшем случае оно не так приятно.
Написание хороших ошибок компилятора нелегко, особенно на таком грязном языке, как C ++.
Но когда это сказано, некоторые компиляторы (включая MSVC и GCC) могут быть намного лучше. Я считаю, что лучшая диагностика компилятора - одна из основных целей Clang.