forked from OSchip/llvm-project
Instantiate incomplete class used in template method.
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 llvm-svn: 236426
This commit is contained in:
parent
19f731f0ea
commit
4c51174677
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue