diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8fda370e058c..abd11c74d374 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1575,6 +1575,8 @@ def err_explicit_instantiation_nontemplate_type : Error< "explicit instantiation of non-templated type %0">; def note_nontemplate_decl_here : Note< "non-templated declaration is here">; +def err_explicit_instantiation_in_class : Error< + "explicit instantiation of %0 in class scope">; def err_explicit_instantiation_out_of_scope : Error< "explicit instantiation of %0 not in a namespace enclosing %1">; def err_explicit_instantiation_must_be_global : Error< diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 31823c72eada..7cc431784509 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4549,13 +4549,21 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { } /// \brief Check the scope of an explicit instantiation. -static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, +/// +/// \returns true if a serious error occurs, false otherwise. +static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, SourceLocation InstLoc, bool WasQualifiedName) { DeclContext *ExpectedContext = D->getDeclContext()->getEnclosingNamespaceContext()->getLookupContext(); DeclContext *CurContext = S.CurContext->getLookupContext(); + if (CurContext->isRecord()) { + S.Diag(InstLoc, diag::err_explicit_instantiation_in_class) + << D; + return true; + } + // C++0x [temp.explicit]p2: // An explicit instantiation shall appear in an enclosing namespace of its // template. @@ -4576,7 +4584,7 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, : diag::warn_explicit_instantiation_out_of_scope_0x) << D; S.Diag(D->getLocation(), diag::note_explicit_instantiation_here); - return; + return false; } // C++0x [temp.explicit]p2: @@ -4585,10 +4593,10 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, // its template is declared or, if that namespace is inline (7.3.1), any // namespace from its enclosing namespace set. if (WasQualifiedName) - return; + return false; if (CurContext->Equals(ExpectedContext)) - return; + return false; S.Diag(InstLoc, S.getLangOptions().CPlusPlus0x? @@ -4596,6 +4604,7 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, : diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x) << D << ExpectedContext; S.Diag(D->getLocation(), diag::note_explicit_instantiation_here); + return false; } /// \brief Determine whether the given scope specifier has a template-id in it. @@ -4698,8 +4707,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, // namespace of its template. [...] // // This is C++ DR 275. - CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc, - SS.isSet()); + if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc, + SS.isSet())) + return true; ClassTemplateSpecializationDecl *Specialization = 0; diff --git a/clang/test/SemaTemplate/explicit-instantiation.cpp b/clang/test/SemaTemplate/explicit-instantiation.cpp index de51f0992baa..3a1446e8dd67 100644 --- a/clang/test/SemaTemplate/explicit-instantiation.cpp +++ b/clang/test/SemaTemplate/explicit-instantiation.cpp @@ -83,3 +83,16 @@ namespace explicit_instantiation_after_implicit_instantiation { void test1() { (void)&X0<1>::x; } template struct X0<1>; } + +namespace PR7622 { // expected-note{{to match this}} + template + struct basic_streambuf; + + // FIXME: Very poor recovery here. + template + struct basic_streambuf{friend bob<>()}; // expected-error{{unknown type name 'bob'}} \ + // expected-error{{ expected member name or ';' after declaration specifiers}} + template struct basic_streambuf; // expected-error{{explicit instantiation of 'basic_streambuf' in class scope}} +} // expected-error{{expected ';' after struct}} + +//expected-error{{expected '}'}}