forked from OSchip/llvm-project
[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. llvm-svn: 347713
This commit is contained in:
parent
6052d09c05
commit
229eee49fc
|
@ -1381,26 +1381,37 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
|
||||||
|
|
||||||
SmallVector<ParseScope*, 4> TemplateParamScopeStack;
|
SmallVector<ParseScope*, 4> TemplateParamScopeStack;
|
||||||
|
|
||||||
// Get the list of DeclContexts to reenter.
|
// Get the list of DeclContexts to reenter. For inline methods, we only want
|
||||||
SmallVector<DeclContext*, 4> DeclContextsToReenter;
|
// 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 *DD = FunD;
|
||||||
|
DeclContext *NextContaining = Actions.getContainingDC(DD);
|
||||||
while (DD && !DD->isTranslationUnit()) {
|
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();
|
DD = DD->getLexicalParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reenter template scopes from outermost to innermost.
|
// Reenter template scopes from outermost to innermost.
|
||||||
SmallVectorImpl<DeclContext *>::reverse_iterator II =
|
for (ContainingDC CDC : reverse(DeclContextsToReenter)) {
|
||||||
DeclContextsToReenter.rbegin();
|
TemplateParamScopeStack.push_back(
|
||||||
for (; II != DeclContextsToReenter.rend(); ++II) {
|
new ParseScope(this, Scope::TemplateParamScope));
|
||||||
TemplateParamScopeStack.push_back(new ParseScope(this,
|
unsigned NumParamLists = Actions.ActOnReenterTemplateScope(
|
||||||
Scope::TemplateParamScope));
|
getCurScope(), cast<Decl>(CDC.getDC()));
|
||||||
unsigned NumParamLists =
|
|
||||||
Actions.ActOnReenterTemplateScope(getCurScope(), cast<Decl>(*II));
|
|
||||||
CurTemplateDepthTracker.addDepth(NumParamLists);
|
CurTemplateDepthTracker.addDepth(NumParamLists);
|
||||||
if (*II != FunD) {
|
if (CDC.shouldPushDC()) {
|
||||||
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
|
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
|
||||||
Actions.PushDeclContext(Actions.getCurScope(), *II);
|
Actions.PushDeclContext(Actions.getCurScope(), CDC.getDC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
Loading…
Reference in New Issue