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:
Anders Carlsson 2010-10-20 02:31:43 +00:00
Родитель 06ff47b0bb
Коммит cae5095c11
10 изменённых файлов: 74 добавлений и 4 удалений

Просмотреть файл

@ -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