[cfe-commits] r153426 - in /cfe/trunk: lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/enum-scoped.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Sun Mar 25 21:08:46 PDT 2012
Author: rsmith
Date: Sun Mar 25 23:08:46 2012
New Revision: 153426
URL: http://llvm.org/viewvc/llvm-project?rev=153426&view=rev
Log:
Delay checking of dependent underlying types for redeclarations of member
enumerations in templates until the template is instantiated.
Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaCXX/enum-scoped.cpp
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=153426&r1=153425&r2=153426&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Mar 25 23:08:46 2012
@@ -7780,7 +7780,9 @@
}
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();
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=153426&r1=153425&r2=153426&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Mar 25 23:08:46 2012
@@ -588,9 +588,20 @@
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 @@
// 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;
}
Modified: cfe/trunk/test/SemaCXX/enum-scoped.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enum-scoped.cpp?rev=153426&r1=153425&r2=153426&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/enum-scoped.cpp (original)
+++ cfe/trunk/test/SemaCXX/enum-scoped.cpp Sun Mar 25 23:08:46 2012
@@ -195,8 +195,29 @@
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}}
}
More information about the cfe-commits
mailing list