forked from OSchip/llvm-project
Add support for the __has_c_attribute builtin preprocessor macro.
This behaves similar to the __has_cpp_attribute builtin macro in that it allows users to detect whether an attribute is supported with the [[]] spelling syntax, which can be enabled in C with -fdouble-square-bracket-attributes. llvm-svn: 320088
This commit is contained in:
parent
095d4ea4bf
commit
48f5f4d895
|
@ -139,6 +139,35 @@ and following ``__`` (double underscore) to avoid interference from a macro with
|
||||||
the same name. For instance, ``gnu::__const__`` can be used instead of
|
the same name. For instance, ``gnu::__const__`` can be used instead of
|
||||||
``gnu::const``.
|
``gnu::const``.
|
||||||
|
|
||||||
|
``__has_c_attribute``
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
This function-like macro takes a single argument that is the name of an
|
||||||
|
attribute exposed with the double square-bracket syntax in C mode. The argument
|
||||||
|
can either be a single identifier or a scoped identifier. If the attribute is
|
||||||
|
supported, a nonzero value is returned. If the attribute is not supported by the
|
||||||
|
current compilation target, this macro evaluates to 0. It can be used like this:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
#ifndef __has_c_attribute // Optional of course.
|
||||||
|
#define __has_c_attribute(x) 0 // Compatibility with non-clang compilers.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
...
|
||||||
|
#if __has_c_attribute(fallthrough)
|
||||||
|
#define FALLTHROUGH [[fallthrough]]
|
||||||
|
#else
|
||||||
|
#define FALLTHROUGH
|
||||||
|
#endif
|
||||||
|
...
|
||||||
|
|
||||||
|
The attribute identifier (but not scope) can also be specified with a preceding
|
||||||
|
and following ``__`` (double underscore) to avoid interference from a macro with
|
||||||
|
the same name. For instance, ``gnu::__const__`` can be used instead of
|
||||||
|
``gnu::const``.
|
||||||
|
|
||||||
|
|
||||||
``__has_attribute``
|
``__has_attribute``
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,11 @@ Clang now supports the ...
|
||||||
Attribute Changes in Clang
|
Attribute Changes in Clang
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
- Added the ``__has_c_attribute()`` builtin preprocessor macro which allows
|
||||||
|
users to dynamically detect whether a double square-bracket attribute is
|
||||||
|
supported in C mode. This attribute syntax can be enabled with the
|
||||||
|
``-fdouble-square-bracket-attributes`` flag.
|
||||||
|
|
||||||
- The presence of __attribute__((availability(...))) on a declaration no longer
|
- The presence of __attribute__((availability(...))) on a declaration no longer
|
||||||
implies default visibility for that declaration on macOS.
|
implies default visibility for that declaration on macOS.
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,7 @@ class Preprocessor {
|
||||||
IdentifierInfo *Ident__building_module; // __building_module
|
IdentifierInfo *Ident__building_module; // __building_module
|
||||||
IdentifierInfo *Ident__MODULE__; // __MODULE__
|
IdentifierInfo *Ident__MODULE__; // __MODULE__
|
||||||
IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute
|
IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute
|
||||||
|
IdentifierInfo *Ident__has_c_attribute; // __has_c_attribute
|
||||||
IdentifierInfo *Ident__has_declspec; // __has_declspec_attribute
|
IdentifierInfo *Ident__has_declspec; // __has_declspec_attribute
|
||||||
|
|
||||||
SourceLocation DATELoc, TIMELoc;
|
SourceLocation DATELoc, TIMELoc;
|
||||||
|
|
|
@ -369,6 +369,7 @@ void Preprocessor::RegisterBuiltinMacros() {
|
||||||
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
|
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
|
||||||
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
|
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
|
||||||
Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
|
Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
|
||||||
|
Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
|
||||||
Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute");
|
Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute");
|
||||||
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
|
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
|
||||||
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
|
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
|
||||||
|
@ -1775,12 +1776,14 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
|
||||||
return II ? hasAttribute(AttrSyntax::Declspec, nullptr, II,
|
return II ? hasAttribute(AttrSyntax::Declspec, nullptr, II,
|
||||||
getTargetInfo(), getLangOpts()) : 0;
|
getTargetInfo(), getLangOpts()) : 0;
|
||||||
});
|
});
|
||||||
} else if (II == Ident__has_cpp_attribute) {
|
} else if (II == Ident__has_cpp_attribute ||
|
||||||
EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this,
|
II == Ident__has_c_attribute) {
|
||||||
[this](Token &Tok, bool &HasLexedNextToken) -> int {
|
bool IsCXX = II == Ident__has_cpp_attribute;
|
||||||
|
EvaluateFeatureLikeBuiltinMacro(
|
||||||
|
OS, Tok, II, *this, [&](Token &Tok, bool &HasLexedNextToken) -> int {
|
||||||
IdentifierInfo *ScopeII = nullptr;
|
IdentifierInfo *ScopeII = nullptr;
|
||||||
IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this,
|
IdentifierInfo *II = ExpectFeatureIdentifierInfo(
|
||||||
diag::err_feature_check_malformed);
|
Tok, *this, diag::err_feature_check_malformed);
|
||||||
if (!II)
|
if (!II)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1796,8 +1799,10 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
|
||||||
diag::err_feature_check_malformed);
|
diag::err_feature_check_malformed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return II ? hasAttribute(AttrSyntax::CXX, ScopeII, II,
|
AttrSyntax Syntax = IsCXX ? AttrSyntax::CXX : AttrSyntax::C;
|
||||||
getTargetInfo(), getLangOpts()) : 0;
|
return II ? hasAttribute(Syntax, ScopeII, II, getTargetInfo(),
|
||||||
|
getLangOpts())
|
||||||
|
: 0;
|
||||||
});
|
});
|
||||||
} else if (II == Ident__has_include ||
|
} else if (II == Ident__has_include ||
|
||||||
II == Ident__has_include_next) {
|
II == Ident__has_include_next) {
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// RUN: %clang_cc1 -fdouble-square-bracket-attributes -std=c11 -E %s -o - | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK: has_fallthrough
|
||||||
|
#if __has_c_attribute(fallthrough)
|
||||||
|
int has_fallthrough();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// CHECK: does_not_have_selectany
|
||||||
|
#if !__has_c_attribute(selectany)
|
||||||
|
int does_not_have_selectany();
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue