r180708 - Keep the parser's template depth up to date when parsing local templates and
Richard Smith
richard-llvm at metafoo.co.uk
Mon Apr 29 04:55:39 PDT 2013
Author: rsmith
Date: Mon Apr 29 06:55:38 2013
New Revision: 180708
URL: http://llvm.org/viewvc/llvm-project?rev=180708&view=rev
Log:
Keep the parser's template depth up to date when parsing local templates and
late-parsed templates. Patch by Faisal Vali!
Added:
cfe/trunk/test/SemaTemplate/local-member-templates.cpp
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=180708&r1=180707&r2=180708&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Apr 29 06:55:38 2013
@@ -172,6 +172,25 @@ class Parser : public CodeCompletionHand
/// The "depth" of the template parameters currently being parsed.
unsigned TemplateParameterDepth;
+ /// \brief RAII class that manages the template parameter depth.
+ class TemplateParameterDepthRAII {
+ unsigned &Depth;
+ unsigned AddedLevels;
+ public:
+ explicit TemplateParameterDepthRAII(unsigned &Depth)
+ : Depth(Depth), AddedLevels(0) {}
+
+ ~TemplateParameterDepthRAII() {
+ Depth -= AddedLevels;
+ }
+
+ void operator++() {
+ ++Depth;
+ ++AddedLevels;
+ }
+ unsigned getDepth() const { return Depth; }
+ };
+
/// Factory object for creating AttributeList objects.
AttributeFactory AttrFactory;
Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=180708&r1=180707&r2=180708&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Mon Apr 29 06:55:38 2013
@@ -278,8 +278,11 @@ void Parser::LateParsedMemberInitializer
void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
- if (HasTemplateScope)
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+ if (HasTemplateScope) {
Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
+ ++CurTemplateDepthTracker;
+ }
// The current scope is still active if we're the top-level class.
// Otherwise we'll need to push and enter a new scope.
@@ -300,9 +303,11 @@ void Parser::ParseLexedMethodDeclaration
void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// If this is a member template, introduce the template parameter scope.
ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
- if (LM.TemplateScope)
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+ if (LM.TemplateScope) {
Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method);
-
+ ++CurTemplateDepthTracker;
+ }
// Start the delayed C++ method declaration
Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
@@ -378,9 +383,11 @@ void Parser::ParseLexedMethodDeclaration
void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
- if (HasTemplateScope)
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+ if (HasTemplateScope) {
Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
-
+ ++CurTemplateDepthTracker;
+ }
bool HasClassScope = !Class.TopLevelClass;
ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
HasClassScope);
@@ -393,9 +400,11 @@ void Parser::ParseLexedMethodDefs(Parsin
void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// If this is a member template, introduce the template parameter scope.
ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
- if (LM.TemplateScope)
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+ if (LM.TemplateScope) {
Actions.ActOnReenterTemplateScope(getCurScope(), LM.D);
-
+ ++CurTemplateDepthTracker;
+ }
// Save the current token position.
SourceLocation origLoc = Tok.getLocation();
@@ -440,6 +449,13 @@ void Parser::ParseLexedMethodDef(LexedMe
} else
Actions.ActOnDefaultCtorInitializers(LM.D);
+ assert((Actions.getDiagnostics().hasErrorOccurred() ||
+ !isa<FunctionTemplateDecl>(LM.D) ||
+ cast<FunctionTemplateDecl>(LM.D)->getTemplateParameters()->getDepth()
+ < TemplateParameterDepth) &&
+ "TemplateParameterDepth should be greater than the depth of "
+ "current template being instantiated!");
+
ParseFunctionStatementBody(LM.D, FnScope);
// Clear the late-template-parsed bit if we set it before.
@@ -465,9 +481,11 @@ void Parser::ParseLexedMemberInitializer
bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
HasTemplateScope);
- if (HasTemplateScope)
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+ if (HasTemplateScope) {
Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
-
+ ++CurTemplateDepthTracker;
+ }
// Set or update the scope flags.
bool AlreadyHasClassScope = Class.TopLevelClass;
unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope;
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=180708&r1=180707&r2=180708&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Mon Apr 29 06:55:38 2013
@@ -39,28 +39,7 @@ Parser::ParseDeclarationStartingWithTemp
AccessAttrs);
}
-/// \brief RAII class that manages the template parameter depth.
-namespace {
- class 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.
///
@@ -117,7 +96,8 @@ Parser::ParseTemplateDeclarationOrSpecia
bool isSpecialization = true;
bool LastParamListWasEmpty = false;
TemplateParameterLists ParamLists;
- TemplateParameterDepthCounter Depth(TemplateParameterDepth);
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+
do {
// Consume the 'export', if any.
SourceLocation ExportLoc;
@@ -137,8 +117,8 @@ Parser::ParseTemplateDeclarationOrSpecia
// Parse the '<' template-parameter-list '>'
SourceLocation LAngleLoc, RAngleLoc;
SmallVector<Decl*, 4> TemplateParams;
- if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc,
- RAngleLoc)) {
+ if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(),
+ TemplateParams, LAngleLoc, RAngleLoc)) {
// Skip until the semi-colon or a }.
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
@@ -147,14 +127,15 @@ Parser::ParseTemplateDeclarationOrSpecia
}
ParamLists.push_back(
- Actions.ActOnTemplateParameterList(Depth, ExportLoc,
+ Actions.ActOnTemplateParameterList(CurTemplateDepthTracker.getDepth(),
+ ExportLoc,
TemplateLoc, LAngleLoc,
TemplateParams.data(),
TemplateParams.size(), RAngleLoc));
if (!TemplateParams.empty()) {
isSpecialization = false;
- ++Depth;
+ ++CurTemplateDepthTracker;
} else {
LastParamListWasEmpty = true;
}
@@ -1249,11 +1230,11 @@ void Parser::ParseLateTemplatedFuncDef(L
return;
// Get the FunctionDecl.
- FunctionDecl *FD = 0;
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D))
- FD = FunTmpl->getTemplatedDecl();
- else
- FD = cast<FunctionDecl>(LMT.D);
+ FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LMT.D);
+ FunctionDecl *FunD =
+ FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LMT.D);
+ // Track template parameter depth.
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
// To restore the context after late parsing.
Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext);
@@ -1262,7 +1243,7 @@ void Parser::ParseLateTemplatedFuncDef(L
// Get the list of DeclContexts to reenter.
SmallVector<DeclContext*, 4> DeclContextsToReenter;
- DeclContext *DD = FD->getLexicalParent();
+ DeclContext *DD = FunD->getLexicalParent();
while (DD && !DD->isTranslationUnit()) {
DeclContextsToReenter.push_back(DD);
DD = DD->getLexicalParent();
@@ -1277,12 +1258,14 @@ void Parser::ParseLateTemplatedFuncDef(L
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope));
Actions.ActOnReenterTemplateScope(getCurScope(), MD);
+ ++CurTemplateDepthTracker;
} else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
bool ManageScope = MD->getDescribedClassTemplate() != 0;
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope, ManageScope));
Actions.ActOnReenterTemplateScope(getCurScope(),
MD->getDescribedClassTemplate());
+ ++CurTemplateDepthTracker;
}
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
Actions.PushDeclContext(Actions.getCurScope(), *II);
@@ -1290,10 +1273,13 @@ void Parser::ParseLateTemplatedFuncDef(L
TemplateParamScopeStack.push_back(
new ParseScope(this, Scope::TemplateParamScope));
- DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FD);
- if (Declarator && Declarator->getNumTemplateParameterLists() != 0)
+ DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD);
+ if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
+ ++CurTemplateDepthTracker;
+ }
Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
+ ++CurTemplateDepthTracker;
assert(!LMT.Toks.empty() && "Empty body!");
@@ -1312,15 +1298,9 @@ void Parser::ParseLateTemplatedFuncDef(L
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
// Recreate the containing function DeclContext.
- Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FD));
-
- if (FunctionTemplateDecl *FunctionTemplate
- = dyn_cast_or_null<FunctionTemplateDecl>(LMT.D))
- Actions.ActOnStartOfFunctionDef(getCurScope(),
- FunctionTemplate->getTemplatedDecl());
- if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D))
- Actions.ActOnStartOfFunctionDef(getCurScope(), Function);
+ Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FunD));
+ Actions.ActOnStartOfFunctionDef(getCurScope(), FunD);
if (Tok.is(tok::kw_try)) {
ParseFunctionTryBlock(LMT.D, FnScope);
@@ -1331,8 +1311,12 @@ void Parser::ParseLateTemplatedFuncDef(L
Actions.ActOnDefaultCtorInitializers(LMT.D);
if (Tok.is(tok::l_brace)) {
+ assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() <
+ TemplateParameterDepth) &&
+ "TemplateParameterDepth should be greater than the depth of "
+ "current template being instantiated!");
ParseFunctionStatementBody(LMT.D, FnScope);
- Actions.MarkAsLateParsedTemplate(FD, false);
+ Actions.MarkAsLateParsedTemplate(FunD, false);
} else
Actions.ActOnFinishFunctionBody(LMT.D, 0);
}
Added: cfe/trunk/test/SemaTemplate/local-member-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/local-member-templates.cpp?rev=180708&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/local-member-templates.cpp (added)
+++ cfe/trunk/test/SemaTemplate/local-member-templates.cpp Mon Apr 29 06:55:38 2013
@@ -0,0 +1,76 @@
+// RUN: %clang_cc1 -std=c++1y -verify %s
+// RUN: %clang_cc1 -std=c++1y -verify %s -fdelayed-template-parsing
+
+namespace nested_local_templates_1 {
+
+template <class T> struct Outer {
+ template <class U> int outer_mem(T t, U u) {
+ struct Inner {
+ template <class V> int inner_mem(T t, U u, V v) {
+ struct InnerInner {
+ template <class W> int inner_inner_mem(W w, T t, U u, V v) {
+ return 0;
+ }
+ };
+ InnerInner().inner_inner_mem("abc", t, u, v);
+ return 0;
+ }
+ };
+ Inner i;
+ i.inner_mem(t, u, 3.14);
+ return 0;
+ }
+
+ template <class U> int outer_mem(T t, U *u);
+};
+
+template int Outer<int>::outer_mem(int, char);
+
+template <class T> template <class U> int Outer<T>::outer_mem(T t, U *u) {
+ struct Inner {
+ template <class V>
+ int inner_mem(T t, U u, V v) { //expected-note{{candidate function}}
+ struct InnerInner {
+ template <class W> int inner_inner_mem(W w, T t, U u, V v) { return 0; }
+ };
+ InnerInner().inner_inner_mem("abc", t, u, v);
+ return 0;
+ }
+ };
+ Inner i;
+ i.inner_mem(t, U{}, i);
+ i.inner_mem(t, u, 3.14); //expected-error{{no matching member function for call to 'inner}}
+ return 0;
+}
+
+template int Outer<int>::outer_mem(int, char *); //expected-note{{in instantiation of function}}
+
+} // end ns
+
+namespace nested_local_templates_2 {
+
+template <class T> struct Outer {
+ template <class U> void outer_mem(T t, U u) {
+ struct Inner {
+ template <class V> struct InnerTemplateClass {
+ template <class W>
+ void itc_mem(T t, U u, V v, W w) { //expected-note{{candidate function}}
+ struct InnerInnerInner {
+ template <class X> void iii_mem(X x) {}
+ };
+ InnerInnerInner i;
+ i.iii_mem("abc");
+ }
+ };
+ };
+ Inner i;
+ typename Inner::template InnerTemplateClass<Inner> ii;
+ ii.itc_mem(t, u, i, "jim");
+ ii.itc_mem(t, u, 0, "abd"); //expected-error{{no matching member function}}
+ }
+};
+
+template void
+Outer<int>::outer_mem(int, char); //expected-note{{in instantiation of}}
+
+}
More information about the cfe-commits
mailing list