EricWF created this revision.

This patch updates `__has_extension` to report the C++1z extensions Clang offers


https://reviews.llvm.org/D32950

Files:
  docs/LanguageExtensions.rst
  lib/Lex/PPMacroExpansion.cpp
  test/Lexer/has_extension_cxx.cpp
  test/Lexer/has_feature_cxx0x.cpp
  test/SemaCXX/cxx1z-extensions.cpp

Index: test/SemaCXX/cxx1z-extensions.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/cxx1z-extensions.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -std=c++11 -Wno-c++1z-extensions -Wno-c++14-extensions -verify %s
+
+// expected-no-diagnostics
+
+// Fold Expressions //
+static_assert(__has_extension(cxx_fold_expressions), "");
+template <class ...Bools>
+constexpr bool test_fold_expressions(Bools ...b) {
+  return (b && ...);
+}
+static_assert(test_fold_expressions(true, true, true), "");
+
+// If Constexpr //
+static_assert(__has_extension(cxx_if_constexpr), "");
+template <bool Pred>
+constexpr bool test_if_constexpr() {
+  if constexpr (Pred) {
+    static_assert(Pred, "");
+    return true;
+  } else {
+    static_assert(!Pred, "");
+    return false;
+  }
+}
+static_assert(test_if_constexpr<true>(), "");
+static_assert(!test_if_constexpr<false>(), "");
+
+// Inline Variables //
+static_assert(__has_extension(cxx_inline_variables), "");
+inline int test_inline_variables = 42;
+
+// Structured Bindings //
+static_assert(__has_extension(cxx_structured_bindings), "");
+struct Tuple {
+  int a, b, c;
+};
+constexpr bool test_bindings() {
+  auto [a, b, c] = Tuple{42, 101, -1};
+  return a == 42 && b == 101 && c == -1;
+}
+static_assert(test_bindings(), "");
+
+// Variadic Using //
+static_assert(__has_extension(cxx_variadic_using), "");
+struct A { constexpr bool operator()() const { return true; } };
+struct B { constexpr bool operator()(int) const { return false; } };
+template <class ...Args> struct TestVariadicUsing : Args... {
+  using Args::operator()...;
+};
+static_assert(TestVariadicUsing<A, B>{}(), "");
+static_assert(!TestVariadicUsing<A, B>{}(42), "");
Index: test/Lexer/has_feature_cxx0x.cpp
===================================================================
--- test/Lexer/has_feature_cxx0x.cpp
+++ test/Lexer/has_feature_cxx0x.cpp
@@ -479,3 +479,57 @@
 // CHECK-14: has_generic_lambdas
 // CHECK-11: no_generic_lambdas
 // CHECK-NO-11: no_generic_lambdas
+
+#if __has_feature(cxx_fold_expressions)
+int has_fold_expressions();
+#else
+int no_fold_expressions();
+#endif
+// CHECK-1Z: has_fold_expressions
+// CHECK-14: no_fold_expressions
+// CHECK-11: no_fold_expressions
+// CHECK-NO-11: no_fold_expressions
+
+
+#if __has_feature(cxx_if_constexpr)
+int has_if_constexpr();
+#else
+int no_if_constexpr();
+#endif
+// CHECK-1Z: has_if_constexpr
+// CHECK-14: no_if_constexpr
+// CHECK-11: no_if_constexpr
+// CHECK-NO-11: no_if_constexpr
+
+
+#if __has_feature(cxx_inline_variables)
+int has_inline_variables();
+#else
+int no_inline_variables();
+#endif
+// CHECK-1Z: has_inline_variables
+// CHECK-14: no_inline_variables
+// CHECK-11: no_inline_variables
+// CHECK-NO-11: no_inline_variables
+
+
+#if __has_feature(cxx_structured_bindings)
+int has_structured_bindings();
+#else
+int no_structured_bindings();
+#endif
+// CHECK-1Z: has_structured_bindings
+// CHECK-14: no_structured_bindings
+// CHECK-11: no_structured_bindings
+// CHECK-NO-11: no_structured_bindings
+
+
+#if __has_feature(cxx_variadic_using)
+int has_variadic_using();
+#else
+int no_variadic_using();
+#endif
+// CHECK-1Z: has_variadic_using
+// CHECK-14: no_variadic_using
+// CHECK-11: no_variadic_using
+// CHECK-NO-11: no_variadic_using
Index: test/Lexer/has_extension_cxx.cpp
===================================================================
--- test/Lexer/has_extension_cxx.cpp
+++ test/Lexer/has_extension_cxx.cpp
@@ -66,3 +66,33 @@
 #if __has_extension(cxx_init_captures)
 int has_init_captures();
 #endif
+
+// CHECK-NOT: has_fold_expressions
+// CHECK11: has_fold_expressions
+#if __has_extension(cxx_fold_expressions)
+int has_fold_expressions();
+#endif
+
+// CHECK-NOT: has_if_constexpr
+// CHECK11: has_if_constexpr
+#if __has_extension(cxx_if_constexpr)
+int has_if_constexpr();
+#endif
+
+// CHECK-NOT: has_inline_variables
+// CHECK11: has_inline_variables
+#if __has_extension(cxx_inline_variables)
+int has_inline_variables();
+#endif
+
+// CHECK-NOT: has_structured_bindings
+// CHECK11: has_structured_bindings
+#if __has_extension(cxx_structured_bindings)
+int has_structured_bindings();
+#endif
+
+// CHECK-NOT: has_variadic_using
+// CHECK11: has_variadic_using
+#if __has_extension(cxx_variadic_using)
+int has_variadic_using();
+#endif
Index: lib/Lex/PPMacroExpansion.cpp
===================================================================
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1224,8 +1224,15 @@
       .Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus14)
       .Case("cxx_return_type_deduction", LangOpts.CPlusPlus14)
       .Case("cxx_variable_templates", LangOpts.CPlusPlus14)
+      // C++17 features
+      .Case("cxx_fold_expressions", LangOpts.CPlusPlus1z)
+      .Case("cxx_if_constexpr", LangOpts.CPlusPlus1z)
+      .Case("cxx_inline_variables", LangOpts.CPlusPlus1z)
+      .Case("cxx_structured_bindings", LangOpts.CPlusPlus1z)
+      .Case("cxx_variadic_using", LangOpts.CPlusPlus1z)
       // NOTE: For features covered by SD-6, it is preferable to provide *only*
-      // the SD-6 macro and not a __has_feature check.
+      // the SD-6 macro and not a __has_feature check unless the feature is
+      // also provided as an extension in older dialects.
 
       // C++ TSes
       //.Case("cxx_runtime_arrays", LangOpts.CPlusPlusTSArrays)
@@ -1314,6 +1321,12 @@
            .Case("cxx_binary_literals", true)
            .Case("cxx_init_captures", LangOpts.CPlusPlus11)
            .Case("cxx_variable_templates", LangOpts.CPlusPlus)
+           // C++17 features supported by other languages as extensions.
+           .Case("cxx_fold_expressions", LangOpts.CPlusPlus11)
+           .Case("cxx_if_constexpr", LangOpts.CPlusPlus11)
+           .Case("cxx_inline_variables", LangOpts.CPlusPlus11)
+           .Case("cxx_structured_bindings", LangOpts.CPlusPlus11)
+           .Case("cxx_variadic_using", LangOpts.CPlusPlus11)
            .Default(false);
 }
 
Index: docs/LanguageExtensions.rst
===================================================================
--- docs/LanguageExtensions.rst
+++ docs/LanguageExtensions.rst
@@ -873,6 +873,45 @@
 ``__has_extension(cxx_variable_templates)`` to determine if support for
 templated variable declarations is enabled.
 
+C++1z
+-----
+
+C++1z fold expressions
+^^^^^^^^^^^^^^^^^^^^^^
+
+Use ``__has_feature(cxx_fold_expressions)`` or
+``__has_extension(cxx_fold_expressions)`` to determine if support for
+fold expressions is enabled.
+
+C++1z if constexpr
+^^^^^^^^^^^^^^^^^^
+
+Use ``__has_feature(cxx_if_constexpr)`` or
+``__has_extension(cxx_if_constexpr)`` to determine if support for
+if constexpr is enabled.
+
+C++1z inline variables
+^^^^^^^^^^^^^^^^^^^^^^
+
+Use ``__has_feature(cxx_inline_variables)`` or
+``__has_extension(cxx_inline_variables)`` to determine if support for
+inline variables is enabled.
+
+C++1z structured bindings
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Use ``__has_feature(cxx_structured_bindings)`` or
+``__has_extension(cxx_structured_bindings)`` to determine if support for
+structured bindings is enabled.
+
+C++1z variadic using
+^^^^^^^^^^^^^^^^^^^^
+
+Use ``__has_feature(cxx_variadic_using)`` or
+``__has_extension(cxx_variadic_using)`` to determine if support for
+variadic using is enabled.
+
+
 C11
 ---
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to