2015-02-06 4 views
9

gcc documentation содержит следующее:Звонки, которые предшествуют определению функции, не могут быть встроены?

Когда функция как встроенная и статического, если все вызовы функции интегрированы в вызывающем, и адресе функции является никогда не используется, то собственный ассемблер функции в код никогда не указан . В этом случае GCC фактически не выводит код ассемблера для этой функции, если вы не укажете опцию -fkeep-inline-functions. Некоторые вызовы не могут быть интегрированы по разным причинам (в частности, звонки, которые предшествуют определению функции не могут быть интегрированы, а также не могут быть рекурсивными вызовами в определении ).

Это всегда звучало абсурдно для меня - почему современный компилятор был бы таким глупым? После быстрого теста это кажется неверным.

Тест Код:

static inline int foo(); 

int bar() { 
    return foo(); 
} 

int foo() { 
    return 42; 
} 

В результате с GCC-4.9.2 на Linux содержит код для bar() но ни для foo(). Вы можете видеть, что foo() была интегрирована:

bar: 
.LFB0: 
    .cfi_startproc 
    movl $42, %eax 
    ret 
    .cfi_endproc 

Если я компилировать в C++ результат тот же, за исключением имени коверкая.

В отличие от документации, несмотря на foo() определяется после вызова в bar(), foo() был полностью интегрирован в bar().

Я неправильно понимаю документацию или она неверна? Возможно, это правильно для более сложного случая?

Я не знаю, существует ли техническое различие между «интеграцией» и «встроенным», но я подозреваю, что «интеграция» используется для отличия от ключевого слова inline, и оно просто ссылается на функцию inline (следовательно, название).

Этот вопрос отмечен как C и C++, потому что эта часть документации gcc относится к «семейству языков C», и я ожидаю, что ответ будет одинаковым для двух языков.

+5

Это предложение уже присутствует в документации gcc 3.0.4. Вероятно, они улучшили компилятор без изменения документации. – AProgrammer

+0

Да. Кажется, это не соответствует тому, что на самом деле происходит. Хотя, я пробовал и на 4.8.1 - такое же поведение. – SGrebenkin

+3

Это даже в документации gcc 2.95.3. – Praxeolitic

ответ

7

Gcc используется для компиляции и оптимизации одной функции за раз, как только они были разобраны, перед разбором следующего. IIRC, только в 4-х часовом периоде они представили опцию -funit-at-a-time, которая отложила оптимизацию до того, как прочитала весь блок компиляции, а затем они ожидали некоторых выпусков, чтобы включить ее по умолчанию.

Возможность включения функции, определенной после вызова, вероятно, будет представлена ​​как часть работы -funit-at-a-time, а документация встроенного (упоминание о вызовах, предшествующих определению, датируется как минимум до 2,95), не обновлялось.