summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2018-11-27 02:21:51 +0000
committerReid Kleckner <rnk@google.com>2018-11-27 02:21:51 +0000
commit5cec19dc1aabeda486aa47845f82fb67a5a899b4 (patch)
tree8fff2da9f1a22c9ad37d99bcfb8d7421c1b020fd
parent44abeb5c3caa99ecdfec8ac6d7c65cc7640d24d4 (diff)
downloadbcm5719-llvm-5cec19dc1aabeda486aa47845f82fb67a5a899b4.tar.gz
bcm5719-llvm-5cec19dc1aabeda486aa47845f82fb67a5a899b4.zip
[MS] Push fewer DeclContexts for delayed template parsing
Only push the outermost record as a DeclContext when parsing a function body. See the comments in Sema::getContainingDC about the way the parser pushes contexts. This is intended to match the behavior the parser normally displays where it parses all method bodies from all nested classes at the end of the outermost class, when all nested classes are complete. Fixes PR38460. llvm-svn: 347627
-rw-r--r--clang/lib/Parse/ParseTemplate.cpp9
-rw-r--r--clang/test/Parser/DelayedTemplateParsing.cpp17
2 files changed, 24 insertions, 2 deletions
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 26709a5aaa6..55f80f231f3 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1382,7 +1382,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
SmallVector<ParseScope*, 4> TemplateParamScopeStack;
// Get the list of DeclContexts to reenter.
- SmallVector<DeclContext*, 4> DeclContextsToReenter;
+ SmallVector<DeclContext *, 4> DeclContextsToReenter;
DeclContext *DD = FunD;
while (DD && !DD->isTranslationUnit()) {
DeclContextsToReenter.push_back(DD);
@@ -1398,7 +1398,12 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
unsigned NumParamLists =
Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II));
CurTemplateDepthTracker.addDepth(NumParamLists);
- if (*II != FunD) {
+ // If we find a class in a class, we need to push the context of the
+ // outermost class to match up with how we would parse a regular C++ class
+ // inline method.
+ if (*II != FunD &&
+ !(isa<CXXRecordDecl>(*II) && isa<CXXRecordDecl>(Actions.CurContext) &&
+ Actions.CurContext == (*II)->getLexicalParent())) {
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
Actions.PushDeclContext(Actions.getCurScope(), *II);
}
diff --git a/clang/test/Parser/DelayedTemplateParsing.cpp b/clang/test/Parser/DelayedTemplateParsing.cpp
index 6ea245c2d4e..301eacfabba 100644
--- a/clang/test/Parser/DelayedTemplateParsing.cpp
+++ b/clang/test/Parser/DelayedTemplateParsing.cpp
@@ -181,3 +181,20 @@ 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();
+}
OpenPOWER on IntegriCloud