diff options
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 10 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 16 | ||||
| -rw-r--r-- | clang/test/Modules/Inputs/submodules-merge-defs/defs.h | 6 |
4 files changed, 26 insertions, 11 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 03ecf96ea30..28c09a1c604 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1850,10 +1850,10 @@ public: /// struct, or union). void ActOnTagStartDefinition(Scope *S, Decl *TagDecl); + typedef void *SkippedDefinitionContext; + /// \brief Invoked when we enter a tag definition that we're skipping. - void ActOnTagStartSkippedDefinition(Scope *S, Decl *TD) { - PushDeclContext(S, cast<DeclContext>(TD)); - } + SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD); Decl *ActOnObjCContainerStartDefinition(Decl *IDecl); @@ -1870,9 +1870,7 @@ public: void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl, SourceLocation RBraceLoc); - void ActOnTagFinishSkippedDefinition() { - PopDeclContext(); - } + void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context); void ActOnObjCContainerFinishDefinition(); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 53e4a419682..55909de0928 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2724,12 +2724,13 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope); ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true, TagType == DeclSpec::TST_interface); - Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl); + auto OldContext = + Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl); // Parse the bases but don't attach them to the class. ParseBaseClause(nullptr); - Actions.ActOnTagFinishSkippedDefinition(); + Actions.ActOnTagFinishSkippedDefinition(OldContext); if (!Tok.is(tok::l_brace)) { Diag(PP.getLocForEndOfToken(PrevTokLocation), diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a4a73753383..347d8070a6b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1081,6 +1081,22 @@ void Sema::PopDeclContext() { assert(CurContext && "Popped translation unit!"); } +Sema::SkippedDefinitionContext Sema::ActOnTagStartSkippedDefinition(Scope *S, + Decl *D) { + // Unlike PushDeclContext, the context to which we return is not necessarily + // the containing DC of TD, because the new context will be some pre-existing + // TagDecl definition instead of a fresh one. + auto Result = static_cast<SkippedDefinitionContext>(CurContext); + CurContext = cast<TagDecl>(D)->getDefinition(); + assert(CurContext && "skipping definition of undefined tag"); + S->setEntity(CurContext); + return Result; +} + +void Sema::ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context) { + CurContext = static_cast<decltype(CurContext)>(Context); +} + /// EnterDeclaratorContext - Used when we must lookup names in the context /// of a declarator's nested name specifier. /// diff --git a/clang/test/Modules/Inputs/submodules-merge-defs/defs.h b/clang/test/Modules/Inputs/submodules-merge-defs/defs.h index d65e93bf72b..1ab1d1a005b 100644 --- a/clang/test/Modules/Inputs/submodules-merge-defs/defs.h +++ b/clang/test/Modules/Inputs/submodules-merge-defs/defs.h @@ -49,8 +49,8 @@ template<typename T = int, int N = 3, template<typename> class K = F> using I = namespace NS { struct A {}; - template<typename T> struct B {}; - template<typename T> struct B<T*> {}; - template<> struct B<int> {}; + template<typename T> struct B : A {}; + template<typename T> struct B<T*> : B<char> {}; + template<> struct B<int> : B<int*> {}; inline void f() {} } |

