]> granicus.if.org Git - clang/commitdiff
Add a __has_attribute macro that works much like __has_feature and __has_builtin.
authorAnders Carlsson <andersca@mac.com>
Wed, 20 Oct 2010 02:31:43 +0000 (02:31 +0000)
committerAnders Carlsson <andersca@mac.com>
Wed, 20 Oct 2010 02:31:43 +0000 (02:31 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116906 91177308-0d34-0410-b5e6-96231b3b80d8

clang.xcodeproj/project.pbxproj
docs/LanguageExtensions.html
include/clang/CMakeLists.txt
include/clang/Lex/CMakeLists.txt [new file with mode: 0644]
include/clang/Lex/Makefile [new file with mode: 0644]
include/clang/Lex/Preprocessor.h
include/clang/Makefile
lib/Lex/CMakeLists.txt
lib/Lex/PPMacroExpansion.cpp
test/Lexer/has_attribute.cpp [new file with mode: 0644]

index 9c95d0a3dee5c0ed6924daa5c0242b6448d219d0..fa1e24574e8f6ff71d0892d96891c27ec9d1669e 100644 (file)
                        isa = PBXProject;
                        buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
                        compatibilityVersion = "Xcode 2.4";
+                       developmentRegion = English;
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
index 27d90c5cd3ccffb8c69e81a88e1864176081356e..f27a5705398102a116603b867d8af2d275b4fa5e 100644 (file)
@@ -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>
 <!-- ======================================================================= -->
index e82cf429eeccc44ed0ee76a73b3b223112590a10..375ae5bdabc85a322c04a9b048b06cc9610ddee2 100644 (file)
@@ -1,4 +1,5 @@
 add_subdirectory(AST)
 add_subdirectory(Basic)
 add_subdirectory(Driver)
+add_subdirectory(Lex)
 add_subdirectory(Serialization)
diff --git a/include/clang/Lex/CMakeLists.txt b/include/clang/Lex/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b823e83
--- /dev/null
@@ -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)
diff --git a/include/clang/Lex/Makefile b/include/clang/Lex/Makefile
new file mode 100644 (file)
index 0000000..9874bcf
--- /dev/null
@@ -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)/../../ $<
index 42e2daac2f26d8db0f12db5c91420c4d6a71c895..1ee0fec1c52920e1376628e352f761d2f15220e0 100644 (file)
@@ -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
 
index 030b0720fd81709b62fb161f305e475b105888d7..d6b9844285d25729b9b688d41d7ea06124ed717f 100644 (file)
@@ -1,5 +1,5 @@
 CLANG_LEVEL := ../..
-DIRS := AST Basic Driver Serialization
+DIRS := AST Basic Driver Lex Serialization
 
 include $(CLANG_LEVEL)/Makefile
 
index 0476384eff3d8e387df9d796177d864778c8b280..aa2c93af8ba7ee88409bd0c15cd6c48fe18a9811 100644 (file)
@@ -26,4 +26,4 @@ add_clang_library(clangLex
   TokenLexer.cpp
   )
 
-add_dependencies(clangLex ClangDiagnosticLex)
+add_dependencies(clangLex ClangDiagnosticLex ClangAttrSpellings)
index 24a0f39b05da906718b5ed4e5bf2552aed055ce6..19a6ca85211d5bb6911e1ec7263bab8db07137d1 100644 (file)
@@ -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);
     }
diff --git a/test/Lexer/has_attribute.cpp b/test/Lexer/has_attribute.cpp
new file mode 100644 (file)
index 0000000..9a58a30
--- /dev/null
@@ -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
+