Added a new preprocessor macro: __has_declspec_attribute. This can be used as a way...
authorAaron Ballman <aaron@aaronballman.com>
Fri, 5 Dec 2014 15:05:29 +0000 (15:05 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Fri, 5 Dec 2014 15:05:29 +0000 (15:05 +0000)
llvm-svn: 223467

clang/docs/LanguageExtensions.rst
clang/include/clang/Lex/Preprocessor.h
clang/lib/Lex/PPMacroExpansion.cpp
clang/test/Preprocessor/has_attribute.cpp

index 5636b89..3ca1010 100644 (file)
@@ -164,6 +164,33 @@ The attribute name can also be specified with a preceding and following ``__``
 (double underscore) to avoid interference from a macro with the same name.  For
 instance, ``__always_inline__`` can be used instead of ``always_inline``.
 
+
+``__has_declspec_attribute``
+----------------------------
+
+This function-like macro takes a single identifier argument that is the name of
+an attribute implemented as a Microsoft-style ``__declspec`` attribute.  It
+evaluates to 1 if the attribute is supported by the current compilation target,
+or 0 if not.  It can be used like this:
+
+.. code-block:: c++
+
+  #ifndef __has_declspec_attribute         // Optional of course.
+    #define __has_declspec_attribute(x) 0  // Compatibility with non-clang compilers.
+  #endif
+
+  ...
+  #if __has_declspec_attribute(dllexport)
+  #define DLLEXPORT __declspec(dllexport)
+  #else
+  #define DLLEXPORT
+  #endif
+  ...
+
+The attribute name can also be specified with a preceding and following ``__``
+(double underscore) to avoid interference from a macro with the same name.  For
+instance, ``__dllexport__`` can be used instead of ``dllexport``.
+
 ``__is_identifier``
 -------------------
 
index cfbc2c8..b6dcaa0 100644 (file)
@@ -136,6 +136,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
   IdentifierInfo *Ident__building_module;          // __building_module
   IdentifierInfo *Ident__MODULE__;                 // __MODULE__
   IdentifierInfo *Ident__has_cpp_attribute;        // __has_cpp_attribute
+  IdentifierInfo *Ident__has_declspec;             // __has_declspec_attribute
 
   SourceLocation DATELoc, TIMELoc;
   unsigned CounterValue;  // Next __COUNTER__ value.
index 37460f5..26cf543 100644 (file)
@@ -118,6 +118,7 @@ void Preprocessor::RegisterBuiltinMacros() {
   Ident__has_extension    = RegisterBuiltinMacro(*this, "__has_extension");
   Ident__has_builtin      = RegisterBuiltinMacro(*this, "__has_builtin");
   Ident__has_attribute    = RegisterBuiltinMacro(*this, "__has_attribute");
+  Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute");
   Ident__has_include      = RegisterBuiltinMacro(*this, "__has_include");
   Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
   Ident__has_warning      = RegisterBuiltinMacro(*this, "__has_warning");
@@ -1381,6 +1382,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
              II == Ident__has_builtin   ||
              II == Ident__is_identifier ||
              II == Ident__has_attribute ||
+             II == Ident__has_declspec  ||
              II == Ident__has_cpp_attribute) {
     // The argument to these builtins should be a parenthesized identifier.
     SourceLocation StartLoc = Tok.getLocation();
@@ -1428,6 +1430,9 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
     else if (II == Ident__has_cpp_attribute)
       Value = hasAttribute(AttrSyntax::CXX, ScopeII, FeatureII,
                            getTargetInfo().getTriple(), getLangOpts());
+    else if (II == Ident__has_declspec)
+      Value = hasAttribute(AttrSyntax::Declspec, nullptr, FeatureII,
+                           getTargetInfo().getTriple(), getLangOpts());
     else if (II == Ident__has_extension)
       Value = HasExtension(*this, FeatureII);
     else {
index 75f72c7..1ab4502 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -E %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fms-compatibility -std=c++11 -E %s -o - | FileCheck %s
 
 // CHECK: has_cxx11_carries_dep
 #if __has_cpp_attribute(carries_dependency)
 #if __has_cpp_attribute(deprecated) == 201309
   int has_cxx14_deprecated_vers();
 #endif
+
+// CHECK: has_declspec_uuid
+#if __has_declspec_attribute(uuid)
+  int has_declspec_uuid();
+#endif
+
+// CHECK: has_declspec_uuid2
+#if __has_declspec_attribute(__uuid__)
+  int has_declspec_uuid2();
+#endif
+
+// CHECK: does_not_have_declspec_fallthrough
+#if !__has_declspec_attribute(fallthrough)
+  int does_not_have_declspec_fallthrough();
+#endif