Skip to content

Commit 0f192e8

Browse files
committed
[modules] Fix assert/crash when parsing and merging a definition of a class with a base-specifier inside a namespace.
llvm-svn: 239569
1 parent 03cb0d8 commit 0f192e8

File tree

4 files changed

+26
-11
lines changed

4 files changed

+26
-11
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,10 +1850,10 @@ class Sema {
18501850
/// struct, or union).
18511851
void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
18521852

1853+
typedef void *SkippedDefinitionContext;
1854+
18531855
/// \brief Invoked when we enter a tag definition that we're skipping.
1854-
void ActOnTagStartSkippedDefinition(Scope *S, Decl *TD) {
1855-
PushDeclContext(S, cast<DeclContext>(TD));
1856-
}
1856+
SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD);
18571857

18581858
Decl *ActOnObjCContainerStartDefinition(Decl *IDecl);
18591859

@@ -1870,9 +1870,7 @@ class Sema {
18701870
void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
18711871
SourceLocation RBraceLoc);
18721872

1873-
void ActOnTagFinishSkippedDefinition() {
1874-
PopDeclContext();
1875-
}
1873+
void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
18761874

18771875
void ActOnObjCContainerFinishDefinition();
18781876

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2724,12 +2724,13 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
27242724
ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
27252725
ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true,
27262726
TagType == DeclSpec::TST_interface);
2727-
Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);
2727+
auto OldContext =
2728+
Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);
27282729

27292730
// Parse the bases but don't attach them to the class.
27302731
ParseBaseClause(nullptr);
27312732

2732-
Actions.ActOnTagFinishSkippedDefinition();
2733+
Actions.ActOnTagFinishSkippedDefinition(OldContext);
27332734

27342735
if (!Tok.is(tok::l_brace)) {
27352736
Diag(PP.getLocForEndOfToken(PrevTokLocation),

clang/lib/Sema/SemaDecl.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,22 @@ void Sema::PopDeclContext() {
10811081
assert(CurContext && "Popped translation unit!");
10821082
}
10831083

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<SkippedDefinitionContext>(CurContext);
1090+
CurContext = cast<TagDecl>(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+
10841100
/// EnterDeclaratorContext - Used when we must lookup names in the context
10851101
/// of a declarator's nested name specifier.
10861102
///

clang/test/Modules/Inputs/submodules-merge-defs/defs.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ template<typename T = int, int N = 3, template<typename> class K = F> using I =
4949

5050
namespace NS {
5151
struct A {};
52-
template<typename T> struct B {};
53-
template<typename T> struct B<T*> {};
54-
template<> struct B<int> {};
52+
template<typename T> struct B : A {};
53+
template<typename T> struct B<T*> : B<char> {};
54+
template<> struct B<int> : B<int*> {};
5555
inline void f() {}
5656
}

0 commit comments

Comments
 (0)