From 203f103b27d352b82b156a51f6309341432629d3 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 27 Nov 2018 21:20:42 +0000 Subject: [PATCH] [MS] Push outermost class DeclContexts only in -fdelayed-template-parsing This is more or less a complete rewrite of r347627, and it fixes PR38460 I added a reduced test case to DelayedTemplateParsing.cpp. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@347713 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseTemplate.cpp | 35 +++++++++++++++++--------- test/Parser/DelayedTemplateParsing.cpp | 30 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 26709a5aaa..e0a7cc6e85 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -1381,26 +1381,37 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { SmallVector TemplateParamScopeStack; - // Get the list of DeclContexts to reenter. - SmallVector DeclContextsToReenter; + // Get the list of DeclContexts to reenter. For inline methods, we only want + // to push the DeclContext of the outermost class. This matches the way the + // parser normally parses bodies of inline methods when the outermost class is + // complete. + struct ContainingDC { + ContainingDC(DeclContext *DC, bool ShouldPush) : Pair(DC, ShouldPush) {} + llvm::PointerIntPair Pair; + DeclContext *getDC() { return Pair.getPointer(); } + bool shouldPushDC() { return Pair.getInt(); } + }; + SmallVector DeclContextsToReenter; DeclContext *DD = FunD; + DeclContext *NextContaining = Actions.getContainingDC(DD); while (DD && !DD->isTranslationUnit()) { - DeclContextsToReenter.push_back(DD); + bool ShouldPush = DD == NextContaining; + DeclContextsToReenter.push_back({DD, ShouldPush}); + if (ShouldPush) + NextContaining = Actions.getContainingDC(DD); DD = DD->getLexicalParent(); } // Reenter template scopes from outermost to innermost. - SmallVectorImpl::reverse_iterator II = - DeclContextsToReenter.rbegin(); - for (; II != DeclContextsToReenter.rend(); ++II) { - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope)); - unsigned NumParamLists = - Actions.ActOnReenterTemplateScope(getCurScope(), cast(*II)); + for (ContainingDC CDC : reverse(DeclContextsToReenter)) { + TemplateParamScopeStack.push_back( + new ParseScope(this, Scope::TemplateParamScope)); + unsigned NumParamLists = Actions.ActOnReenterTemplateScope( + getCurScope(), cast(CDC.getDC())); CurTemplateDepthTracker.addDepth(NumParamLists); - if (*II != FunD) { + if (CDC.shouldPushDC()) { TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope)); - Actions.PushDeclContext(Actions.getCurScope(), *II); + Actions.PushDeclContext(Actions.getCurScope(), CDC.getDC()); } } diff --git a/test/Parser/DelayedTemplateParsing.cpp b/test/Parser/DelayedTemplateParsing.cpp index 6ea245c2d4..c65e80b1f7 100644 --- a/test/Parser/DelayedTemplateParsing.cpp +++ b/test/Parser/DelayedTemplateParsing.cpp @@ -181,3 +181,33 @@ static void h() { } } + +struct PR38460 { + template + struct T { + static void foo() { + struct U { + void dummy() { + use_delayed_identifier(); + } + }; + } + }; +}; +void use_delayed_identifier(); +void trigger_PR38460() { + PR38460::T::foo(); +} + +template struct PR38460_2 { + struct p { + struct G { + bool operator()(int) {} + }; + }; + static void as() { + typename p::G g; + g(0); + } +}; +template struct PR38460_2; -- 2.40.0