Add __has_feature() for each of the type traits

llvm-svn: 124820
This commit is contained in:
Douglas Gregor 2011-02-03 21:57:35 +00:00
parent fb0bd049da
commit 7c60768590
3 changed files with 152 additions and 1 deletions

View File

@ -46,6 +46,7 @@ td {
<li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li>
<li><a href="#cxx_trailing_return">C++0x trailing return type</a></li>
</ul>
<li><a href="#checking_type_traits">Checks for Type Traits</a></li>
<li><a href="#blocks">Blocks</a></li>
<li><a href="#overloading-in-c">Function Overloading in C</a></li>
<li><a href="#builtins">Builtin Functions</a>
@ -436,6 +437,46 @@ the alternate function declaration syntax with trailing return type is enabled.<
<p>Use <tt>__has_feature(cxx_strong_enums)</tt> to determine if support for
strongly typed, scoped enumerations is enabled.</p>
<!-- ======================================================================= -->
<h2 id="checking_type_traits">Checks for Type Traits</h2>
<!-- ======================================================================= -->
<p>Clang supports the <a hef="http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html">GNU C++ type traits</a> and a subset of the <a href="http://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx">Microsoft Visual C++ Type traits</a>. For each supported type trait <code>__X</code>, <code>__has_feature(X)</code> indicates the presence of the type trait. For example:
<blockquote>
<pre>
#if __has_feature(is_convertible_to)
template&lt;typename From, typename To&gt;
struct is_convertible_to {
static const bool value = __is_convertible_to(From, To);
};
#else
// Emulate type trait
#endif
</pre>
</blockquote>
<p>The following type traits are supported by Clang:</p>
<ul>
<li><code>__has_nothrow_assign</code> (GNU, Microsoft)</li>
<li><code>__has_nothrow_copy</code> (GNU, Microsoft)</li>
<li><code>__has_nothrow_constructor</code> (GNU, Microsoft)</li>
<li><code>__has_trivial_assign</code> (GNU, Microsoft)</li>
<li><code>__has_trivial_copy</code> (GNU, Microsoft)</li>
<li><code>__has_trivial_constructor</code> (GNU, Microsoft)</li>
<li><code>__has_trivial_destructor</code> (GNU, Microsoft)</li>
<li><code>__has_virtual_destructor</code> (GNU, Microsoft)</li>
<li><code>__is_abstract</code> (GNU, Microsoft)</li>
<li><code>__is_base_of</code> (GNU, Microsoft)</li>
<li><code>__is_class</code> (GNU, Microsoft)</li>
<li><code>__is_convertible_to</code> (Microsoft)</li>
<li><code>__is_empty</code> (GNU, Microsoft)</li>
<li><code>__is_enum</code> (GNU, Microsoft)</li>
<li><code>__is_pod</code> (GNU, Microsoft)</li>
<li><code>__is_polymorphic</code> (GNU, Microsoft)</li>
<li><code>__is_union</code> (GNU, Microsoft)</li>
<li><code>__is_literal(type)</code>: Determines whether the given type is a literal type</li>
</ul>
<!-- ======================================================================= -->
<h2 id="blocks">Blocks</h2>
<!-- ======================================================================= -->

View File

@ -565,6 +565,25 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("cxx_static_assert", LangOpts.CPlusPlus0x)
.Case("cxx_trailing_return", LangOpts.CPlusPlus0x)
.Case("cxx_variadic_templates", LangOpts.CPlusPlus0x)
// Type traits
.Case("has_nothrow_assign", LangOpts.CPlusPlus)
.Case("has_nothrow_copy", LangOpts.CPlusPlus)
.Case("has_nothrow_constructor", LangOpts.CPlusPlus)
.Case("has_trivial_assign", LangOpts.CPlusPlus)
.Case("has_trivial_copy", LangOpts.CPlusPlus)
.Case("has_trivial_constructor", LangOpts.CPlusPlus)
.Case("has_trivial_destructor", LangOpts.CPlusPlus)
.Case("has_virtual_destructor", LangOpts.CPlusPlus)
.Case("is_abstract", LangOpts.CPlusPlus)
.Case("is_base_of", LangOpts.CPlusPlus)
.Case("is_class", LangOpts.CPlusPlus)
.Case("is_convertible_to", LangOpts.CPlusPlus)
.Case("is_empty", LangOpts.CPlusPlus)
.Case("is_enum", LangOpts.CPlusPlus)
.Case("is_pod", LangOpts.CPlusPlus)
.Case("is_polymorphic", LangOpts.CPlusPlus)
.Case("is_union", LangOpts.CPlusPlus)
.Case("is_literal", LangOpts.CPlusPlus)
.Case("tls", PP.getTargetInfo().isTLSSupported())
.Default(false);
}

View File

@ -0,0 +1,91 @@
// RUN: %clang_cc1 -E %s -o - | FileCheck %s
#if __has_feature(has_nothrow_assign)
int has_nothrow_assign();
#endif
// CHECK: int has_nothrow_assign();
#if __has_feature(has_nothrow_copy)
int has_nothrow_copy();
#endif
// CHECK: int has_nothrow_copy();
#if __has_feature(has_nothrow_constructor)
int has_nothrow_constructor();
#endif
// CHECK: int has_nothrow_constructor();
#if __has_feature(has_trivial_assign)
int has_trivial_assign();
#endif
// CHECK: int has_trivial_assign();
#if __has_feature(has_trivial_copy)
int has_trivial_copy();
#endif
// CHECK: int has_trivial_copy();
#if __has_feature(has_trivial_constructor)
int has_trivial_constructor();
#endif
// CHECK: int has_trivial_constructor();
#if __has_feature(has_trivial_destructor)
int has_trivial_destructor();
#endif
// CHECK: int has_trivial_destructor();
#if __has_feature(has_virtual_destructor)
int has_virtual_destructor();
#endif
// CHECK: int has_virtual_destructor();
#if __has_feature(is_abstract)
int is_abstract();
#endif
// CHECK: int is_abstract();
#if __has_feature(is_base_of)
int is_base_of();
#endif
// CHECK: int is_base_of();
#if __has_feature(is_class)
int is_class();
#endif
// CHECK: int is_class();
#if __has_feature(is_convertible_to)
int is_convertible_to();
#endif
// CHECK: int is_convertible_to();
#if __has_feature(is_empty)
int is_empty();
#endif
// CHECK: int is_empty();
#if __has_feature(is_enum)
int is_enum();
#endif
// CHECK: int is_enum();
#if __has_feature(is_pod)
int is_pod();
#endif
// CHECK: int is_pod();
#if __has_feature(is_polymorphic)
int is_polymorphic();
#endif
// CHECK: int is_polymorphic();
#if __has_feature(is_union)
int is_union();
#endif
// CHECK: int is_union();
#if __has_feature(is_literal)
int is_literal();
#endif
// CHECK: int is_literal();