web-dev-qa-db-ja.com

clangでは、関数ごとの最適化属性をどのように使用しますか?

memset()への特定のセキュリティ関連の呼び出しが最適化されないようにするために、clangを使用して最適化せずに特定の関数をコンパイルしようとしています。

ここにあるドキュメント によると、これを可能にするoptnone属性が存在します。また、 例はここにあります

残念ながら(少なくとも以下のバージョンのclang、OS X 10.9.5では)、この例に見られるように、これがコンパイラの警告を引き起こしています。

$ clang --version
Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn)
Target: x86_64-Apple-darwin13.4.0
Thread model: posix

$ cat optnone.c
#include <string.h>

__attribute__((optnone)) void*
always_memset(void *b, int c, size_t len)
{
    return memset(b, c, len);
}

$ clang -Wall -O3 -c -o optnone.o optnone.c
optnone.c:3:16: warning: unknown attribute 'optnone' ignored [-Wattributes]
__attribute__((optnone)) void*
               ^
1 warning generated.

#pragma clang optimize offも使用してみましたが、unknown pragma ignoredの警告が発生しました。

なぜこれが機能しないのか誰かが知っていますか?この機能を使用するための前提条件を見逃しましたか? (-std=c11gnu11c99など、さまざまなgnu99パラメーターも使用してみましたが、動作は変わりませんでした。)

11
mpontillo

Clangのドキュメントにあるように、

ClangはGCCのgnu属性名前空間をサポートしています。 __attribute__((foo))構文で受け入れられるすべてのGCC属性は、[[gnu::foo]]としても受け入れられます。これは、GCCによって指定された属性にのみ拡張されます(GCC関数属性、GCC変数属性、およびGCCタイプ属性のリストを参照してください)。 GCC実装と同様に、これらの属性は宣言内のdeclarator-idに関連付けられている必要があります。つまり、宣言の開始時または名前が宣言された直後に配置する必要があります。

試してみてください

void* always_memset(void *b, int c, size_t len) [[gnu::optimize(0)]]

または

void* always_memset(void *b, int c, size_t len) __attribute__ ((optimize("0")));
6
EvgeniyZh

@dulaccがコメントで提唱しているように、__attribute__ ((optnone))はMacのHighSierraのclang9.0.0で動作します。

4
Paul Price