Index: clang/lib/AST/TemplateBase.cpp =================================================================== --- clang/lib/AST/TemplateBase.cpp +++ clang/lib/AST/TemplateBase.cpp @@ -70,13 +70,51 @@ if (T->isBooleanType() && !Policy.MSVCFormatting) { Out << (Val.getBoolValue() ? "true" : "false"); + } else if (T->isBooleanType()) { + Out << Val; } else if (T->isCharType()) { const char Ch = Val.getZExtValue(); Out << ((Ch == '\'') ? "'\\" : "'"); Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); Out << "'"; } else { - Out << Val; + bool flag = false; + if (auto *autoT = T->getAs()) { + if (autoT->getAs()) { + flag = true; + } + } else if (T->getAs()) { + flag = true; + } + if (flag) { + if (auto *BT = T->getAs()) { + switch (BT->getKind()) { + case BuiltinType::ULongLong: + Out << Val << "ULL"; + break; + case BuiltinType::LongLong: + Out << Val << "LL"; + break; + case BuiltinType::ULong: + Out << Val << "UL"; + break; + case BuiltinType::Long: + Out << Val << "L"; + break; + case BuiltinType::UInt: + Out << Val << "U"; + break; + case BuiltinType::Int: + Out << Val; + break; + default: + Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")" + << Val; + break; + } + } + } else + Out << Val; } } Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -6822,6 +6822,14 @@ QualType CanonParamType = Context.getCanonicalType(ParamType); + // Note: this renders CanonParamType non-canonical, but since every + // instantiation of this argument will be wrapped in an AutoType (since + // Param->getType() will always be an AutoType for this template), there + // should be no difference in how arguments are distinguished. + if (Param->getType()->getAs()) + CanonParamType = Context.getAutoType(CanonParamType, + AutoTypeKeyword::Auto, false, false); + // Convert the APValue to a TemplateArgument. switch (Value.getKind()) { case APValue::None: Index: clang/test/SemaTemplate/temp_arg_nontype.cpp =================================================================== --- clang/test/SemaTemplate/temp_arg_nontype.cpp +++ clang/test/SemaTemplate/temp_arg_nontype.cpp @@ -270,6 +270,23 @@ void test_char_possibly_negative() { enable_if_char<'\x02'>::type i; } // expected-error{{enable_if_char<'\x02'>'; did you mean 'enable_if_char<'a'>::type'?}} void test_char_single_quote() { enable_if_char<'\''>::type i; } // expected-error{{enable_if_char<'\''>'; did you mean 'enable_if_char<'a'>::type'?}} void test_char_backslash() { enable_if_char<'\\'>::type i; } // expected-error{{enable_if_char<'\\'>'; did you mean 'enable_if_char<'a'>::type'?}} + + template struct enable_if_int {}; + template <> struct enable_if_int<1> { typedef int type; }; // expected-note{{'enable_if_int<1>::type' declared here}} + void test_int() { enable_if_int<2>::type i; } // expected-error{{enable_if_int<2>'; did you mean 'enable_if_int<1>::type'?}} + + template struct enable_if_unsigned_int {}; + template <> struct enable_if_unsigned_int<1> { typedef int type; }; // expected-note{{'enable_if_unsigned_int<1>::type' declared here}} + void test_unsigned_int() { enable_if_unsigned_int<2>::type i; } // expected-error{{enable_if_unsigned_int<2>'; did you mean 'enable_if_unsigned_int<1>::type'?}} + + template struct enable_if_unsigned_long_long {}; + template <> struct enable_if_unsigned_long_long<1> { typedef int type; }; // expected-note{{'enable_if_unsigned_long_long<1>::type' declared here}} + void test_unsigned_long_long() { enable_if_unsigned_long_long<2>::type i; } // expected-error{{enable_if_unsigned_long_long<2>'; did you mean 'enable_if_unsigned_long_long<1>::type'?}} + + template struct enable_if_long_long {}; + template <> struct enable_if_long_long<1> { typedef int type; }; // expected-note{{'enable_if_long_long<1>::type' declared here}} + void test_long_long() { enable_if_long_long<2>::type i; } // expected-error{{enable_if_long_long<2>'; did you mean 'enable_if_long_long<1>::type'?}} + } namespace PR10579 { Index: clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp =================================================================== --- clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -459,3 +459,13 @@ X y; int n = y.call(); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}} } + +namespace PR9227 { + template struct S {}; + template <> struct S<1> { using type = int; }; // expected-note {{'S<1>::type' declared here}} + S<1L>::type t; // expected-error {{no type named 'type' in 'PR9227::S<1L>'; did you mean 'S<1>::type'?}} + + template struct A {}; + template <> struct A<1> { using type = int; }; // expected-note {{'A<1>::type' declared here}} + A<2>::type x; // expected-error {{no type named 'type' in 'PR9227::A<2>'; did you mean 'A<1>::type'?}} +}