Introduce __has_extension macro

__has_extension is a function-like macro which takes the same set
of feature identifiers as __has_feature.  It evaluates to 1 if the
feature is supported by Clang in the current language (either as a
language extension or a standard language feature) or 0 if not.

At the same time, add support for the C1X feature identifiers
c_generic_selections (renamed from generic_selections) and
c_static_assert, and document them.

Patch by myself and Jean-Daniel Dupas.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131308 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index bc3c9b5..6a9d4ab 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -85,6 +85,7 @@
 
   // Clang Extensions.
   Ident__has_feature      = RegisterBuiltinMacro(*this, "__has_feature");
+  Ident__has_extension    = RegisterBuiltinMacro(*this, "__has_extension");
   Ident__has_builtin      = RegisterBuiltinMacro(*this, "__has_builtin");
   Ident__has_attribute    = RegisterBuiltinMacro(*this, "__has_attribute");
   Ident__has_include      = RegisterBuiltinMacro(*this, "__has_include");
@@ -525,8 +526,8 @@
 }
 
 
-/// HasFeature - Return true if we recognize and implement the specified feature
-/// specified by the identifier.
+/// HasFeature - Return true if we recognize and implement the feature
+/// specified by the identifier as a standard language feature.
 static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
   const LangOptions &LangOpts = PP.getLangOptions();
 
@@ -550,12 +551,14 @@
            .Case("cxx_exceptions", LangOpts.Exceptions)
            .Case("cxx_rtti", LangOpts.RTTI)
            .Case("enumerator_attributes", true)
-           .Case("generic_selections", true)
            .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI)
            .Case("objc_weak_class", LangOpts.ObjCNonFragileABI)
            .Case("ownership_holds", true)
            .Case("ownership_returns", true)
            .Case("ownership_takes", true)
+           // C1X features
+           .Case("c_generic_selections", LangOpts.C1X)
+           .Case("c_static_assert", LangOpts.C1X)
            // C++0x features
            .Case("cxx_access_control_sfinae", LangOpts.CPlusPlus0x)
            .Case("cxx_alias_templates", LangOpts.CPlusPlus0x)
@@ -603,6 +606,35 @@
            .Default(false);
 }
 
+/// HasExtension - Return true if we recognize and implement the feature
+/// specified by the identifier, either as an extension or a standard language
+/// feature.
+static bool HasExtension(const Preprocessor &PP, const IdentifierInfo *II) {
+  if (HasFeature(PP, II))
+    return true;
+
+  // If the use of an extension results in an error diagnostic, extensions are
+  // effectively unavailable, so just return false here.
+  if (PP.getDiagnostics().getExtensionHandlingBehavior()==Diagnostic::Ext_Error)
+    return false;
+
+  const LangOptions &LangOpts = PP.getLangOptions();
+
+  // Because we inherit the feature list from HasFeature, this string switch
+  // must be less restrictive than HasFeature's.
+  return llvm::StringSwitch<bool>(II->getName())
+           // C1X features supported by other languages as extensions.
+           .Case("c_generic_selections", true)
+           .Case("c_static_assert", true)
+           // C++0x features supported by other languages as extensions.
+           .Case("cxx_deleted_functions", LangOpts.CPlusPlus)
+           .Case("cxx_inline_namespaces", LangOpts.CPlusPlus)
+           .Case("cxx_override_control", LangOpts.CPlusPlus)
+           .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus)
+           .Case("cxx_rvalue_references", LangOpts.CPlusPlus)
+           .Default(false);
+}
+
 /// HasAttribute -  Return true if we recognize and implement the attribute
 /// specified by the given identifier.
 static bool HasAttribute(const IdentifierInfo *II) {
@@ -851,10 +883,11 @@
     // __COUNTER__ expands to a simple numeric value.
     OS << CounterValue++;
     Tok.setKind(tok::numeric_constant);
-  } else if (II == Ident__has_feature ||
-             II == Ident__has_builtin ||
+  } else if (II == Ident__has_feature   ||
+             II == Ident__has_extension ||
+             II == Ident__has_builtin   ||
              II == Ident__has_attribute) {
-    // The argument to these two builtins should be a parenthesized identifier.
+    // The argument to these builtins should be a parenthesized identifier.
     SourceLocation StartLoc = Tok.getLocation();
 
     bool IsValid = false;
@@ -883,6 +916,8 @@
       Value = FeatureII->getBuiltinID() != 0;
     } else if (II == Ident__has_attribute)
       Value = HasAttribute(FeatureII);
+    else if (II == Ident__has_extension)
+      Value = HasExtension(*this, FeatureII);
     else {
       assert(II == Ident__has_feature && "Must be feature check");
       Value = HasFeature(*this, FeatureII);