適用範囲:Arm Compiler 6
概要:
inline または__inline__ をプロジェクト内でキーワードとしてインライン関数定義に使用した場合、Arm Compiler 6でビルドをするとarmlink がundefined reference エラーを返します。
例えば、以下のようなコードを例に挙げると:
foo.c
inline int add(int i, int j) {
return i + j;
}
int main(void) {
int i = add(4, 5);
return i;
}
return i + j;
}
int main(void) {
int i = add(4, 5);
return i;
}
以下のコマンドでfoo.cをビルドすると:
armclang --target=arm-arm-none-eabi -mcpu=cortex-m7 foo.c -c -o foo.o
armlink --cpu=cortex-m7 foo.o -o foo.axf
armlink --cpu=cortex-m7 foo.o -o foo.axf
リンカが以下のエラーを返します。
Error: L6218E: Undefined symbol add (referred from foo.o)
注意:この内容はインライン関数定義に__attribute__((always_inline)) 使用時には適用されません。
回答:
この問題は以下の理由により発生します:
- 関数をキーワードinline または__inline__ で修飾すると、その関数をインライン展開する必要があることをコンパイラに提示しますが、最終的な決定はコンパイラで行われます。-O0または-O1 でコンパイルすると、ほとんどの場合、コンパイラはそのような関数をインライン化しません。
- armclang は、inline キーワードに対し、標準C99 セマンティクスを使用します。C99 では、inline は、関数の定義がインライン展開のためだけに提供され、プログラムのどこか別の場所に(インライン展開されていない)別の定義があることを意味します。つまり、foo.c のサンプルコードはC99 では不完全なものとなります。add() がインライン化されない場合、main() はインライン化されていない欠落した定義への未解決参照を持っていることになります。
解決策: この問題を解消するためには以下のいずれかの回避策を使用してください:
- inline または__inline__ キーワードを使用しない同等の関数を実装します。
- inline または__inline__ キーワードをstatic inline に変更します。
- inline または__inline__ キーワードは、コンパイラへの提案としてのみ機能するため、削除します。
- -std=gnu90 オプションを使用して、GNU C90 言語モードでコンパイルします。