[cfe-commits] r168441 - in /cfe/trunk: lib/Sema/SemaTemplate.cpp test/Misc/integer-literal-printing.cpp

Benjamin Kramer benny.kra at googlemail.com
Wed Nov 21 09:42:47 PST 2012


Author: d0k
Date: Wed Nov 21 11:42:47 2012
New Revision: 168441

URL: http://llvm.org/viewvc/llvm-project?rev=168441&view=rev
Log:
SemaCXX: an enumeral type can be of character or boolean type in a C++11 enum class. Make sure we create a literal of the right type.

Fixes PR14386.

Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/Misc/integer-literal-printing.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=168441&r1=168440&r2=168441&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Nov 21 11:42:47 2012
@@ -4606,7 +4606,18 @@
                                                   SourceLocation Loc) {
   assert(Arg.getKind() == TemplateArgument::Integral &&
          "Operation is only valid for integral template arguments");
-  QualType T = Arg.getIntegralType();
+  QualType OrigT = Arg.getIntegralType();
+
+  // If this is an enum type that we're instantiating, we need to use an integer
+  // type the same size as the enumerator.  We don't want to build an
+  // IntegerLiteral with enum type.  The integer type of an enum type can be of
+  // any integral type with C++11 enum classes, make sure we create the right
+  // type of literal for it.
+  QualType T = OrigT;
+  if (const EnumType *ET = OrigT->getAs<EnumType>())
+    T = ET->getDecl()->getIntegerType();
+
+  Expr *E;
   if (T->isAnyCharacterType()) {
     CharacterLiteral::CharacterKind Kind;
     if (T->isWideCharType())
@@ -4618,34 +4629,22 @@
     else
       Kind = CharacterLiteral::Ascii;
 
-    return Owned(new (Context) CharacterLiteral(
-                                            Arg.getAsIntegral().getZExtValue(),
-                                            Kind, T, Loc));
+    E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(),
+                                       Kind, T, Loc);
+  } else if (T->isBooleanType()) {
+    E = new (Context) CXXBoolLiteralExpr(Arg.getAsIntegral().getBoolValue(),
+                                         T, Loc);
+  } else if (T->isNullPtrType()) {
+    E = new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc);
+  } else {
+    E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), T, Loc);
   }
 
-  if (T->isBooleanType())
-    return Owned(new (Context) CXXBoolLiteralExpr(
-                                            Arg.getAsIntegral().getBoolValue(),
-                                            T, Loc));
-
-  if (T->isNullPtrType())
-    return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
-  
-  // If this is an enum type that we're instantiating, we need to use an integer
-  // type the same size as the enumerator.  We don't want to build an
-  // IntegerLiteral with enum type.
-  QualType BT;
-  if (const EnumType *ET = T->getAs<EnumType>())
-    BT = ET->getDecl()->getIntegerType();
-  else
-    BT = T;
-
-  Expr *E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), BT, Loc);
-  if (T->isEnumeralType()) {
+  if (OrigT->isEnumeralType()) {
     // FIXME: This is a hack. We need a better way to handle substituted
     // non-type template parameters.
-    E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0, 
-                               Context.getTrivialTypeSourceInfo(T, Loc),
+    E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E, 0,
+                               Context.getTrivialTypeSourceInfo(OrigT, Loc),
                                Loc, Loc);
   }
   

Modified: cfe/trunk/test/Misc/integer-literal-printing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/integer-literal-printing.cpp?rev=168441&r1=168440&r2=168441&view=diff
==============================================================================
--- cfe/trunk/test/Misc/integer-literal-printing.cpp (original)
+++ cfe/trunk/test/Misc/integer-literal-printing.cpp Wed Nov 21 11:42:47 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11
 
 // PR11179
 template <short T> class Type1 {};
@@ -7,7 +7,73 @@
 template <unsigned short T> class Type2 {};
 template <unsigned short T> void Function2(Type2<T>& x) {} // expected-note{{candidate function [with T = 42] not viable: expects an l-value for 1st argument}}
 
+enum class boolTy : bool {
+  b = 0,
+};
+
+template <boolTy T> struct Type3Helper;
+template <> struct Type3Helper<boolTy::b> { typedef boolTy Ty; };
+template <boolTy T, typename Type3Helper<T>::Ty U> struct Type3 {};
+
+// PR14386
+enum class charTy : char {
+  c = 0,
+};
+
+template <charTy T> struct Type4Helper;
+template <> struct Type4Helper<charTy::c> { typedef charTy Ty; };
+template <charTy T, typename Type4Helper<T>::Ty U> struct Type4 {};
+
+enum class scharTy : signed char {
+  c = 0,
+};
+
+template <scharTy T> struct Type5Helper;
+template <> struct Type5Helper<scharTy::c> { typedef scharTy Ty; };
+template <scharTy T, typename Type5Helper<T>::Ty U> struct Type5 {};
+
+enum class ucharTy : unsigned char {
+  c = 0,
+};
+
+template <ucharTy T> struct Type6Helper;
+template <> struct Type6Helper<ucharTy::c> { typedef ucharTy Ty; };
+template <ucharTy T, typename Type6Helper<T>::Ty U> struct Type6 {};
+
+enum class wcharTy : wchar_t {
+  c = 0,
+};
+
+template <wcharTy T> struct Type7Helper;
+template <> struct Type7Helper<wcharTy::c> { typedef wcharTy Ty; };
+template <wcharTy T, typename Type7Helper<T>::Ty U> struct Type7 {};
+
+enum class char16Ty : char16_t {
+  c = 0,
+};
+
+template <char16Ty T> struct Type8Helper;
+template <> struct Type8Helper<char16Ty::c> { typedef char16Ty Ty; };
+template <char16Ty T, typename Type8Helper<T>::Ty U> struct Type8 {};
+
+enum class char32Ty : char16_t {
+  c = 0,
+};
+
+template <char32Ty T> struct Type9Helper;
+template <> struct Type9Helper<char32Ty::c> { typedef char32Ty Ty; };
+template <char32Ty T, typename Type9Helper<T>::Ty U> struct Type9 {};
+
 void Function() {
   Function1(Type1<-42>()); // expected-error{{no matching function for call to 'Function1'}}
   Function2(Type2<42>()); // expected-error{{no matching function for call to 'Function2'}}
+
+  struct Type3<boolTy::b, "3"> t3; // expected-error{{value of type 'const char [2]' is not implicitly convertible to 'typename Type3Helper<(boolTy)false>::Ty' (aka 'boolTy')}}
+
+  struct Type4<charTy::c, "4"> t4; // expected-error{{value of type 'const char [2]' is not implicitly convertible to 'typename Type4Helper<(charTy)'\x0'>::Ty' (aka 'charTy')}}
+  struct Type5<scharTy::c, "5"> t5; // expected-error{{value of type 'const char [2]' is not implicitly convertible to 'typename Type5Helper<(scharTy)'\x0'>::Ty' (aka 'scharTy')}}
+  struct Type6<ucharTy::c, "6"> t6; // expected-error{{value of type 'const char [2]' is not implicitly convertible to 'typename Type6Helper<(ucharTy)'\x0'>::Ty' (aka 'ucharTy')}}
+  struct Type7<wcharTy::c, "7"> t7; // expected-error{{value of type 'const char [2]' is not implicitly convertible to 'typename Type7Helper<(wcharTy)L'\x0'>::Ty' (aka 'wcharTy')}}
+  struct Type8<char16Ty::c, "8"> t8; // expected-error{{value of type 'const char [2]' is not implicitly convertible to 'typename Type8Helper<(char16Ty)u'\x0'>::Ty' (aka 'char16Ty')}}
+  struct Type9<char32Ty::c, "9"> t9; // expected-error{{value of type 'const char [2]' is not implicitly convertible to 'typename Type9Helper<(char32Ty)u'\x0'>::Ty' (aka 'char32Ty')}}
 }





More information about the cfe-commits mailing list