Я пишу очень простой компилятор, в котором пользователям разрешено определять функции, которые возвращают либо void
, int
, либо char
.Тем не менее, функция пользователя может быть нарушена.Они могут не возвращать значение для функции, которая не возвращает void
, или возвращать значение для функции, которая возвращает void
, как объявлено.В настоящее время мой компилятор не может обнаружить ошибки такого рода и не может создать правильный код для функции, которая возвращает void
, поскольку этот класс функций может возвращаться без return;
(они возвращаются неявно).Эти две проблемы стоили мне довольно много времени, чтобы четко их сформулировать.Смотрите пример кода ниже:
// Problem A: detect implicit return.
void Foo(int Arg) {
if (Arg)
return;
else {
Arg = 1;
// Foo returns here! How can I know!
}
}
// Problem B: detect "forgotten return".
int Bar(int Arg) {
if (Arg > 1) {
return 1;
}
// this is an error: control flow reaches end at non-void function!
// How can I know!
}
Я думаю, что более общий вопрос может быть: как я могу сказать, что поток управления достигает конца в некоторой точке функции?Говоря достичь конца я имею в виду, что он достигает точки, после которой у функции нет кода для выполнения.Если я могу определить конец потока управления, я могу найти return
в этой точке и либо сообщить об ошибке, если функция должна что-то вернуть, либо сгенерировать явное return
для функции void
.Если я перечислю все такие точки функции, я смогу убедиться, что функция полностью проверена или дополнена.
Я считаю эту проблему хорошо решенной в инженерии компиляторов, поскольку современный C / C ++ может сделать это довольноЧто ж.LLVM
может предложить какой-либо API для этого?Или есть простой алгоритм для достижения этой цели?Большое спасибо.
Редактировать: В настоящее время я использую LLVM
и уже BasicBlock
испущено.Я надеюсь, что руководство сделает это особенно в LLVM
.
Edit: В этом вопросе мы предполагаем, что тип возвращаемого значения, объявленный в прототипе функции всегда , соответствует этомуего return
stmt.Я в первую очередь сосредотачиваюсь на отсутствии необходимого return
.