Index: docs/LanguageExtensions.rst
===================================================================
--- docs/LanguageExtensions.rst	(revision 198899)
+++ docs/LanguageExtensions.rst	(working copy)
@@ -112,10 +112,18 @@
 ``__has_attribute``
 -------------------
 
-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 by the current
-compilation target, or 0 if not.  It can be used like this:
+This function-like macro determines whether an attribute is supported by the 
+current compilation target, depending on the syntax used for the attribute.  It 
+evaluates to 1 if the attribute is supported, or 0 if not.
 
+Supported attribute syntaxes are: GNU-style ``__attribute__((ident))``, 
+C++11-style ``[[ident]]`` and ``[[scope::ident]]``, and Microsoft Visual Studio-
+style ``__declspec(ident)``.  If the exact syntax is not important, or if the 
+attribute is implemented as a keyword, a single identifier argument is also 
+accepted.
+
+It can be used like this:
+
 .. code-block:: c++
 
   #ifndef __has_attribute         // Optional of course.
@@ -127,12 +135,26 @@
   #define ALWAYS_INLINE __attribute__((always_inline))
   #else
   #define ALWAYS_INLINE
+  #endif  
+  ...
+  #if __has_attribute(__attribute__((dllexport)))
+    void foo(void) __attribute__((dllexport));
+  #elif __has_attribute(__declspec(dllexport))
+    __declspec(dllexport) void foo(void);
   #endif
   ...
+  #if __has_attribute([[clang::fallthrough]])
+  #define FALLTHROUGH [[clang::fallthrough]]
+  #else
+  #define FALLTHROUGH
+  #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, ``__always_inline__`` can be used instead of ``always_inline``.
+instance, ``__always_inline__`` can be used instead of ``always_inline``.  For 
+C++11-style attributes, the name can be bracketed with double underscores, but 
+the scope cannot.
 
 
 Include File Checking Macros
Index: include/clang/Lex/CMakeLists.txt
===================================================================
--- include/clang/Lex/CMakeLists.txt	(revision 198891)
+++ include/clang/Lex/CMakeLists.txt	(working copy)
@@ -1,5 +1,5 @@
-clang_tablegen(AttrSpellings.inc -gen-clang-attr-spelling-list
+clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl
   -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
   SOURCE ../Basic/Attr.td
-  TARGET ClangAttrSpellings
-  DEPENDS AttrSpellings.inc)
+  TARGET ClangAttrHasAttributeImpl
+  DEPENDS AttrHasAttributeImpl.inc)
Index: include/clang/Lex/Makefile
===================================================================
--- include/clang/Lex/Makefile	(revision 198891)
+++ include/clang/Lex/Makefile	(working copy)
@@ -1,6 +1,6 @@
 CLANG_LEVEL := ../../..
 TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = AttrSpellings.inc 
+BUILT_SOURCES = AttrHasAttributeImpl.inc 
 
 TABLEGEN_INC_FILES_COMMON = 1
 
@@ -8,6 +8,6 @@
 
 $(ObjDir)/AttrSpellings.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
                                   $(ObjDir)/.dir
-	$(Echo) "Building Clang attribute spellings with tblgen"
-	$(Verb) $(ClangTableGen) -gen-clang-attr-spelling-list -o $(call SYSPATH, $@) \
+	$(Echo) "Building Clang __has_attribute implementation with tblgen"
+	$(Verb) $(ClangTableGen) -gen-clang-attr-has-attribute-impl -o $(call SYSPATH, $@) \
 		-I $(PROJ_SRC_DIR)/../../ $<
Index: lib/Lex/PPMacroExpansion.cpp
===================================================================
--- lib/Lex/PPMacroExpansion.cpp	(revision 198897)
+++ lib/Lex/PPMacroExpansion.cpp	(working copy)
@@ -1043,18 +1043,31 @@
            .Default(false);
 }
 
+namespace AttrSyntax {
+enum {
+  /// Is the attribute identifier generally known for any syntax?
+  Generic,
+  /// Is the identifier known as a GNU-style attribute?
+  GNU,
+  /// Is the identifier known as a __declspec-style attribute?
+  Declspec,
+  // Is the identifier known as a C++-style attribute?
+  CXX
+};
+}
+
 /// HasAttribute -  Return true if we recognize and implement the attribute
 /// specified by the given identifier.
-static bool HasAttribute(const IdentifierInfo *II, const llvm::Triple &T) {
-  StringRef Name = II->getName();
+static bool HasAttribute(unsigned Syntax, const IdentifierInfo *Scope,
+                         const IdentifierInfo *Attr, const llvm::Triple &T) {
+  StringRef Name = Attr->getName();
   // Normalize the attribute name, __foo__ becomes foo.
   if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
     Name = Name.substr(2, Name.size() - 4);
 
-  // FIXME: Do we need to handle namespaces here?
-  return llvm::StringSwitch<bool>(Name)
-#include "clang/Lex/AttrSpellings.inc"
-        .Default(false);
+#include "clang/Lex/AttrHasAttributeImpl.inc"
+
+  return false;
 }
 
 /// EvaluateHasIncludeCommon - Process a '__has_include("path")'
@@ -1365,10 +1378,115 @@
     // __COUNTER__ expands to a simple numeric value.
     OS << CounterValue++;
     Tok.setKind(tok::numeric_constant);
+  } else if (II == Ident__has_attribute) {
+    // __has_attribute specifies the attribute syntax desired in one of four
+    // ways: __declspec, __attribute__, [[]] (in C++11 mode), and generically
+    // via a single identifier.
+    SourceLocation StartLoc = Tok.getLocation();
+    bool IsValid = false;
+    unsigned Syntax;
+    IdentifierInfo *Feature = 0, *Scope = 0;
+
+    // Read the opening paren.
+    LexUnexpandedToken(Tok);
+    if (Tok.is(tok::l_paren)) {
+      // Read the next token to determine what syntax is desired.
+      bool ShouldLexRParen = false;
+      LexUnexpandedToken(Tok);
+      if (Tok.is(tok::kw___attribute)) {
+        Syntax = AttrSyntax::GNU;
+
+        // Lex the two open parens, followed by anything we can get an
+        // IdentifierInfo out of, and two right parens. Note that we do not
+        // support attribute arguments.
+        LexUnexpandedToken(Tok);
+        if (Tok.is(tok::l_paren)) {
+          LexUnexpandedToken(Tok);
+          if (Tok.is(tok::l_paren)) {
+            LexUnexpandedToken(Tok);
+            if (Feature = Tok.getIdentifierInfo()) {
+              LexUnexpandedToken(Tok);
+              if (Tok.is(tok::r_paren)) {
+                LexUnexpandedToken(Tok);
+                ShouldLexRParen = Tok.is(tok::r_paren);
+              }
+            }
+          }
+        }
+      } else if (Tok.is(tok::kw___declspec)) {
+        Syntax = AttrSyntax::Declspec;
+
+        // Lex the open paren, followed by anything we can get an
+        // IdentifierInfo out of, and a right paren. Note that we do not
+        // support attribute arguments.
+        LexUnexpandedToken(Tok);
+        if (Tok.is(tok::l_paren)) {
+          LexUnexpandedToken(Tok);
+          if (Feature = Tok.getIdentifierInfo()) {
+            LexUnexpandedToken(Tok);
+            ShouldLexRParen = Tok.is(tok::r_paren);
+          }
+        }
+      } else if (Tok.is(tok::l_square)) {
+        Syntax = AttrSyntax::CXX;
+
+        // Lex the second open square bracket, followed by anything we can get
+        // an IdentifierInfo out of, and two right square brackets for the
+        // simple case. However, it can also have a scope specified.
+        LexUnexpandedToken(Tok);
+        if (Tok.is(tok::l_square)) {
+          LexUnexpandedToken(Tok);
+          if (Feature = Tok.getIdentifierInfo()) {
+            LexUnexpandedToken(Tok);
+            // If there's a ::, then we just lexed the Scope and not the
+            // Feature. Otherwise, we expect a ].
+            if (Tok.is(tok::coloncolon)) {
+              Scope = Feature;
+              LexUnexpandedToken(Tok);
+              Feature = Tok.getIdentifierInfo();
+
+              // Lex what we hope is the start of the closing square brackets.
+              LexUnexpandedToken(Tok);
+            }            
+            if (Tok.is(tok::r_square)) {
+              LexUnexpandedToken(Tok);
+              ShouldLexRParen = Tok.is(tok::r_square);
+            }
+          }
+        }
+      } else {
+        // Generic attribute syntax requires something we can get an
+        // IdentifierInfo out of, and nothing more.
+        Syntax = AttrSyntax::Generic;
+        if (Feature = Tok.getIdentifierInfo())
+          ShouldLexRParen = true;
+      }
+
+      if (ShouldLexRParen) {
+        LexUnexpandedToken(Tok);
+        if (Tok.is(tok::r_paren))
+          IsValid = true;
+      }
+    }
+
+    bool Value = false;
+    if (!IsValid)
+      Diag(StartLoc, diag::err_feature_check_malformed);
+    else {
+      // Do not support C++11 syntax attributes outside of C++11 mode.
+      if (Syntax == AttrSyntax::CXX && !getLangOpts().CPlusPlus11)
+        Value = 0;
+      else
+        Value = HasAttribute(Syntax, Scope, Feature,
+                             getTargetInfo().getTriple());
+    }
+
+    OS << (int)Value;
+    if (IsValid)
+      Tok.setKind(tok::numeric_constant);
   } else if (II == Ident__has_feature   ||
              II == Ident__has_extension ||
-             II == Ident__has_builtin   ||
-             II == Ident__has_attribute) {
+             II == Ident__has_builtin) {
     // The argument to these builtins should be a parenthesized identifier.
     SourceLocation StartLoc = Tok.getLocation();
 
@@ -1391,11 +1509,9 @@
     bool Value = false;
     if (!IsValid)
       Diag(StartLoc, diag::err_feature_check_malformed);
-    else if (II == Ident__has_builtin) {
+    else if (II == Ident__has_builtin)
       // Check for a builtin is trivial.
       Value = FeatureII->getBuiltinID() != 0;
-    } else if (II == Ident__has_attribute)
-      Value = HasAttribute(FeatureII, getTargetInfo().getTriple());
     else if (II == Ident__has_extension)
       Value = HasExtension(*this, FeatureII);
     else {
Index: test/Preprocessor/has_attribute.c
===================================================================
--- test/Preprocessor/has_attribute.c	(revision 198897)
+++ test/Preprocessor/has_attribute.c	(working copy)
@@ -48,3 +48,29 @@
 #if !__has_attribute(dllexport)
   int does_not_have_dllexport();
 #endif
+
+// CHECK: has_gnu_weakref
+#if __has_attribute(__attribute__((weakref)))
+  int has_gnu_weakref();
+#endif
+
+// CHECK: does_not_have_gnu_selectany
+#if !__has_attribute(__attribute__((selectany)))
+  int does_not_have_gnu_selectany();
+#endif
+
+// Because we're in C mode, there are no C++11-style attribute features.
+// CHECK: does_not_have_cxx11_carries_dep
+#if !__has_attribute([[carries_dependency]])
+  int does_not_have_cxx11_carries_dep();
+#endif
+
+// CHECK: has_declspec_selectany
+#if __has_attribute(__declspec(selectany))
+  int has_declspec_selectany();
+#endif
+
+// CHECK: does_not_have_declspec_weak_ref
+#if !__has_attribute(__declspec(weak_ref))
+  int does_not_have_declspec_weak_ref();
+#endif
Index: test/Preprocessor/has_attribute.cpp
===================================================================
--- test/Preprocessor/has_attribute.cpp	(revision 0)
+++ test/Preprocessor/has_attribute.cpp	(working copy)
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -std=c++11 -E %s -o - | FileCheck %s
+
+// CHECK: has_cxx11_carries_dep
+#if __has_attribute([[carries_dependency]])
+  int has_cxx11_carries_dep();
+#endif
+
+// CHECK: has_clang_fallthrough
+#if __has_attribute([[clang::fallthrough]])
+  int has_clang_fallthrough();
+#endif
+
+// CHECK: does_not_have_selectany
+#if !__has_attribute([[selectany]])
+  int does_not_have_selectany();
+#endif
+
+// The attribute name can be bracketed with double underscores.
+// CHECK: has_clang_fallthrough_2
+#if __has_attribute([[clang::__fallthrough__]])
+  int has_clang_fallthrough_2();
+#endif
+
+// The scope cannot be bracketed with double underscores.
+// CHECK: does_not_have___clang___fallthrough
+#if !__has_attribute([[__clang__::fallthrough]])
+  int does_not_have___clang___fallthrough();
+#endif
Index: utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- utils/TableGen/ClangAttrEmitter.cpp	(revision 198897)
+++ utils/TableGen/ClangAttrEmitter.cpp	(working copy)
@@ -1535,16 +1535,14 @@
   OS << "  }\n";
 }
 
-// Emits the list of spellings for attributes.
-void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
-  emitSourceFileHeader("llvm::StringSwitch code to match attributes based on "
-                       "the target triple, T", OS);
-
-  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
-  
-  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+static void
+GenerateHasAttrSpellingStringSwitch(const std::vector<Record *> &Attrs,
+                                    raw_ostream &OS,
+                                    const std::string &Variety = "",
+                                    const std::string &Scope = "") {
+  for (std::vector<Record*>::const_iterator I = Attrs.begin(), E = Attrs.end();
        I != E; ++I) {
-    Record &Attr = **I;
+    const Record &Attr = **I;
 
     // It is assumed that there will be an llvm::Triple object named T within
     // scope that can be used to determine whether the attribute exists in
@@ -1584,11 +1582,75 @@
     std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
     for (std::vector<Record*>::const_iterator I = Spellings.begin(),
          E = Spellings.end(); I != E; ++I) {
-      OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " << Test;
-      OS << ")\n";
+      if (Variety.empty() || 
+          (Variety == (*I)->getValueAsString("Variety") &&
+           (Scope.empty() || Scope == (*I)->getValueAsString("Namespace")))) {
+        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " << Test;
+        OS << ")\n";
+      }
     }
   }
+  OS << ".Default(false);\n";
+}
 
+// Emits the list of spellings for attributes.
+void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
+  emitSourceFileHeader("Code to implement the __has_attribute logic", OS);
+
+  // Separate all of the attributes out into four group: generic, c++11, gnu,
+  // and declspecs. Then generate a big switch statement for each of them.
+  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");  
+  std::vector<Record *> Declspec, GNU;
+  std::map<std::string, std::vector<Record *> > CXX;
+
+  // Walk over the list of all attributes, and split them out based on the
+  // spelling variety.
+  for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end();
+       I != E; ++I) {
+    Record *R = *I;
+    std::vector<Record *> Spellings = R->getValueAsListOfDefs("Spellings");
+    
+    for (std::vector<Record *>::const_iterator SI = Spellings.begin(),
+         SE = Spellings.end(); SI != SE; ++SI) {
+      Record &Spelling = **SI;
+
+      std::string Variety = Spelling.getValueAsString("Variety");
+      if (Variety == "GNU")
+        GNU.push_back(R);
+      else if (Variety == "Declspec")
+        Declspec.push_back(R);
+      else if (Variety == "CXX11") {
+        CXX[Spelling.getValueAsString("Namespace")].push_back(R);
+      }
+    }
+  }
+
+  OS << "switch (Syntax) {\n";
+  OS << "case AttrSyntax::Generic:\n";
+  OS << "  return llvm::StringSwitch<bool>(Name)\n";
+  GenerateHasAttrSpellingStringSwitch(Attrs, OS);
+  OS << "case AttrSyntax::GNU:\n";
+  OS << "  return llvm::StringSwitch<bool>(Name)\n";
+  GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU");
+  OS << "case AttrSyntax::Declspec:\n";
+  OS << "  return llvm::StringSwitch<bool>(Name)\n";
+  GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
+  OS << "case AttrSyntax::CXX: {\n";
+  // C++11-style attributes are further split out based on the Scope.
+  for (std::map<std::string, std::vector<Record *> >::iterator I = CXX.begin(),
+       E = CXX.end(); I != E; ++I) {
+    if (I != CXX.begin())
+      OS << " else ";
+    if (I->first.empty())
+      OS << "if (!Scope || Scope->getName() == \"\") {\n";
+    else
+      OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
+    OS << "  return llvm::StringSwitch<bool>(Name)\n";
+    GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first);
+    OS << "}";
+  }
+  OS << "\n}\n";
+  OS << "}\n";
 }
 
 void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
Index: utils/TableGen/TableGen.cpp
===================================================================
--- utils/TableGen/TableGen.cpp	(revision 198891)
+++ utils/TableGen/TableGen.cpp	(working copy)
@@ -31,7 +31,7 @@
   GenClangAttrList,
   GenClangAttrPCHRead,
   GenClangAttrPCHWrite,
-  GenClangAttrSpellingList,
+  GenClangAttrHasAttributeImpl,
   GenClangAttrSpellingListIndex,
   GenClangAttrASTVisitor,
   GenClangAttrLateParsedList,
@@ -83,7 +83,8 @@
                    "Generate clang PCH attribute reader"),
         clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
                    "Generate clang PCH attribute writer"),
-        clEnumValN(GenClangAttrSpellingList, "gen-clang-attr-spelling-list",
+        clEnumValN(GenClangAttrHasAttributeImpl,
+                   "gen-clang-attr-has-attribute-impl",
                    "Generate a clang attribute spelling list"),
         clEnumValN(GenClangAttrSpellingListIndex,
                    "gen-clang-attr-spelling-index",
@@ -177,8 +178,8 @@
   case GenClangAttrPCHWrite:
     EmitClangAttrPCHWrite(Records, OS);
     break;
-  case GenClangAttrSpellingList:
-    EmitClangAttrSpellingList(Records, OS);
+  case GenClangAttrHasAttributeImpl:
+    EmitClangAttrHasAttrImpl(Records, OS);
     break;
   case GenClangAttrSpellingListIndex:
     EmitClangAttrSpellingListIndex(Records, OS);
Index: utils/TableGen/TableGenBackends.h
===================================================================
--- utils/TableGen/TableGenBackends.h	(revision 198891)
+++ utils/TableGen/TableGenBackends.h	(working copy)
@@ -37,7 +37,7 @@
 void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS);
 void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS);
 void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS);
-void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS);
 void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS);
 void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS);
 void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS);
