[modules] Fix assert/crash when parsing and merging a definition of a… · llvm/llvm-project@0f192e8 (original) (raw)

File tree

4 files changed

lines changed

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -1850,10 +1850,10 @@ class Sema {
1850 1850 /// struct, or union).
1851 1851 void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
1852 1852
1853 +typedef void *SkippedDefinitionContext;
1854 +
1853 1855 /// \brief Invoked when we enter a tag definition that we're skipping.
1854 -void ActOnTagStartSkippedDefinition(Scope *S, Decl *TD) {
1855 -PushDeclContext(S, cast(TD));
1856 - }
1856 + SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD);
1857 1857
1858 1858 Decl *ActOnObjCContainerStartDefinition(Decl *IDecl);
1859 1859
@@ -1870,9 +1870,7 @@ class Sema {
1870 1870 void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
1871 1871 SourceLocation RBraceLoc);
1872 1872
1873 -void ActOnTagFinishSkippedDefinition() {
1874 -PopDeclContext();
1875 - }
1873 +void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
1876 1874
1877 1875 void ActOnObjCContainerFinishDefinition();
1878 1876
Original file line number Diff line number Diff line change
@@ -2724,12 +2724,13 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
2724 2724 ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
2725 2725 ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true,
2726 2726 TagType == DeclSpec::TST_interface);
2727 - Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);
2727 +auto OldContext =
2728 + Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);
2728 2729
2729 2730 // Parse the bases but don't attach them to the class.
2730 2731 ParseBaseClause(nullptr);
2731 2732
2732 - Actions.ActOnTagFinishSkippedDefinition();
2733 + Actions.ActOnTagFinishSkippedDefinition(OldContext);
2733 2734
2734 2735 if (!Tok.is(tok::l_brace)) {
2735 2736 Diag(PP.getLocForEndOfToken(PrevTokLocation),
Original file line number Diff line number Diff line change
@@ -1081,6 +1081,22 @@ void Sema::PopDeclContext() {
1081 1081 assert(CurContext && "Popped translation unit!");
1082 1082 }
1083 1083
1084 +Sema::SkippedDefinitionContext Sema::ActOnTagStartSkippedDefinition(Scope *S,
1085 + Decl *D) {
1086 + // Unlike PushDeclContext, the context to which we return is not necessarily
1087 + // the containing DC of TD, because the new context will be some pre-existing
1088 + // TagDecl definition instead of a fresh one.
1089 + auto Result = static_cast(CurContext);
1090 + CurContext = cast(D)->getDefinition();
1091 + assert(CurContext && "skipping definition of undefined tag");
1092 + S->setEntity(CurContext);
1093 + return Result;
1094 +}
1095 +
1096 +void Sema::ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context) {
1097 + CurContext = static_cast<decltype(CurContext)>(Context);
1098 +}
1099 +
1084 1100 /// EnterDeclaratorContext - Used when we must lookup names in the context
1085 1101 /// of a declarator's nested name specifier.
1086 1102 ///
Original file line number Diff line number Diff line change
@@ -49,8 +49,8 @@ template<typename T = int, int N = 3, template class K = F> using I =
49 49
50 50 namespace NS {
51 51 struct A {};
52 -template struct B {};
53 -template struct B<T*> {};
54 -template<> struct B<int> {};
52 +template struct B : A {};
53 +template struct B<T*> : B<char> {};
54 +template<> struct B<int> : B<int*> {};
55 55 inline void f() {}
56 56 }