Clean up our handling of local instantiation scopes, which keep track
of the mapping from local declarations to their instantiated
counterparts during template instantiation. Previously, we tried to do
some unholy merging of local instantiation scopes that involved
storing a single hash table along with an "undo" list on the
side... which was ugly, and never handled function parameters
properly.

Now, we just keep separate hash tables for each local instantiation
scope, and "combining" two scopes means that we'll look in each of the
combined hash tables. The combined scope stack is rarely deep, and
this makes it easy to avoid the "undo" issues we were hitting. Also,
I've simplified the logic for function parameters: if we're declaring
a function and we need the function parameters to live longer, we just
push them back into the local instantiation scope where we need them. 

Fixes PR6990.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102732 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 4d107b5..a5b43e8 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3589,7 +3589,7 @@
     /// instantiated ParmVarDecl for 'x'.
     llvm::DenseMap<const Decl *, Decl *> LocalDecls;
 
-    /// \brief The outer scope, in which contains local variable
+    /// \brief The outer scope, which contains local variable
     /// definitions from some other instantiation (that may not be
     /// relevant to this particular scope).
     LocalInstantiationScope *Outer;
@@ -3597,54 +3597,36 @@
     /// \brief Whether we have already exited this scope.
     bool Exited;
 
-    /// \brief Whether this scope is temporary, meaning that we should
-    /// remove any additions we make once we exit this
-    /// scope. Temporary scopes are always combined with their outer
-    /// scopes.
-    bool Temporary;
-
-    /// \brief List of the declarations that we have added into this
-    /// temporary scope. They will be removed when we exit the
-    /// temporary scope.
-    llvm::SmallVector<const Decl *, 4> AddedTemporaryDecls;
-
+    /// \brief Whether to combine this scope with the outer scope, such that
+    /// lookup will search our outer scope.
+    bool CombineWithOuterScope;
+    
     // This class is non-copyable
     LocalInstantiationScope(const LocalInstantiationScope &);
     LocalInstantiationScope &operator=(const LocalInstantiationScope &);
 
   public:
-    LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false,
-                            bool Temporary = false)
+    LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
       : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
-        Exited(false), Temporary(Temporary) {
-      if (!CombineWithOuterScope && !Temporary)
-        SemaRef.CurrentInstantiationScope = this;
-      else
-        assert(SemaRef.CurrentInstantiationScope &&
-               "No outer instantiation scope?");
+        Exited(false), CombineWithOuterScope(CombineWithOuterScope)
+    {
+      SemaRef.CurrentInstantiationScope = this;
     }
 
     ~LocalInstantiationScope() {
-      if (!Exited) {
-        SemaRef.CurrentInstantiationScope = Outer;
-        for (unsigned I = 0, N = AddedTemporaryDecls.size(); I != N; ++I)
-          LocalDecls.erase(AddedTemporaryDecls[I]);
-      }
+      Exit();
     }
 
     /// \brief Exit this local instantiation scope early.
     void Exit() {
+      if (Exited)
+        return;
+      
       SemaRef.CurrentInstantiationScope = Outer;
-      LocalDecls.clear();
       Exited = true;
     }
 
-    Decl *getInstantiationOf(const Decl *D) {
-      Decl *Result = LocalDecls[D];
-      assert((Result || D->isInvalidDecl()) &&
-             "declaration was not instantiated in this scope!");
-      return Result;
-    }
+    Decl *getInstantiationOf(const Decl *D);
 
     VarDecl *getInstantiationOf(const VarDecl *Var) {
       return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
@@ -3659,15 +3641,7 @@
       return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
     }
 
-    void InstantiatedLocal(const Decl *D, Decl *Inst) {
-      Decl *&Stored = LocalDecls[D];
-      assert((!Stored || Stored == Inst) && "Already instantiated this local");
-
-      if (Temporary && !Stored)
-        AddedTemporaryDecls.push_back(D);
-
-      Stored = Inst;
-    }
+    void InstantiatedLocal(const Decl *D, Decl *Inst);
   };
 
   /// \brief The current instantiation scope used to store local