]> granicus.if.org Git - clang/commitdiff
Sema: Instantiation of variable definitions weren't local enough
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 27 Nov 2013 22:57:44 +0000 (22:57 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 27 Nov 2013 22:57:44 +0000 (22:57 +0000)
We wouldn't properly save and restore the pending local instantiations
we had built up prior to instantiation of a variable definition.  This
would lead to us instantiating too much causing crashes and other
general badness.

This fixes PR14374.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@195887 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-local-class.cpp

index 300619b3896e9bb43979b561615775c961d7333f..b635d9b271ca02b4cd73eefbb10414859c271d7a 100644 (file)
@@ -6406,6 +6406,24 @@ public:
   /// types, static variables, enumerators, etc.
   std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
 
+  class SavePendingLocalImplicitInstantiationsRAII {
+  public:
+    SavePendingLocalImplicitInstantiationsRAII(Sema &S): S(S) {
+      SavedPendingLocalImplicitInstantiations.swap(
+          S.PendingLocalImplicitInstantiations);
+    }
+
+    ~SavePendingLocalImplicitInstantiationsRAII() {
+      SavedPendingLocalImplicitInstantiations.swap(
+          S.PendingLocalImplicitInstantiations);
+    }
+
+  private:
+    Sema &S;
+    std::deque<PendingImplicitInstantiation>
+    SavedPendingLocalImplicitInstantiations;
+  };
+
   void PerformPendingInstantiations(bool LocalOnly = false);
 
   TypeSourceInfo *SubstType(TypeSourceInfo *T,
index 136bb5aa4f827f1bb4fc9578754d72b934c17d5d..0e6e204e661080c55af406a0d8efe657743a44e8 100644 (file)
@@ -3222,10 +3222,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
   // while we're still within our own instantiation context.
   SmallVector<VTableUse, 16> SavedVTableUses;
   std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
-  std::deque<PendingImplicitInstantiation> 
-                              SavedPendingLocalImplicitInstantiations;
-  SavedPendingLocalImplicitInstantiations.swap(
-                                  PendingLocalImplicitInstantiations);
+  SavePendingLocalImplicitInstantiationsRAII
+      SavedPendingLocalImplicitInstantiations(*this);
   if (Recursive) {
     VTableUses.swap(SavedVTableUses);
     PendingInstantiations.swap(SavedPendingInstantiations);
@@ -3306,8 +3304,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
            "PendingInstantiations should be empty before it is discarded.");
     PendingInstantiations.swap(SavedPendingInstantiations);
   }
-  SavedPendingLocalImplicitInstantiations.swap(
-                            PendingLocalImplicitInstantiations);
 }
 
 VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
@@ -3727,6 +3723,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
   // while we're still within our own instantiation context.
   SmallVector<VTableUse, 16> SavedVTableUses;
   std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+  SavePendingLocalImplicitInstantiationsRAII
+      SavedPendingLocalImplicitInstantiations(*this);
   if (Recursive) {
     VTableUses.swap(SavedVTableUses);
     PendingInstantiations.swap(SavedPendingInstantiations);
index 2b5db0fda3ece947e6eb9774c4eb7c2c6ef7b46e..bdc5ea0d4a8648698accdce9fd8deffca5c2a0bc 100644 (file)
@@ -160,3 +160,23 @@ void call() {
   C::func([]() {});
 }
 }
+
+namespace PR14373 {
+  struct function {
+    template <typename _Functor> function(_Functor __f) { __f(); }
+  };
+  template <typename Func> function exec_func(Func f) {
+    struct functor {
+      functor(Func f) : func(f) {}
+      void operator()() const { func(); }
+      Func func;
+    };
+    return functor(f);
+  }
+  struct Type {
+    void operator()() const {}
+  };
+  int call() {
+    exec_func(Type());
+  }
+}