Fundo
Nota: Isso não é importante para a questão
Tenho algumas macros que agem como uma versão um pouco mais geral de atributos, que anexo a funções. Dependendo do compilador e da versão do compilador, elas se expandirão para um atributo (por exemplo, __attribute__((nonnull))
) ou um aviso (por exemplo, _Pragma("message \"nonnull attribute unavailable\"")
). Como as macros de atributos podem estar em qualquer ordem, isso pode levar a que sejam misturadas (por exemplo, aviso atributo atributo aviso aviso).
O resultado é que posso ter um código como o seguinte:
Amostra
#pragma message "one"
__attribute__((cold))
#pragma message "two"
__attribute__((noreturn))
#pragma message "three"
void test(void);
Emitir
Executando clang
, este código de exemplo compila perfeitamente, imprimindo as três mensagens conforme o esperado.
input.c:1:9: warning: one [-W#pragma-messages]
#pragma message "one"
^
input.c:3:9: warning: two [-W#pragma-messages]
#pragma message "two"
^
input.c:5:9: warning: three [-W#pragma-messages]
#pragma message "three"
^
Executar gcc
, no entanto, me dá um erro no segundo #pragma
. Se eu comentar isso, recebo um erro no terceiro #pragma
.
input.c:1:9: note: ‘#pragma message: one’
1 | #pragma message "one"
| ^~~~~~~
input.c:3:9: error: expected identifier or ‘(’ before ‘#pragma’
3 | #pragma message "two"
| ^~~~~~~
input.c:1:9: note: ‘#pragma message: one’
1 | #pragma message "one"
| ^~~~~~~
input.c:5:9: error: expected identifier or ‘(’ before ‘#pragma’
5 | #pragma message "three"
| ^~~~~~~
Com a experimentação, parece que gcc
não aceita nenhuma #pragma
diretiva depois de um __attribute__
.
Exemplo reproduzível
Descomentar #pragma
causa um erro reproduzível no GCC v11.4.0
__attribute__((nonnull))
// #pragma message "this is an error"
void test(void);
Pergunta
Existe alguma correção ou solução que me permita misturar as diretivas #pragma
and em , assim como permite?__attribute__
gcc
clang
Tentei várias combinações diferentes e todas produziram os resultados que você está vendo.
Isso pode ser devido às diferentes maneiras que
gcc
eclang
fazem a análise sintática.clang
tem o pré-processador totalmente integrado. Paragcc
, é um passe/programa separado.Então, até onde sei, não há solução direta.
Você não especificou como as macros são geradas condicionalmente, mas vou dar um palpite. Você tem algo semelhante a
autoconf
que sonda o sistema e gera (por exemploconfig.h
).Pode haver uma solução alternativa, se você [apenas] quiser avisar/gerar erro em um atributo não suportado.
Isso é um pouco complicado, mas...
Compilar com
-DHAVE_INLINE
compila de forma limpa.Compilar sem
-DHAVE_INLINE
produz:Pode ser ainda mais simples: