Как подавить предупреждение: контроль достигает конца непустой функции

У меня есть код сборки PowerPC, переведенный с помощью кросс-компилятора gcc с этой функцией:

uint32_t fill_cache(void)
{
    __asm__ ("addi 3, 0, 0\n");  /* R3 = 0 */
    /* More asm here modifying R3 and filling the cache lines. */
}

который в рамках PowerPC EABI возвращает значение, вычисленное в R3. При компиляции получаю

foo.c:105: warning: control reaches end of non-void function

Есть ли способ научить gcc, что значение действительно возвращается? Или есть способ подавить предупреждение (без удаления -Wall или добавления -Wno- *)? Я хотел бы очень выборочно подавить это предупреждение только для этой функции, чтобы оставить общий уровень предупреждения как можно более высоким.

Невозможно заставить эту функцию возвращать значение void, поскольку вычисленное значение требуется вызывающей стороне.


person Jens    schedule 10.04.2013    source источник


Ответы (2)


Решение 1: с помощью диагностических прагм вы можете локально подавить определенные диагностические проверки. . Конкретный вариант (который также подразумевается -Wall), который жалуется на отсутствие возврата в непустой функции, - это -Wreturn-type. Итак, конкретный код для подавления предупреждения:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type"
/* Your code here */
#pragma GCC diagnostic pop

Вы можете узнать, какой параметр вызывает предупреждение, скомпилировав его с помощью -fdiagnostics-show-option. Он просто добавит параметр к предупреждающему сообщению.

Решение 2. определите регистровую переменную и поместите ее в желаемый реестр. Обратитесь к переменной в встроенном шаблоне ассемблера с полученным кодом:

uint32_t fill_cache(void)
{
  register uint32_t cacheVal __asm__ ("r3");

  __asm__ __volatile__ ("addi %0, 0, 0" : "=r" (cacheVal));
  /* More code here */

  return cacheVal;
}

Модификатор volatile предназначен для того, чтобы гарантировать, что инструкция не будет удалена или каким-либо иным образом нежелательно затронута стратегией оптимизации.

Решение 2 является предпочтительным как минимум по двум причинам:

  1. Значение невозвращаемой непустой функции не определено в соответствии со стандартом.
  2. Нет риска подавления (новых) диагностических предупреждений, которые изначально не планировалось подавлять.
person Robert Johansson    schedule 10.04.2013

Функция может быть объявлена ​​как naked, в этом случае компилятор не будет генерировать пролог и эпилог и будет предполагать, что программист сохраняет все необходимые регистры и помещает выходное значение в правильные регистры перед возвратом.

uint32_t fill_cache(void) __attribute__((naked)); // Declaration
// attribute should be specified in declaration not in implementation

uint32_t fill_cache(void) 
{
    __asm__ ("addi 3, 0, 0\n");  /* R3 = 0 */
    /* More asm here modifying R3 and filling the cache lines. */
}

Немного поздно, но, может быть, кто-то вмешается и в это :)

PS: Насколько я знаю, синтаксис __asm__ и __volatile__ - это std=c89. Практически нет разницы между __asm__ и asm в GNU GCC. Но современный подход - это стиль без подчеркивания: asm volatile.

asm_language

person user3124812    schedule 06.03.2017