r237434 - Limit set of types instantiated in FindInstantiatedDecl.

Serge Pavlov sepavloff at gmail.com
Fri May 15 03:10:28 PDT 2015


Author: sepavloff
Date: Fri May 15 05:10:28 2015
New Revision: 237434

URL: http://llvm.org/viewvc/llvm-project?rev=237434&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=237434&r1=237433&r2=237434&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri May 15 05:10:28 2015
@@ -2788,9 +2788,14 @@ LocalInstantiationScope::findInstantiati
       isa<TemplateTemplateParmDecl>(D))
     return nullptr;
 
-  // Tag type may be referenced prior to definition, in this case it does not
-  // have instantiation yet.
-  if (isa<TagDecl>(D))
+  // Local types referenced prior to definition may require instantiation.
+  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
+    if (RD->isLocalClass())
+      return nullptr;
+
+  // Enumeration types referenced prior to definition may appear as a result of
+  // error recovery.
+  if (isa<EnumDecl>(D))
     return nullptr;
 
   // If we didn't find the decl, then we either have a sema bug, or we have a

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=237434&r1=237433&r2=237434&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri May 15 05:10:28 2015
@@ -4442,9 +4442,25 @@ NamedDecl *Sema::FindInstantiatedDecl(So
     if (D->isInvalidDecl())
       return nullptr;
 
-    // Tag type may be referenced prior to definition, in this case it must be
-    // instantiated now.
-    if (isa<TagDecl>(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<typename T> 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<CXXRecordDecl>(D))
+      NeedInstantiate = RD->isLocalClass();
+    else
+      NeedInstantiate = isa<EnumDecl>(D);
+    if (NeedInstantiate) {
       Decl *Inst = SubstDecl(D, CurContext, TemplateArgs);
       CurrentInstantiationScope->InstantiatedLocal(D, Inst);
       return cast<TypeDecl>(Inst);

Modified: cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp?rev=237434&r1=237433&r2=237434&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-local-class.cpp Fri May 15 05:10:28 2015
@@ -225,6 +225,12 @@ namespace PR18653 {
   }
   template void f1<int>();
 
+  template<typename T> void f1a() {
+    void g1(union x1);
+    union x1 {};
+  }
+  template void f1a<int>();
+
   template<typename T> 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<int>();
 
+  template<typename T> void f4a() {
+    void g4(union x4 {} x);  // expected-error{{'x4' cannot be defined in a parameter type}}
+  }
+  template void f4a<int>();
+
 
   template <class T> void f();
   template <class T> struct S1 {
     void m() {
       f<class newclass>();
+      f<union newunion>();
     }
   };
   template struct S1<int>;
@@ -274,6 +286,14 @@ namespace PR18653 {
   };
   template struct S4<int>;
 
+  template <class T> struct S4a {
+    union local {};
+    void m() {
+      f<local>();
+    }
+  };
+  template struct S4a<int>;
+
   template <class T> struct S5 {
     enum local { nothing };
     void m() {
@@ -301,6 +321,15 @@ namespace PR18653 {
   };
   template struct S01<int>;
 
+  template <class T> struct S01a {
+    union local { };
+    void m() {
+      local x;
+      fff(&x);
+    }
+  };
+  template struct S01a<int>;
+
   template <class T> struct S02 {
     enum local { nothing };
     void m() {
@@ -328,6 +357,14 @@ namespace PR18653 {
   };
   template struct S04<int>;
 
+  template <class T> struct S04a {
+    void m() {
+      union { } x;
+      fff(&x);
+    }
+  };
+  template struct S04a<int>;
+
   template <class T> struct S05 {
     void m() {
       enum { nothing } x;





More information about the cfe-commits mailing list