diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2018-12-20 22:32:04 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2018-12-20 22:32:04 +0000 |
commit | 5af7f70eef9405bdaa895370fc4702b47f0e953a (patch) | |
tree | 71e0ead9b6d8a627059ec57cd3a6d6c9e0e510e1 /docs | |
parent | 5faf6e9d41afa74a447da0b47349e4888e59e466 (diff) |
Add support for namespaces on #pragma clang attribute
Namespaces are introduced by adding an "identifier." before a
push/pop directive. Pop directives with namespaces can only pop a
attribute group that was pushed with the same namespace. Push and pop
directives that don't opt into namespaces have the same semantics.
This is necessary to prevent a pitfall of using multiple #pragma
clang attribute directives spread out in a large file, particularly
when macros are involved. It isn't easy to see which pop corripsonds
to which push, so its easy to inadvertently pop the wrong group.
Differential revision: https://reviews.llvm.org/D55628
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@349845 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'docs')
-rw-r--r-- | docs/LanguageExtensions.rst | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 0d358ad51a..7d878150de 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -2697,6 +2697,36 @@ The ``__declspec`` style syntax is also supported: A single push directive accepts only one attribute regardless of the syntax used. +Because multiple push directives can be nested, if you're writing a macro that +expands to ``_Pragma("clang attribute")`` it's good hygiene (though not +required) to add a namespace to your push/pop directives. A pop directive with a +namespace will pop the innermost push that has that same namespace. This will +ensure that another macro's ``pop`` won't inadvertently pop your attribute. Note +that an ``pop`` without a namespace will pop the innermost ``push`` without a +namespace. ``push``es with a namespace can only be popped by ``pop`` with the +same namespace. For instance: + +.. code-block:: c++ + + #define ASSUME_NORETURN_BEGIN _Pragma("clang attribute AssumeNoreturn.push ([[noreturn]], apply_to = function)") + #define ASSUME_NORETURN_END _Pragma("clang attribute AssumeNoreturn.pop") + + #define ASSUME_UNAVAILABLE_BEGIN _Pragma("clang attribute Unavailable.push (__attribute__((unavailable)), apply_to=function)") + #define ASSUME_UNAVAILABLE_END _Pragma("clang attribute Unavailable.pop") + + + ASSUME_NORETURN_BEGIN + ASSUME_UNAVAILABLE_BEGIN + void function(); // function has [[noreturn]] and __attribute__((unavailable)) + ASSUME_NORETURN_END + void other_function(); // function has __attribute__((unavailable)) + ASSUME_UNAVAILABLE_END + +Without the namespaces on the macros, ``other_function`` will be annotated with +``[[noreturn]]`` instead of ``__attribute__((unavailable))``. This may seem like +a contrived example, but its very possible for this kind of situation to appear +in real code if the pragmas are spread out accross a large file. + Subject Match Rules ------------------- |