Получить предупреждение компиляции в правильном положении (`gcc`) - PullRequest
0 голосов
/ 30 января 2019

В в этом примере, приведенном в действие Godbolt и воспроизведенном ниже, можно создать функцию, которая требует, чтобы ее параметры соответствовали некоторым условиям (i >= 0), ptr != NULL и т. Д.

// EXPECT() : will trigger a warning if the condition is not guaranteed
#define EXPECT(c)  (void)((c) ? (void)0 : never_reach())

// assume() : tell the compiler that `cond` is true
// note : only works for simple conditions, such as `i>=0`.
// Avoid complex conditions invoking functions.
#define assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)


// *********************************************************
// Function declaration
// *********************************************************

int positive_plus1_body(int v); 
#define positive_plus1_preconditions(v)   ((v)>=0)     // Let's first define the preconditions. 
                                                       // Name is long, because conditions must be unique to the function

// The inlined function express the contract, with both pre and post conditions.
// `inline` is essential, so that actual input values get verified,
// and result gets enriched with `assume` conditions.
// Problem is, the error is now located INTO the inlined function, not at the place where it's called.
// This makes it very hard to identify where the problem happens.
static inline int positive_plus1(int v)                // Ideally, this function should also have additional attribute to not trigger warnings when it's not invoked
{
    int r;
    EXPECT(positive_plus1_preconditions(v));           // preconditions
    r = positive_plus1_body(v);
    assume(r > 0);                                     // postconditions
    return r;
}

Пример Godbolt live позволяет вызвать функцию с хорошими и неправильными параметрами и засвидетельствовать влияние на диагностику компиляции.

Если вызывающая сторона не соблюдает условия,Компилятор генерирует предупреждение.Это довольно удобно, чтобы сразу обнаружить нарушения условий.Обычной альтернативой является использование assert() внутри тела функции, но она использует тесты во время выполнения для выявления потенциальных нарушений условий, которые менее очевидны и менее достоверны.

Проблема в том, что если функция inlineвызванный с неправильными аргументами, компилятор найдет нарушение условия внутри функции inline.Этот диагноз имеет ограниченную полезность.Вместо этого мы хотели бы прочитать строку, в которой функция inline вызывается с неверными аргументами.

Обходной путь - использовать вместо этого макрос.Однако макрос вызовет известную проблему множественной оценки, поскольку его аргументы должны использоваться несколько раз.Это достаточно опасно, чтобы избежать этого.Кроме того, инкапсулирующая функция inline может быть автоматически сгенерирована с помощью макроса, но макрос не может быть сгенерирован другим макросом.

Другое решение состоит в использовании выражения оператора , которое решаетмульти-оценка проблемы.Однако он непереносим и по-прежнему является макросом, поэтому он не может быть сгенерирован другим макросом.

Было бы предпочтительно сохранить функцию inline в этом примере, если это возможно.Но генерация правильного номера строки, где происходит нарушение условия, очень важна.Есть ли способ достичь этого, сохранив функциональный подход inline?

...