]> granicus.if.org Git - clang/commitdiff
Instantiate incomplete class used in template method.
authorSerge Pavlov <sepavloff@gmail.com>
Mon, 4 May 2015 16:44:39 +0000 (16:44 +0000)
committerSerge Pavlov <sepavloff@gmail.com>
Mon, 4 May 2015 16:44:39 +0000 (16:44 +0000)
If a class is absent from instantiation and is incomplete, instantiate it as
an incomplete class thus avoiding compiler crash.

This change fixes PR18653.

Differential Revision: http://reviews.llvm.org/D8281

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236426 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-local-class.cpp

index 62b506276e6e03c2f2d441ab7f81d165329205c6..187478255370bfbc20f796abcd57ef7b0f9468b7 100644 (file)
@@ -2788,6 +2788,11 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
       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))
+    return nullptr;
+
   // If we didn't find the decl, then we either have a sema bug, or we have a
   // forward reference to a label declaration.  Return null to indicate that
   // we have an uninstantiated label.
index 8f2e95a6152ac994cf0a03fc009db96543fec4c5..41245d9b3fd399fe6a7401449a01a69da9f213df 100644 (file)
@@ -4434,6 +4434,14 @@ 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 (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
+      Decl *Inst = SubstDecl(D, CurContext, TemplateArgs);
+      CurrentInstantiationScope->InstantiatedLocal(D, Inst);
+      return cast<TypeDecl>(Inst);
+    }
+
     // If we didn't find the decl, then we must have a label decl that hasn't
     // been found yet.  Lazily instantiate it and return it now.
     assert(isa<LabelDecl>(D));
index 367134a2a5311bc07040b0bf8a022a0f88faf2b1..3365c374072e7a787ea51699dc3c0d9f44e9864f 100644 (file)
@@ -213,3 +213,132 @@ namespace PR23194 {
     return make_seed_pair();
   }
 }
+
+namespace PR18653 {
+  // Forward declarations
+
+  template<typename T> void f1() {
+    void g1(struct x1);
+    struct x1 {};
+  }
+  template void f1<int>();
+
+  template<typename T> void f2() {
+    void g2(enum x2);  // expected-error{{ISO C++ forbids forward references to 'enum' types}}
+    enum x2 { nothing };
+  }
+  template void f2<int>();
+
+  template<typename T> void f3() {
+    void g3(enum class x3);
+    enum class x3 { nothing };
+  }
+  template void f3<int>();
+
+
+  template<typename T> void f4() {
+    void g4(struct x4 {} x);  // expected-error{{'x4' cannot be defined in a parameter type}}
+  }
+  template void f4<int>();
+
+
+  template <class T> void f();
+  template <class T> struct S1 {
+    void m() {
+      f<class newclass>();
+    }
+  };
+  template struct S1<int>;
+
+  template <class T> struct S2 {
+    void m() {
+      f<enum new_enum>();  // expected-error{{ISO C++ forbids forward references to 'enum' types}}
+    }
+  };
+  template struct S2<int>;
+
+  template <class T> struct S3 {
+    void m() {
+      f<enum class new_enum>();
+    }
+  };
+  template struct S3<int>;
+
+  template <class T> struct S4 {
+    struct local {};
+    void m() {
+      f<local>();
+    }
+  };
+  template struct S4<int>;
+
+  template <class T> struct S5 {
+    enum local { nothing };
+    void m() {
+      f<local>();
+    }
+  };
+  template struct S5<int>;
+
+  template <class T> struct S7 {
+    enum class local { nothing };
+    void m() {
+      f<local>();
+    }
+  };
+  template struct S7<int>;
+
+
+  template <class T> void fff(T *x);
+  template <class T> struct S01 {
+    struct local { };
+    void m() {
+      local x;
+      fff(&x);
+    }
+  };
+  template struct S01<int>;
+
+  template <class T> struct S02 {
+    enum local { nothing };
+    void m() {
+      local x;
+      fff(&x);
+    }
+  };
+  template struct S02<int>;
+
+  template <class T> struct S03 {
+    enum class local { nothing };
+    void m() {
+      local x;
+      fff(&x);
+    }
+  };
+  template struct S03<int>;
+
+
+  template <class T> struct S04 {
+    void m() {
+      struct { } x;
+      fff(&x);
+    }
+  };
+  template struct S04<int>;
+
+  template <class T> struct S05 {
+    void m() {
+      enum { nothing } x;
+      fff(&x);
+    }
+  };
+  template struct S05<int>;
+
+  template <class T> struct S06 {
+    void m() {
+      class { virtual void mmm() {} } x;
+      fff(&x);
+    }
+  };
+  template struct S06<int>;
+}