diff options
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 49 | ||||
-rw-r--r-- | test/Misc/integer-literal-printing.cpp | 68 |
2 files changed, 91 insertions, 26 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 1fa554abd0..21be2442e4 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4606,7 +4606,18 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, 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 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, 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); } diff --git a/test/Misc/integer-literal-printing.cpp b/test/Misc/integer-literal-printing.cpp index 4085d606d2..8b0b1fc7f2 100644 --- a/test/Misc/integer-literal-printing.cpp +++ b/test/Misc/integer-literal-printing.cpp @@ -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 <short T> void Function1(Type1<T>& x) {} // expected-note{{candidate fu 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')}} } |