Add 178663 back.

http://lab.llvm.org:8011/builders/clang-x86_64-darwin10-gdb went back green
before it processed the reverted 178663, so it could not have been the culprit.

Revert "Revert 178663."

This reverts commit 4f8a3eb2ce5d4ba422483439e20c8cbb4d953a41.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178682 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 7401530..b1d174b 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -749,7 +749,7 @@
   dumpName(D);
   dumpType(D->getType());
 
-  StorageClass SC = D->getStorageClassAsWritten();
+  StorageClass SC = D->getStorageClass();
   if (SC != SC_None)
     OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
   if (D->isInlineSpecified())
@@ -850,7 +850,7 @@
 void ASTDumper::VisitVarDecl(const VarDecl *D) {
   dumpName(D);
   dumpType(D->getType());
-  StorageClass SC = D->getStorageClassAsWritten();
+  StorageClass SC = D->getStorageClass();
   if (SC != SC_None)
     OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
   if (D->isThreadSpecified())
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 01d1a1e..d2e6d29 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2716,8 +2716,7 @@
                                        cast<CXXRecordDecl>(DC),
                                        D->getInnerLocStart(),
                                        NameInfo, T, TInfo,
-                                       Method->isStatic(),
-                                       Method->getStorageClassAsWritten(),
+                                       Method->getStorageClass(),
                                        Method->isInlineSpecified(),
                                        D->isConstexpr(),
                                        Importer.Import(D->getLocEnd()));
@@ -2725,7 +2724,6 @@
     ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
                                       D->getInnerLocStart(),
                                       NameInfo, T, TInfo, D->getStorageClass(),
-                                      D->getStorageClassAsWritten(),
                                       D->isInlineSpecified(),
                                       D->hasWrittenPrototype(),
                                       D->isConstexpr());
@@ -3076,8 +3074,7 @@
                                    Importer.Import(D->getInnerLocStart()),
                                    Loc, Name.getAsIdentifierInfo(),
                                    T, TInfo,
-                                   D->getStorageClass(),
-                                   D->getStorageClassAsWritten());
+                                   D->getStorageClass());
   ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
   ToVar->setAccess(D->getAccess());
   ToVar->setLexicalDeclContext(LexicalDC);
@@ -3145,7 +3142,6 @@
                                      Importer.Import(D->getInnerLocStart()),
                                             Loc, Name.getAsIdentifierInfo(),
                                             T, TInfo, D->getStorageClass(),
-                                             D->getStorageClassAsWritten(),
                                             /*FIXME: Default argument*/ 0);
   ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg());
   return Importer.Imported(D, ToParm);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 4b92069..9505d29 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -498,26 +498,24 @@
     //   declared to have external linkage; or (there is no equivalent in C99)
     if (Context.getLangOpts().CPlusPlus &&
         Var->getType().isConstQualified() && 
-        !Var->getType().isVolatileQualified() &&
-        Var->getStorageClass() != SC_Extern &&
-        Var->getStorageClass() != SC_PrivateExtern) {
-      bool FoundExtern = false;
-      for (const VarDecl *PrevVar = Var->getPreviousDecl();
-           PrevVar && !FoundExtern; 
-           PrevVar = PrevVar->getPreviousDecl())
-        if (isExternalLinkage(PrevVar->getLinkage()))
-          FoundExtern = true;
-      
-      if (!FoundExtern)
-        return LinkageInfo::internal();
-    }
-    if (Var->getStorageClass() == SC_None) {
+        !Var->getType().isVolatileQualified()) {
       const VarDecl *PrevVar = Var->getPreviousDecl();
-      for (; PrevVar; PrevVar = PrevVar->getPreviousDecl())
-        if (PrevVar->getStorageClass() == SC_PrivateExtern)
-          break;
       if (PrevVar)
         return PrevVar->getLinkageAndVisibility();
+
+      if (Var->getStorageClass() != SC_Extern &&
+          Var->getStorageClass() != SC_PrivateExtern)
+        return LinkageInfo::internal();
+    }
+
+    for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar;
+         PrevVar = PrevVar->getPreviousDecl()) {
+      if (PrevVar->getStorageClass() == SC_PrivateExtern &&
+          Var->getStorageClass() == SC_None)
+        return PrevVar->getLinkageAndVisibility();
+      // Explicitly declared static.
+      if (PrevVar->getStorageClass() == SC_Static)
+        return LinkageInfo::internal();
     }
   } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
     // C++ [temp]p4:
@@ -531,7 +529,7 @@
       Function = cast<FunctionDecl>(D);
 
     // Explicitly declared static.
-    if (Function->getStorageClass() == SC_Static)
+    if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
       return LinkageInfo(InternalLinkage, DefaultVisibility, false);
   } else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
     //   - a data member of an anonymous union.
@@ -995,7 +993,7 @@
       return LinkageInfo::uniqueExternal();
 
     // This is a "void f();" which got merged with a file static.
-    if (Function->getStorageClass() == SC_Static)
+    if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
       return LinkageInfo::internal();
 
     LinkageInfo LV;
@@ -1013,15 +1011,11 @@
   }
 
   if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
-    if (Var->hasExternalStorageAsWritten()) {
+    if (Var->hasExternalStorage()) {
       if (Var->isInAnonymousNamespace() &&
           !Var->getDeclContext()->isExternCContext())
         return LinkageInfo::uniqueExternal();
 
-      // This is an "extern int foo;" which got merged with a file static.
-      if (Var->getStorageClass() == SC_Static)
-        return LinkageInfo::internal();
-
       LinkageInfo LV;
       if (Var->getStorageClass() == SC_PrivateExtern)
         LV.mergeVisibility(HiddenVisibility, true);
@@ -1030,9 +1024,13 @@
           LV.mergeVisibility(*Vis, true);
       }
 
-      // Note that Sema::MergeVarDecl already takes care of implementing
-      // C99 6.2.2p4 and propagating the visibility attribute, so we don't
-      // have to do it here.
+      if (const VarDecl *Prev = Var->getPreviousDecl()) {
+        LinkageInfo PrevLV = getLVForDecl(Prev, computation);
+        if (PrevLV.getLinkage())
+          LV.setLinkage(PrevLV.getLinkage());
+        LV.mergeVisibility(PrevLV);
+      }
+
       return LV;
     }
   }
@@ -1467,21 +1465,18 @@
 VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
                          SourceLocation StartL, SourceLocation IdL,
                          IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
-                         StorageClass S, StorageClass SCAsWritten) {
-  return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S, SCAsWritten);
+                         StorageClass S) {
+  return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S);
 }
 
 VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarDecl));
   return new (Mem) VarDecl(Var, 0, SourceLocation(), SourceLocation(), 0, 
-                           QualType(), 0, SC_None, SC_None);
+                           QualType(), 0, SC_None);
 }
 
 void VarDecl::setStorageClass(StorageClass SC) {
   assert(isLegalForVariable(SC));
-  if (getStorageClass() != SC)
-    assert(isLinkageValid());
-
   VarDeclBits.SClass = SC;
 }
 
@@ -1581,7 +1576,7 @@
   if (hasExternalStorage())
     return DeclarationOnly;
 
-  if (hasExternalStorageAsWritten()) {
+  if (hasExternalStorage()) {
     for (const VarDecl *PrevVar = getPreviousDecl();
          PrevVar; PrevVar = PrevVar->getPreviousDecl()) {
       if (PrevVar->getLinkage() == InternalLinkage)
@@ -1879,16 +1874,15 @@
                                  SourceLocation StartLoc,
                                  SourceLocation IdLoc, IdentifierInfo *Id,
                                  QualType T, TypeSourceInfo *TInfo,
-                                 StorageClass S, StorageClass SCAsWritten,
-                                 Expr *DefArg) {
+                                 StorageClass S, Expr *DefArg) {
   return new (C) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo,
-                             S, SCAsWritten, DefArg);
+                             S, DefArg);
 }
 
 ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl));
   return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(),
-                               0, QualType(), 0, SC_None, SC_None, 0);
+                               0, QualType(), 0, SC_None, 0);
 }
 
 SourceRange ParmVarDecl::getSourceRange() const {
@@ -2067,7 +2061,7 @@
   if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
     return Method->isStatic();
 
-  if (getStorageClass() == SC_Static)
+  if (getCanonicalDecl()->getStorageClass() == SC_Static)
     return false;
 
   for (const DeclContext *DC = getDeclContext();
@@ -2112,14 +2106,6 @@
   return getFirstDeclaration();
 }
 
-void FunctionDecl::setStorageClass(StorageClass SC) {
-  assert(isLegalForFunction(SC));
-  if (getStorageClass() != SC)
-    assert(isLinkageValid());
-
-  SClass = SC;
-}
-
 /// \brief Returns a value indicating whether this function
 /// corresponds to a builtin function.
 ///
@@ -2270,7 +2256,7 @@
     //
     // FIXME: What happens if gnu_inline gets added on after the first
     // declaration?
-    if (!isInlineSpecified() || getStorageClassAsWritten() == SC_Extern)
+    if (!isInlineSpecified() || getStorageClass() == SC_Extern)
       return false;
 
     const FunctionDecl *Prev = this;
@@ -2282,10 +2268,10 @@
         // If it's not the case that both 'inline' and 'extern' are
         // specified on the definition, then it is always externally visible.
         if (!Prev->isInlineSpecified() ||
-            Prev->getStorageClassAsWritten() != SC_Extern)
+            Prev->getStorageClass() != SC_Extern)
           return false;
       } else if (Prev->isInlineSpecified() && 
-                 Prev->getStorageClassAsWritten() != SC_Extern) {
+                 Prev->getStorageClass() != SC_Extern) {
         return false;
       }
     }
@@ -2340,7 +2326,7 @@
     // If it's not the case that both 'inline' and 'extern' are
     // specified on the definition, then this inline definition is
     // externally visible.
-    if (!(isInlineSpecified() && getStorageClassAsWritten() == SC_Extern))
+    if (!(isInlineSpecified() && getStorageClass() == SC_Extern))
       return true;
     
     // If any declaration is 'inline' but not 'extern', then this definition
@@ -2349,7 +2335,7 @@
          Redecl != RedeclEnd;
          ++Redecl) {
       if (Redecl->isInlineSpecified() && 
-          Redecl->getStorageClassAsWritten() != SC_Extern)
+          Redecl->getStorageClass() != SC_Extern)
         return true;
     }    
     
@@ -3212,12 +3198,12 @@
                                    SourceLocation StartLoc,
                                    const DeclarationNameInfo &NameInfo,
                                    QualType T, TypeSourceInfo *TInfo,
-                                   StorageClass SC, StorageClass SCAsWritten,
+                                   StorageClass SC,
                                    bool isInlineSpecified, 
                                    bool hasWrittenPrototype,
                                    bool isConstexprSpecified) {
   FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo,
-                                           T, TInfo, SC, SCAsWritten,
+                                           T, TInfo, SC,
                                            isInlineSpecified,
                                            isConstexprSpecified);
   New->HasWrittenPrototype = hasWrittenPrototype;
@@ -3228,7 +3214,7 @@
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionDecl));
   return new (Mem) FunctionDecl(Function, 0, SourceLocation(), 
                                 DeclarationNameInfo(), QualType(), 0,
-                                SC_None, SC_None, false, false);
+                                SC_None, false, false);
 }
 
 BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 1e60560..bd6d99c 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -435,7 +435,7 @@
 
   // Variables, if they aren't definitions.
   if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
-    if (!Var->hasExternalStorage() || Var->getInit()) {
+    if (Var->isThisDeclarationADefinition()) {
       IsDefinition = true;
       return false;
     }
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 9ed9b7d..ffad9ae 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -1251,6 +1251,42 @@
 
 void CXXMethodDecl::anchor() { }
 
+bool CXXMethodDecl::isStatic() const {
+  const CXXMethodDecl *MD = this;
+  for (;;) {
+    const CXXMethodDecl *C = MD->getCanonicalDecl();
+    if (C != MD) {
+      MD = C;
+      continue;
+    }
+
+    FunctionTemplateSpecializationInfo *Info =
+      MD->getTemplateSpecializationInfo();
+    if (!Info)
+      break;
+    MD = cast<CXXMethodDecl>(Info->getTemplate()->getTemplatedDecl());
+  }
+
+  if (MD->getStorageClass() == SC_Static)
+    return true;
+
+  DeclarationName Name = getDeclName();
+  // [class.free]p1:
+  // Any allocation function for a class T is a static member
+  // (even if not explicitly declared static).
+  if (Name.getCXXOverloadedOperator() == OO_New ||
+      Name.getCXXOverloadedOperator() == OO_Array_New)
+    return true;
+
+  // [class.free]p6 Any deallocation function for a class X is a static member
+  // (even if not explicitly declared static).
+  if (Name.getCXXOverloadedOperator() == OO_Delete ||
+      Name.getCXXOverloadedOperator() == OO_Array_Delete)
+    return true;
+
+  return false;
+}
+
 static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD,
                                  const CXXMethodDecl *BaseMD) {
   for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
@@ -1312,10 +1348,10 @@
                       SourceLocation StartLoc,
                       const DeclarationNameInfo &NameInfo,
                       QualType T, TypeSourceInfo *TInfo,
-                      bool isStatic, StorageClass SCAsWritten, bool isInline,
+                      StorageClass SC, bool isInline,
                       bool isConstexpr, SourceLocation EndLocation) {
   return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo,
-                               isStatic, SCAsWritten, isInline, isConstexpr,
+                               SC, isInline, isConstexpr,
                                EndLocation);
 }
 
@@ -1323,7 +1359,7 @@
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXMethodDecl));
   return new (Mem) CXXMethodDecl(CXXMethod, 0, SourceLocation(), 
                                  DeclarationNameInfo(), QualType(),
-                                 0, false, SC_None, false, false,
+                                 0, SC_None, false, false,
                                  SourceLocation());
 }
 
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 54fa9ca..c3bf8f8 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -393,7 +393,7 @@
 void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
   CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
   if (!Policy.SuppressSpecifiers) {
-    switch (D->getStorageClassAsWritten()) {
+    switch (D->getStorageClass()) {
     case SC_None: break;
     case SC_Extern: Out << "extern "; break;
     case SC_Static: Out << "static "; break;
@@ -641,9 +641,9 @@
 
 
 void DeclPrinter::VisitVarDecl(VarDecl *D) {
-  StorageClass SCAsWritten = D->getStorageClassAsWritten();
-  if (!Policy.SuppressSpecifiers && SCAsWritten != SC_None)
-    Out << VarDecl::getStorageClassSpecifierString(SCAsWritten) << " ";
+  StorageClass SC = D->getStorageClass();
+  if (!Policy.SuppressSpecifiers && SC != SC_None)
+    Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
 
   if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
     Out << "__thread ";