Implement redeclaration checking and hiding semantics for using declarations.  There
are a couple of O(n^2) operations in this, some analogous to the usual O(n^2)
redeclaration problem and some not.  In particular, retroactively removing
shadow declarations when they're hidden by later decls is pretty unfortunate.
I'm not yet convinced it's worse than the alternative, though.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91045 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index c557e61..2022b4a 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -636,6 +636,46 @@
   return !FirstDecl;
 }
 
+void DeclContext::removeDecl(Decl *D) {
+  assert(D->getLexicalDeclContext() == this &&
+         "decl being removed from non-lexical context");
+  assert((D->NextDeclInContext || D == LastDecl) &&
+         "decl is not in decls list");
+
+  // Remove D from the decl chain.  This is O(n) but hopefully rare.
+  if (D == FirstDecl) {
+    if (D == LastDecl)
+      FirstDecl = LastDecl = 0;
+    else
+      FirstDecl = D->NextDeclInContext;
+  } else {
+    for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) {
+      assert(I && "decl not found in linked list");
+      if (I->NextDeclInContext == D) {
+        I->NextDeclInContext = D->NextDeclInContext;
+        if (D == LastDecl) LastDecl = I;
+        break;
+      }
+    }
+  }
+  
+  // Mark that D is no longer in the decl chain.
+  D->NextDeclInContext = 0;
+
+  // Remove D from the lookup table if necessary.
+  if (isa<NamedDecl>(D)) {
+    NamedDecl *ND = cast<NamedDecl>(D);
+
+    void *OpaqueMap = getPrimaryContext()->LookupPtr;
+    if (!OpaqueMap) return;
+
+    StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(OpaqueMap);
+    StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
+    assert(Pos != Map->end() && "no lookup entry for decl");
+    Pos->second.remove(ND);
+  }
+}
+
 void DeclContext::addHiddenDecl(Decl *D) {
   assert(D->getLexicalDeclContext() == this &&
          "Decl inserted into wrong lexical context");