При реализации моего собственного компилятора C11 я пытаюсь выяснить, как именно обрабатывать ключевое слово/оператор _Pragma
. C11 §6.10.9 описывает _Pragma
как оператор, поэтому представляется возможным переопределить его с помощью макросов, т.е. #define _Pragma(x) SOME_OTHER_MACRO(x)
. Кроме того, утверждение #undef _Pragma
не должно иметь эффекта (если не считать предшествующего #define
of _Pragma
). Это похоже на то, как ключевые слова могут быть #define
d, например старый VС++ hack #define for if (0) ; else for
. Однако, поскольку оператор _Pragma
оценивается во время фазы 3 перевода, на той же фазе, что и при выполнении директив препроцессора, неясно, является ли это исключением; в стандарте не упоминается, использовать ли его undefined поведение _Pragma
как имя макроса.
Я провел некоторое тестирование с помощью GCC, используя следующий код:
#define PRAGMA _Pragma
PRAGMA("message \"hi\"")
_Pragma ("message \"sup\"")
#undef PRAGMA
#undef _Pragma
//#define _Pragma(x)
_Pragma("message \"hello\"")
Компиляция с выводами gcc -std=c11 -pedantic -Wall -Wextra -c
:
tmp.c:2:1: note: #pragma message: hi
PRAGMA("message \"hi\"")
^
tmp.c:4:1: note: #pragma message: sup
_Pragma ("message \"sup\"")
^
tmp.c:8:8: warning: undefining "_Pragma" [enabled by default]
#undef _Pragma
^
tmp.c:10:9: error: expected declaration specifiers or ‘...’ before string constant
_Pragma("message \"hello\"")
^
Если я добавлю строку #undef _Alignof
, GCC не будет жаловаться на нее.
Это говорит о том, что GCC реализует _Pragma
через макрос (через предупреждающее сообщение), а это не определяет его, что приводит к ошибке компиляции. Если я раскомментирую #define _Pragma(x)
, ошибка исчезнет (поскольку литерал строки исчезнет).
Итак, мои вопросы:
- Можно ли реализовать
_Pragma
в реализациях как просто макрос, а не реализовать его как оператор? - Если это не так, GCC ошибается в этом?
- Если
_Pragma
должен быть оператором, является ли поведение undefined определять_Pragma
как макрос? - Есть ли порядок между оценкой
_Pragma
и другими директивами препроцессора? Или они имеют одинаковый "приоритет" (т.е. Оцениваются в порядке)?
Опять же, просмотр стандарта C11 не упоминает ничего о _Pragma
, кроме него, оператора, который может использоваться для директив #pragma
.