diff options
| author | Douglas Gregor <dgregor@apple.com> | 2009-10-15 12:53:22 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2009-10-15 12:53:22 +0000 |
| commit | 68edf132137eb20fd3edbb418420b267da0237a4 (patch) | |
| tree | 58b6d3732fa0772fa817328d773bd569b330e423 /clang | |
| parent | 917db86b42eeb6496339cda4da911fdf377f1f6c (diff) | |
| download | bcm5719-llvm-68edf132137eb20fd3edbb418420b267da0237a4.tar.gz bcm5719-llvm-68edf132137eb20fd3edbb418420b267da0237a4.zip | |
More explicit template instantiation. Now we're checking for more
cases where an explicit instantiation requires a definition; the
remainder of these checks will come with the implementation of
paragraph 4 of [temp.explicit].
llvm-svn: 84181
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 20 | ||||
| -rw-r--r-- | clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp | 55 |
3 files changed, 71 insertions, 6 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b1222a3f84e..c9803da719c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1112,6 +1112,8 @@ def err_explicit_instantiation_without_qualified_id_quals : Error< "qualifier in explicit instantiation of '%0%1' requires a template-id">; def err_explicit_instantiation_unqualified_wrong_namespace : Error< "explicit instantiation of %q0 must occur in %1">; +def err_explicit_instantiation_undefined_member_class : Error< + "explicit instantiation of undefined member class %0 of class template %1">; // C++ typename-specifiers def err_typename_nested_not_found : Error<"no type named %0 in %1">; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ab0bbe081db..04580b70b88 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3651,12 +3651,20 @@ Sema::ActOnExplicitInstantiation(Scope *S, CheckExplicitInstantiationScope(*this, Record, NameLoc, true); if (!Record->getDefinition(Context)) { - // If the class has a definition, instantiate it (and all of its - // members, recursively). - Pattern = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context)); - if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern, - getTemplateInstantiationArgs(Record), - TSK)) + // C++ [temp.explicit]p3: + // A definition of a member class of a class template shall be in scope + // at the point of an explicit instantiation of the member class. + CXXRecordDecl *Def + = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context)); + if (!Def) { + Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member_class) + << Record->getDeclName() << Record->getDeclContext(); + Diag(Pattern->getLocation(), diag::note_forward_declaration) + << Pattern; + return true; + } else if (InstantiateClass(TemplateLoc, Record, Def, + getTemplateInstantiationArgs(Record), + TSK)) return true; } else // Instantiate all of the members of the class. InstantiateClassMembers(TemplateLoc, Record, diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp new file mode 100644 index 00000000000..2bd781bbed2 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp @@ -0,0 +1,55 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// A declaration of a function template shall be in scope at the point of the +// explicit instantiation of the function template. +template<typename T> void f0(T) { } +template void f0(int); // okay + +// A definition of the class or class template containing a member function +// template shall be in scope at the point of the explicit instantiation of +// the member function template. +struct X0; // expected-note 2{{forward declaration}} +template<typename> struct X1; // expected-note 2{{declared here}} \ + // expected-note 3{{forward declaration}} + +// FIXME: Repeated diagnostics here! +template void X0::f0<int>(int); // expected-error 2{{incomplete type}} \ + // expected-error{{invalid token after}} +template void X1<int>::f0<int>(int); // expected-error{{implicit instantiation of undefined template}} \ + // expected-error{{incomplete type}} \\ + // expected-error{{invalid token}} + +// A definition of a class template or class member template shall be in scope +// at the point of the explicit instantiation of the class template or class +// member template. +template struct X1<float>; // expected-error{{explicit instantiation of undefined template}} + +template<typename T> +struct X2 { // expected-note 4{{refers here}} + template<typename U> + struct Inner; // expected-note{{declared here}} + + struct InnerClass; // expected-note{{forward declaration}} +}; + +template struct X2<int>::Inner<float>; // expected-error{{explicit instantiation of undefined template}} + +// A definition of a class template shall be in scope at the point of an +// explicit instantiation of a member function or a static data member of the +// class template. +template void X1<int>::f1(int); // expected-error{{incomplete type}} \ + // expected-error{{does not refer}} + +template int X1<int>::member; // expected-error{{incomplete type}} \ + // expected-error{{does not refer}} + +// A definition of a member class of a class template shall be in scope at the +// point of an explicit instantiation of the member class. +template struct X2<float>::InnerClass; // expected-error{{undefined member}} + +// If the declaration of the explicit instantiation names an implicitly-declared +// special member function (Clause 12), the program is ill-formed. +template X2<int>::X2(); // expected-error{{not an instantiation}} +template X2<int>::X2(const X2&); // expected-error{{not an instantiation}} +template X2<int>::~X2(); // expected-error{{not an instantiation}} +template X2<int> &X2<int>::operator=(const X2<int>&); // expected-error{{not an instantiation}} |

