diff options
author | Reid Kleckner <rnk@google.com> | 2018-11-27 21:20:42 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2018-11-27 21:20:42 +0000 |
commit | 203f103b27d352b82b156a51f6309341432629d3 (patch) | |
tree | 3da35e085e04dc0dc173e6e447dccdb06a18d56c | |
parent | 681787a6f6b3b5ca4d267173c206fe4acc52c1fe (diff) | |
download | clang-203f103b27d352b82b156a51f6309341432629d3.tar.gz |
[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
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 35 | ||||
-rw-r--r-- | 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<ParseScope*, 4> TemplateParamScopeStack; - // Get the list of DeclContexts to reenter. - SmallVector<DeclContext*, 4> 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<DeclContext *, 1, bool> Pair; + DeclContext *getDC() { return Pair.getPointer(); } + bool shouldPushDC() { return Pair.getInt(); } + }; + SmallVector<ContainingDC, 4> 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<DeclContext *>::reverse_iterator II = - DeclContextsToReenter.rbegin(); - for (; II != DeclContextsToReenter.rend(); ++II) { - TemplateParamScopeStack.push_back(new ParseScope(this, - Scope::TemplateParamScope)); - unsigned NumParamLists = - Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II)); + for (ContainingDC CDC : reverse(DeclContextsToReenter)) { + TemplateParamScopeStack.push_back( + new ParseScope(this, Scope::TemplateParamScope)); + unsigned NumParamLists = Actions.ActOnReenterTemplateScope( + getCurScope(), cast<Decl>(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 <typename> + struct T { + static void foo() { + struct U { + void dummy() { + use_delayed_identifier(); + } + }; + } + }; +}; +void use_delayed_identifier(); +void trigger_PR38460() { + PR38460::T<int>::foo(); +} + +template <typename> struct PR38460_2 { + struct p { + struct G { + bool operator()(int) {} + }; + }; + static void as() { + typename p::G g; + g(0); + } +}; +template struct PR38460_2<int>; |