forked from OSchip/llvm-project
Delay checking of dependent underlying types for redeclarations of member
enumerations in templates until the template is instantiated. llvm-svn: 153426
This commit is contained in:
parent
eb75cc26af
commit
258a744bbd
|
@ -7780,7 +7780,9 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
|
|||
}
|
||||
|
||||
if (IsFixed && Prev->isFixed()) {
|
||||
if (!Context.hasSameUnqualifiedType(EnumUnderlyingTy,
|
||||
if (!EnumUnderlyingTy->isDependentType() &&
|
||||
!Prev->getIntegerType()->isDependentType() &&
|
||||
!Context.hasSameUnqualifiedType(EnumUnderlyingTy,
|
||||
Prev->getIntegerType())) {
|
||||
Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch)
|
||||
<< EnumUnderlyingTy << Prev->getIntegerType();
|
||||
|
|
|
@ -588,9 +588,20 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
|
|||
if (SubstQualifier(D, Enum)) return 0;
|
||||
Owner->addDecl(Enum);
|
||||
|
||||
// FIXME: If this is a redeclaration:
|
||||
// CheckEnumRedeclaration(Enum->getLocation(), Enum->isScoped(),
|
||||
// Enum->getIntegerType(), Prev);
|
||||
EnumDecl *Def = D->getDefinition();
|
||||
if (Def && Def != D) {
|
||||
// If this is an out-of-line definition of an enum member template, check
|
||||
// that the underlying types match in the instantiation of both
|
||||
// declarations.
|
||||
if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) {
|
||||
SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
|
||||
QualType DefnUnderlying =
|
||||
SemaRef.SubstType(TI->getType(), TemplateArgs,
|
||||
UnderlyingLoc, DeclarationName());
|
||||
SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(),
|
||||
DefnUnderlying, Enum);
|
||||
}
|
||||
}
|
||||
|
||||
if (D->getDeclContext()->isFunctionOrMethod())
|
||||
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum);
|
||||
|
@ -600,8 +611,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
|
|||
// not the definitions of scoped member enumerations.
|
||||
// FIXME: There appears to be no wording for what happens for an enum defined
|
||||
// within a block scope, but we treat that like a member of a class template.
|
||||
if (!Enum->isScoped() && D->getDefinition())
|
||||
InstantiateEnumDefinition(Enum, D);
|
||||
if (!Enum->isScoped() && Def)
|
||||
InstantiateEnumDefinition(Enum, Def);
|
||||
|
||||
return Enum;
|
||||
}
|
||||
|
|
|
@ -195,8 +195,29 @@ namespace test8 {
|
|||
enum A : int; // expected-note {{here}}
|
||||
enum class B; // expected-note {{here}}
|
||||
enum class C : int; // expected-note {{here}}
|
||||
enum class D : int; // expected-note {{here}}
|
||||
};
|
||||
template<typename T> enum S<T>::A { a }; // expected-error {{previously declared with fixed underlying type}}
|
||||
template<typename T> enum class S<T>::B : char { b }; // expected-error {{redeclared with different underlying}}
|
||||
template<typename T> enum S<T>::C : int { c }; // expected-error {{previously declared as scoped}}
|
||||
template<typename T> enum class S<T>::D : char { d }; // expected-error {{redeclared with different underlying}}
|
||||
}
|
||||
|
||||
namespace test9 {
|
||||
template<typename T> struct S {
|
||||
enum class ET : T; // expected-note 2{{here}}
|
||||
enum class Eint : int; // expected-note 2{{here}}
|
||||
};
|
||||
template<> enum class S<int>::ET : int {};
|
||||
template<> enum class S<char>::ET : short {}; // expected-error {{different underlying type}}
|
||||
template<> enum class S<int>::Eint : short {}; // expected-error {{different underlying type}}
|
||||
template<> enum class S<char>::Eint : int {};
|
||||
|
||||
template<typename T> enum class S<T>::ET : int {}; // expected-error {{different underlying type 'int' (was 'short')}}
|
||||
template<typename T> enum class S<T>::Eint : T {}; // expected-error {{different underlying type 'short' (was 'int')}}
|
||||
|
||||
// The implicit instantiation of S<short> causes the implicit instantiation of
|
||||
// all declarations of member enumerations, so is ill-formed, even though we
|
||||
// never instantiate the definitions of S<short>::ET nor S<short>::Eint.
|
||||
S<short> s; // expected-note {{in instantiation of}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue