summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2018-11-27 21:20:42 +0000
committerReid Kleckner <rnk@google.com>2018-11-27 21:20:42 +0000
commit203f103b27d352b82b156a51f6309341432629d3 (patch)
tree3da35e085e04dc0dc173e6e447dccdb06a18d56c
parent681787a6f6b3b5ca4d267173c206fe4acc52c1fe (diff)
downloadclang-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.cpp35
-rw-r--r--test/Parser/DelayedTemplateParsing.cpp30
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>;