Keep track of the template parameter depth properly when we have
member templates declared inside other templates. This allows us to
match out-of-line definitions of member function templates within
class templates to the declarations within the class template. We
still can't handle out-of-line definitions for member class templates,
however.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79955 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index b2b7ed0..34cabfd 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -15,6 +15,7 @@
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Parse/Scope.h"
+#include "llvm/Support/Compiler.h"
 using namespace clang;
 
 /// \brief Parse a template declaration, explicit instantiation, or
@@ -29,6 +30,29 @@
   return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
 }
 
+/// \brief RAII class that manages the template parameter depth.
+namespace {
+  class VISIBILITY_HIDDEN TemplateParameterDepthCounter {
+    unsigned &Depth;
+    unsigned AddedLevels;
+
+  public:
+    explicit TemplateParameterDepthCounter(unsigned &Depth) 
+      : Depth(Depth), AddedLevels(0) { }
+    
+    ~TemplateParameterDepthCounter() {
+      Depth -= AddedLevels;
+    }
+    
+    void operator++() { 
+      ++Depth;
+      ++AddedLevels;
+    }
+    
+    operator unsigned() const { return Depth; }
+  };
+}
+
 /// \brief Parse a template declaration or an explicit specialization.
 ///
 /// Template declarations include one or more template parameter lists
@@ -77,6 +101,7 @@
   // context).
   bool isSpecialization = true;
   TemplateParameterLists ParamLists;
+  TemplateParameterDepthCounter Depth(TemplateParameterDepth);
   do {
     // Consume the 'export', if any.
     SourceLocation ExportLoc;
@@ -96,7 +121,7 @@
     // Parse the '<' template-parameter-list '>'
     SourceLocation LAngleLoc, RAngleLoc;
     TemplateParameterList TemplateParams;
-    if (ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc, 
+    if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc, 
                                 RAngleLoc)) {
       // Skip until the semi-colon or a }.
       SkipUntil(tok::r_brace, true, true);
@@ -104,15 +129,17 @@
         ConsumeToken();
       return DeclPtrTy();      
     }
-      
-    if (!TemplateParams.empty())
-      isSpecialization = false;
 
     ParamLists.push_back(
-      Actions.ActOnTemplateParameterList(ParamLists.size(), ExportLoc, 
+      Actions.ActOnTemplateParameterList(Depth, ExportLoc, 
                                          TemplateLoc, LAngleLoc, 
                                          TemplateParams.data(),
                                          TemplateParams.size(), RAngleLoc));
+
+    if (!TemplateParams.empty()) {
+      isSpecialization = false;
+      ++Depth;
+    }    
   } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
 
   // Parse the actual template declaration.