Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
- index 6a3d2b30e46..7addedcf1a2 100644
- --- a/clang/lib/AST/TemplateBase.cpp
- +++ b/clang/lib/AST/TemplateBase.cpp
- @@ -70,13 +70,51 @@ static void printIntegral(const TemplateArgument &TemplArg,
- 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<AutoType>()) {
- + if (autoT->getAs<DeducedType>()) {
- + flag = true;
- + }
- + } else if (T->getAs<DeducedType>()) {
- + flag = true;
- + }
- + if (flag) {
- + if (auto *BT = T->getAs<BuiltinType>()) {
- + 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;
- }
- }
- diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
- index d63d307b9ab..13784148b0f 100644
- --- a/clang/lib/Sema/SemaTemplate.cpp
- +++ b/clang/lib/Sema/SemaTemplate.cpp
- @@ -6822,6 +6822,14 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
- 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<AutoType>())
- + CanonParamType = Context.getAutoType(CanonParamType,
- + AutoTypeKeyword::Auto, false, false);
- +
- // Convert the APValue to a TemplateArgument.
- switch (Value.getKind()) {
- case APValue::None:
- diff --git a/clang/test/SemaTemplate/temp_arg_nontype.cpp b/clang/test/SemaTemplate/temp_arg_nontype.cpp
- index dd086dbb25b..d36178769f9 100644
- --- a/clang/test/SemaTemplate/temp_arg_nontype.cpp
- +++ b/clang/test/SemaTemplate/temp_arg_nontype.cpp
- @@ -270,6 +270,23 @@ namespace PR9227 {
- 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 <int N> 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 <unsigned int N> 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 <unsigned long long N> 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 <long long N> 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 {
- diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
- index 7538de33090..28fb89691fa 100644
- --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
- +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
- @@ -459,3 +459,13 @@ namespace PR46637 {
- X<f> y;
- int n = y.call(); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}}
- }
- +
- +namespace PR9227 {
- + template <auto N> 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 <auto N> 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'?}}
- +}
Advertisement
Add Comment
Please, Sign In to add comment