From 52636aa16aab0ffceb9036ef3b00dab34bc6a04b Mon Sep 17 00:00:00 2001 From: Faisal Vali Date: Wed, 4 Dec 2013 03:51:14 +0000 Subject: [PATCH] Fix PR17637: incorrect calculation of template parameter depth 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 | 4 ++ lib/Parse/ParseTemplate.cpp | 6 ++- test/Parser/cxx-template-argument.cpp | 1 + test/Parser/cxx-template-decl.cpp | 77 +++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 81ba5e1882..f23d4fb8a5 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -193,6 +193,10 @@ class Parser : public CodeCompletionHandler { ++Depth; ++AddedLevels; } + void addDepth(unsigned D) { + Depth += D; + AddedLevels += D; + } unsigned getDepth() const { return Depth; } }; diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 076edb93fa..8275922a6e 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -1304,9 +1304,11 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { new ParseScope(this, Scope::TemplateParamScope)); DeclaratorDecl *Declarator = dyn_cast(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; diff --git a/test/Parser/cxx-template-argument.cpp b/test/Parser/cxx-template-argument.cpp index 8bf2a4f78a..bbd53b2bdd 100644 --- a/test/Parser/cxx-template-argument.cpp +++ b/test/Parser/cxx-template-argument.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s -fdelayed-template-parsing template struct A {}; diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp index 81269ce254..8742900122 100644 --- a/test/Parser/cxx-template-decl.cpp +++ b/test/Parser/cxx-template-decl.cpp @@ -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 class T> struct shadow8 { // expected-note{{template template void f(int& i) { i = Size; + #ifdef DELAYED_TEMPLATE_PARSING + Size = i; + #else Size = i; // expected-error{{expression is not assignable}} + #endif } template @@ -127,3 +134,73 @@ namespace PR6184 { template void N::bar(typename T::x) { } } + +// This PR occurred only in template parsing mode. +namespace PR17637 { +template +struct L { + template + struct O { + template + static void Fun(U); + }; +}; + +template +template +template +void L::O::Fun(U) {} + +void Instantiate() { L<0>::O::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 struct bool_ { typedef int type; }; +template<> struct bool_ { }; + +#define XCAT(x,y) x ## y +#define CAT(x,y) XCAT(x,y) +#define sassert(_b_) bool_<(_b_)>::type CAT(var, __LINE__); + + +template +struct L { + template + struct O { + template + static oneT Fun(U); + + }; +}; +template +template +template +oneT L::O::Fun(U) { return one; } + +template<> +template<> +template +oneT L<0>::O::Fun(U) { return one; } + + +void Instantiate() { + sassert(sizeof(L<0>::O::Fun(0)) == sizeof(one)); + sassert(sizeof(L<0>::O::Fun(0)) == sizeof(one)); +} + +} -- 2.40.0