Support accepting __gnu__ as a scoped attribute namespace that aliases to gnu.

This is useful in libstdc++ to avoid clashes with identifiers in the user's namespace.

llvm-svn: 345132
diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp
index 3dff0ad..ccfbe66 100644
--- a/clang/lib/Sema/ParsedAttr.cpp
+++ b/clang/lib/Sema/ParsedAttr.cpp
@@ -103,14 +103,25 @@
 
 #include "clang/Sema/AttrParsedAttrKinds.inc"
 
-static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
+static StringRef normalizeAttrScopeName(StringRef ScopeName,
+                                        ParsedAttr::Syntax SyntaxUsed) {
+  // We currently only normalize the "__gnu__" scope name to be "gnu".
+  if ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
+       SyntaxUsed == ParsedAttr::AS_C2x) &&
+      ScopeName == "__gnu__")
+    ScopeName = ScopeName.slice(2, ScopeName.size() - 2);
+  return ScopeName;
+}
+
+static StringRef normalizeAttrName(StringRef AttrName,
+                                   StringRef NormalizedScopeName,
                                    ParsedAttr::Syntax SyntaxUsed) {
   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
-  // for GNU attributes.
+  // for GNU attributes, and attributes using the double square bracket syntax.
   bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU ||
                ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
                  SyntaxUsed == ParsedAttr::AS_C2x) &&
-                ScopeName == "gnu");
+                NormalizedScopeName == "gnu");
   if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
       AttrName.endswith("__"))
     AttrName = AttrName.slice(2, AttrName.size() - 2);
@@ -125,7 +136,7 @@
 
   SmallString<64> FullName;
   if (ScopeName)
-    FullName += ScopeName->getName();
+    FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
 
   AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
 
@@ -141,9 +152,10 @@
 unsigned ParsedAttr::getAttributeSpellingListIndex() const {
   // Both variables will be used in tablegen generated
   // attribute spell list index matching code.
-  StringRef Scope = ScopeName ? ScopeName->getName() : "";
-  StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
-                                     (ParsedAttr::Syntax)SyntaxUsed);
+  auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed);
+  StringRef Scope =
+      ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : "";
+  StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax);
 
 #include "clang/Sema/AttrSpellingListIndex.inc"
 
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index c0fb335..a0faf84 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5831,16 +5831,14 @@
   if (AL.isDeclspecAttribute() || AL.isCXX11Attribute())
     checkAttributeAtMostNumArgs(S, AL, 1);
   else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) &&
-           !S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
-    return;
-
-  if (!S.getLangOpts().CPlusPlus14)
-    if (AL.isCXX11Attribute() &&
-        !(AL.hasScope() && AL.getScopeName()->isStr("gnu")))
-      S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL;
-
-  D->addAttr(::new (S.Context)
-                 DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement,
+           !S.checkStringLiteralArgumentAttr(AL, 1, Replacement))

+    return;

+

+  if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope())

+    S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL;

+

+  D->addAttr(::new (S.Context)

+                 DeprecatedAttr(AL.getRange(), S.Context, Str, Replacement,

                                 AL.getAttributeSpellingListIndex()));
 }
 
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 27dbf70..85a57e7 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -7273,7 +7273,7 @@
       // not appertain to a DeclaratorChunk. If we handle them as type
       // attributes, accept them in that position and diagnose the GCC
       // incompatibility.
-      if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) {
+      if (attr.isGNUScope()) {
         bool IsTypeAttr = attr.isTypeAttr();
         if (TAL == TAL_DeclChunk) {
           state.getSema().Diag(attr.getLoc(),