зеркало из https://github.com/microsoft/clang.git
Add a __has_attribute macro that works much like __has_feature and __has_builtin.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116906 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
06ff47b0bb
Коммит
cae5095c11
|
@ -2039,6 +2039,7 @@
|
|||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
|
||||
compatibilityVersion = "Xcode 2.4";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
|
|
|
@ -135,6 +135,30 @@ can be used like this:</p>
|
|||
|
||||
<p>The feature tag is described along with the language feature below.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__has_attribute">__has_attribute</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This function-like macro takes a single identifier argument that is the name
|
||||
of an attribute. It evaluates to 1 if the attribute is supported or 0 if not. It
|
||||
can be used like this:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#ifndef __has_attribute // Optional of course.
|
||||
#define __has_attribute(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
...
|
||||
#if __has_attribute(override) || \
|
||||
#define OVERRIDE __attribute__((override))
|
||||
#else
|
||||
#define OVERRIDE
|
||||
#endif
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="has_include">Include File Checking Macros</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
add_subdirectory(AST)
|
||||
add_subdirectory(Basic)
|
||||
add_subdirectory(Driver)
|
||||
add_subdirectory(Lex)
|
||||
add_subdirectory(Serialization)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td)
|
||||
tablegen(AttrSpellings.inc
|
||||
-gen-clang-attr-spelling-list
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
add_custom_target(ClangAttrSpellings
|
||||
DEPENDS AttrSpellings.inc)
|
|
@ -0,0 +1,13 @@
|
|||
CLANG_LEVEL := ../../..
|
||||
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
|
||||
BUILT_SOURCES = AttrSpellings.inc
|
||||
|
||||
TABLEGEN_INC_FILES_COMMON = 1
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
||||
$(ObjDir)/AttrSpellings.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
|
||||
$(ObjDir)/.dir
|
||||
$(Echo) "Building Clang attribute spellings with tblgen"
|
||||
$(Verb) $(TableGen) -gen-clang-attr-spelling-list -o $(call SYSPATH, $@) \
|
||||
-I $(PROJ_SRC_DIR)/../../ $<
|
|
@ -83,6 +83,7 @@ class Preprocessor {
|
|||
IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
|
||||
IdentifierInfo *Ident__has_feature; // __has_feature
|
||||
IdentifierInfo *Ident__has_builtin; // __has_builtin
|
||||
IdentifierInfo *Ident__has_attribute; // __has_attribute
|
||||
IdentifierInfo *Ident__has_include; // __has_include
|
||||
IdentifierInfo *Ident__has_include_next; // __has_include_next
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
CLANG_LEVEL := ../..
|
||||
DIRS := AST Basic Driver Serialization
|
||||
DIRS := AST Basic Driver Lex Serialization
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
||||
|
|
|
@ -26,4 +26,4 @@ add_clang_library(clangLex
|
|||
TokenLexer.cpp
|
||||
)
|
||||
|
||||
add_dependencies(clangLex ClangDiagnosticLex)
|
||||
add_dependencies(clangLex ClangDiagnosticLex ClangAttrSpellings)
|
||||
|
|
|
@ -70,6 +70,7 @@ void Preprocessor::RegisterBuiltinMacros() {
|
|||
// Clang Extensions.
|
||||
Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
|
||||
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
|
||||
Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
|
||||
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
|
||||
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
|
||||
|
||||
|
@ -535,6 +536,14 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
|
|||
.Default(false);
|
||||
}
|
||||
|
||||
/// HasAttribute - Return true if we recognize and implement the attribute
|
||||
/// specified by the given identifier.
|
||||
static bool HasAttribute(const IdentifierInfo *II) {
|
||||
return llvm::StringSwitch<bool>(II->getName())
|
||||
#include "clang/Lex/AttrSpellings.inc"
|
||||
.Default(false);
|
||||
}
|
||||
|
||||
/// EvaluateHasIncludeCommon - Process a '__has_include("path")'
|
||||
/// or '__has_include_next("path")' expression.
|
||||
/// Returns true if successful.
|
||||
|
@ -767,7 +776,8 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
|
|||
OS << CounterValue++;
|
||||
Tok.setKind(tok::numeric_constant);
|
||||
} else if (II == Ident__has_feature ||
|
||||
II == Ident__has_builtin) {
|
||||
II == Ident__has_builtin ||
|
||||
II == Ident__has_attribute) {
|
||||
// The argument to these two builtins should be a parenthesized identifier.
|
||||
SourceLocation StartLoc = Tok.getLocation();
|
||||
|
||||
|
@ -795,7 +805,9 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
|
|||
else if (II == Ident__has_builtin) {
|
||||
// Check for a builtin is trivial.
|
||||
Value = FeatureII->getBuiltinID() != 0;
|
||||
} else {
|
||||
} else if (II == Ident__has_attribute)
|
||||
Value = HasAttribute(FeatureII);
|
||||
else {
|
||||
assert(II == Ident__has_feature && "Must be feature check");
|
||||
Value = HasFeature(*this, FeatureII);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: %clang_cc1 -E %s -o - | FileCheck %s
|
||||
|
||||
// CHECK: always_inline
|
||||
#if __has_attribute(always_inline)
|
||||
int always_inline();
|
||||
#endif
|
||||
|
||||
// CHECK: no_dummy_attribute
|
||||
#if !__has_attribute(dummy_attribute)
|
||||
int no_dummy_attribute();
|
||||
#endif
|
||||
|
Загрузка…
Ссылка в новой задаче