Introduce a second queue of "local" pending implicit instantiation,
which are instantiations of the member functions of local
classes. These implicit instantiations have to occur at the same time
as---and in the same local instantiation scope as---the enclosing
function, since the member functions of the local class can refer to
locals within the enclosing function. This should really, really fix PR5764.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93666 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index c14ce29..02e3a7a 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3165,13 +3165,17 @@
     /// relevant to this particular scope).
     LocalInstantiationScope *Outer;
 
+    /// \brief Whether we have already exited this scope.
+    bool Exited;
+
     // This class is non-copyable
     LocalInstantiationScope(const LocalInstantiationScope &);
     LocalInstantiationScope &operator=(const LocalInstantiationScope &);
 
   public:
     LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
-      : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope) {
+      : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), 
+        Exited(false) {
       if (!CombineWithOuterScope)
         SemaRef.CurrentInstantiationScope = this;
       else
@@ -3180,7 +3184,15 @@
     }
 
     ~LocalInstantiationScope() {
+      if (!Exited)
+        SemaRef.CurrentInstantiationScope = Outer;
+    }
+
+    /// \brief Exit this local instantiation scope early.
+    void Exit() {
       SemaRef.CurrentInstantiationScope = Outer;
+      LocalDecls.clear();
+      Exited = true;
     }
 
     Decl *getInstantiationOf(const Decl *D) {
@@ -3227,7 +3239,16 @@
   /// but have not yet been performed.
   std::deque<PendingImplicitInstantiation> PendingImplicitInstantiations;
 
-  void PerformPendingImplicitInstantiations();
+  /// \brief The queue of implicit template instantiations that are required
+  /// and must be performed within the current local scope.
+  ///
+  /// This queue is only used for member functions of local classes in
+  /// templates, which must be instantiated in the same scope as their
+  /// enclosing function, so that they can reference function-local
+  /// types, static variables, enumerators, etc.
+  std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
+
+  void PerformPendingImplicitInstantiations(bool LocalOnly = false);
 
   TypeSourceInfo *SubstType(TypeSourceInfo *T,
                             const MultiLevelTemplateArgumentList &TemplateArgs,
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0b97d76..31ec778 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -7215,8 +7215,15 @@
           AlreadyInstantiated = true;
       }
       
-      if (!AlreadyInstantiated)
-        PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc));
+      if (!AlreadyInstantiated) {
+        if (isa<CXXRecordDecl>(Function->getDeclContext()) &&
+            cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass())
+          PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
+                                                                      Loc));
+        else
+          PendingImplicitInstantiations.push_back(std::make_pair(Function, 
+                                                                 Loc));
+      }
     }
     
     // FIXME: keep track of references to static functions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e6be538..98619f3 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1653,8 +1653,14 @@
   ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
 
   // Introduce a new scope where local variable instantiations will be
-  // recorded.
-  LocalInstantiationScope Scope(*this);
+  // recorded, unless we're actually a member function within a local
+  // class, in which case we need to merge our results with the parent
+  // scope (of the enclosing function).
+  bool MergeWithParentScope = false;
+  if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
+    MergeWithParentScope = Rec->isLocalClass();
+
+  LocalInstantiationScope Scope(*this, MergeWithParentScope);
 
   // Introduce the instantiated function parameters into the local
   // instantiation scope.
@@ -1691,6 +1697,11 @@
   DeclGroupRef DG(Function);
   Consumer.HandleTopLevelDecl(DG);
 
+  // This class may have local implicit instantiations that need to be
+  // instantiation within this scope.
+  PerformPendingImplicitInstantiations(/*LocalOnly=*/true);
+  Scope.Exit();
+
   if (Recursive) {
     // Instantiate any pending implicit instantiations found during the
     // instantiation of this template.
@@ -2223,10 +2234,18 @@
 
 /// \brief Performs template instantiation for all implicit template
 /// instantiations we have seen until this point.
-void Sema::PerformPendingImplicitInstantiations() {
-  while (!PendingImplicitInstantiations.empty()) {
-    PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front();
-    PendingImplicitInstantiations.pop_front();
+void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
+  while (!PendingLocalImplicitInstantiations.empty() ||
+         (!LocalOnly && !PendingImplicitInstantiations.empty())) {
+    PendingImplicitInstantiation Inst;
+
+    if (PendingLocalImplicitInstantiations.empty()) {
+      Inst = PendingImplicitInstantiations.front();
+      PendingImplicitInstantiations.pop_front();
+    } else {
+      Inst = PendingLocalImplicitInstantiations.front();
+      PendingLocalImplicitInstantiations.pop_front();
+    }
 
     // Instantiate function definitions
     if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {