Provide a special diagnostic for attempts to explicitly specialize
class templates within class scope (which is ill-formed), and recover by dropping the explicit specialization entirely. Fixes the infinite loop in PR7622. llvm-svn: 108217
This commit is contained in:
parent
11cfd9441d
commit
6cc1df5d3d
|
@ -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<
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<typename,typename=int>
|
||||
struct basic_streambuf;
|
||||
|
||||
// FIXME: Very poor recovery here.
|
||||
template<typename,typename>
|
||||
struct basic_streambuf{friend bob<>()}; // expected-error{{unknown type name 'bob'}} \
|
||||
// expected-error{{ expected member name or ';' after declaration specifiers}}
|
||||
template struct basic_streambuf<int>; // expected-error{{explicit instantiation of 'basic_streambuf' in class scope}}
|
||||
} // expected-error{{expected ';' after struct}}
|
||||
|
||||
//expected-error{{expected '}'}}
|
||||
|
|
Loading…
Reference in New Issue