[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