]> granicus.if.org Git - clang/commitdiff
Fix PR17637: incorrect calculation of template parameter depth
authorFaisal Vali <faisalv@yahoo.com>
Wed, 4 Dec 2013 03:51:14 +0000 (03:51 +0000)
committerFaisal Vali <faisalv@yahoo.com>
Wed, 4 Dec 2013 03:51:14 +0000 (03:51 +0000)
In delayed template parsing mode, adjust the template depth counter for each template parameter list associated with an out of line member template specialization.

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

include/clang/Parse/Parser.h
lib/Parse/ParseTemplate.cpp
test/Parser/cxx-template-argument.cpp
test/Parser/cxx-template-decl.cpp

index 81ba5e1882ee217546ace55fec8a95af36e6f2a7..f23d4fb8a530b7e6a2583f8d568e3a7a8acc3448 100644 (file)
@@ -193,6 +193,10 @@ class Parser : public CodeCompletionHandler {
       ++Depth;
       ++AddedLevels;
     }
+    void addDepth(unsigned D) {
+      Depth += D;
+      AddedLevels += D;
+    }
     unsigned getDepth() const { return Depth; }
   };
 
index 076edb93fa11a65fc730f57be6de49bbb80eed58..8275922a6e3ef0b70c109320bcb686ee13bbd1f7 100644 (file)
@@ -1304,9 +1304,11 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
       new ParseScope(this, Scope::TemplateParamScope));
 
   DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD);
-  if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
+  const unsigned DeclaratorNumTemplateParameterLists = 
+      (Declarator ? Declarator->getNumTemplateParameterLists() : 0);
+  if (Declarator && DeclaratorNumTemplateParameterLists != 0) {
     Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
-    ++CurTemplateDepthTracker;
+    CurTemplateDepthTracker.addDepth(DeclaratorNumTemplateParameterLists);
   }
   Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D);
   ++CurTemplateDepthTracker;
index 8bf2a4f78addbd6b0c95f57d1819390644c862c0..bbd53b2bdd6911218b6e04fba9a5d1968ac39660 100644 (file)
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -fdelayed-template-parsing
 
 template<typename T> struct A {};
 
index 81269ce25416b55db716c4a2b2ad78fa550aaba4..87429001223acd29d75751d7c7cbf720d773e830 100644 (file)
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+
+
 
 // Errors
 export class foo { };   // expected-error {{expected template}}
@@ -102,7 +105,11 @@ template<template<typename> class T> struct shadow8 { // expected-note{{template
 template<int Size> 
 void f(int& i) {
   i = Size;
+ #ifdef DELAYED_TEMPLATE_PARSING
+  Size = i; 
+ #else
   Size = i; // expected-error{{expression is not assignable}}
+ #endif
 }
 
 template<typename T>
@@ -127,3 +134,73 @@ namespace PR6184 {
   template <typename T>
   void N::bar(typename T::x) { }
 }
+
+// This PR occurred only in template parsing mode.
+namespace PR17637 {
+template <int>
+struct L {
+  template <typename T>
+  struct O {
+    template <typename U>
+    static void Fun(U);
+  };
+};
+
+template <int k>
+template <typename T>
+template <typename U>
+void L<k>::O<T>::Fun(U) {}
+
+void Instantiate() { L<0>::O<int>::Fun(0); }
+
+}
+
+namespace explicit_partial_specializations {
+typedef char (&oneT)[1];
+typedef char (&twoT)[2];
+typedef char (&threeT)[3];
+typedef char (&fourT)[4];
+typedef char (&fiveT)[5];
+typedef char (&sixT)[6];
+
+char one[1];
+char two[2];
+char three[3];
+char four[4];
+char five[5];
+char six[6];
+
+template<bool b> struct bool_ { typedef int type; };
+template<> struct bool_<false> {  };
+
+#define XCAT(x,y) x ## y
+#define CAT(x,y) XCAT(x,y)
+#define sassert(_b_) bool_<(_b_)>::type CAT(var, __LINE__);
+
+
+template <int>
+struct L {
+  template <typename T>
+  struct O {
+    template <typename U>
+    static oneT Fun(U);
+    
+  };
+};
+template <int k>
+template <typename T>
+template <typename U>
+oneT L<k>::O<T>::Fun(U) { return one; }
+
+template<>
+template<>
+template<typename U>
+oneT L<0>::O<char>::Fun(U) { return one; }
+
+
+void Instantiate() { 
+  sassert(sizeof(L<0>::O<int>::Fun(0)) == sizeof(one)); 
+  sassert(sizeof(L<0>::O<char>::Fun(0)) == sizeof(one));
+}
+
+}