From d0a49e2f5421c8485e2099510b13d544acc035dc Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Fri, 15 May 2015 10:10:28 +0000 Subject: [PATCH] Limit set of types instantiated in FindInstantiatedDecl. Starting from r236426 FindInstantiatedDecl may instantiate types that are referenced before definition. This change limit the set of types that can be instantiated by this function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@237434 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateInstantiate.cpp | 11 ++++-- lib/Sema/SemaTemplateInstantiateDecl.cpp | 22 +++++++++-- test/SemaTemplate/instantiate-local-class.cpp | 37 +++++++++++++++++++ 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 1874782553..82ff7c0ca4 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2788,9 +2788,14 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) { isa(D)) return nullptr; - // Tag type may be referenced prior to definition, in this case it does not - // have instantiation yet. - if (isa(D)) + // Local types referenced prior to definition may require instantiation. + if (const CXXRecordDecl *RD = dyn_cast(D)) + if (RD->isLocalClass()) + return nullptr; + + // Enumeration types referenced prior to definition may appear as a result of + // error recovery. + if (isa(D)) return nullptr; // If we didn't find the decl, then we either have a sema bug, or we have a diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 4a92efdaae..5c994f86bd 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4442,9 +4442,25 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, if (D->isInvalidDecl()) return nullptr; - // Tag type may be referenced prior to definition, in this case it must be - // instantiated now. - if (isa(D)) { + // Normally this function only searches for already instantiated declaration + // however we have to make an exclusion for local types used before + // definition as in the code: + // + // template void f1() { + // void g1(struct x1); + // struct x1 {}; + // } + // + // In this case instantiation of the type of 'g1' requires definition of + // 'x1', which is defined later. Error recovery may produce an enum used + // before definition. In these cases we need to instantiate relevant + // declarations here. + bool NeedInstantiate = false; + if (CXXRecordDecl *RD = dyn_cast(D)) + NeedInstantiate = RD->isLocalClass(); + else + NeedInstantiate = isa(D); + if (NeedInstantiate) { Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); CurrentInstantiationScope->InstantiatedLocal(D, Inst); return cast(Inst); diff --git a/test/SemaTemplate/instantiate-local-class.cpp b/test/SemaTemplate/instantiate-local-class.cpp index ff6cf7923f..f58d7a4962 100644 --- a/test/SemaTemplate/instantiate-local-class.cpp +++ b/test/SemaTemplate/instantiate-local-class.cpp @@ -225,6 +225,12 @@ namespace PR18653 { } template void f1(); + template void f1a() { + void g1(union x1); + union x1 {}; + } + template void f1a(); + template void f2() { void g2(enum x2); // expected-error{{ISO C++ forbids forward references to 'enum' types}} enum x2 { nothing }; @@ -243,11 +249,17 @@ namespace PR18653 { } template void f4(); + template void f4a() { + void g4(union x4 {} x); // expected-error{{'x4' cannot be defined in a parameter type}} + } + template void f4a(); + template void f(); template struct S1 { void m() { f(); + f(); } }; template struct S1; @@ -274,6 +286,14 @@ namespace PR18653 { }; template struct S4; + template struct S4a { + union local {}; + void m() { + f(); + } + }; + template struct S4a; + template struct S5 { enum local { nothing }; void m() { @@ -301,6 +321,15 @@ namespace PR18653 { }; template struct S01; + template struct S01a { + union local { }; + void m() { + local x; + fff(&x); + } + }; + template struct S01a; + template struct S02 { enum local { nothing }; void m() { @@ -328,6 +357,14 @@ namespace PR18653 { }; template struct S04; + template struct S04a { + void m() { + union { } x; + fff(&x); + } + }; + template struct S04a; + template struct S05 { void m() { enum { nothing } x; -- 2.50.1