reikdas updated this revision to Diff 285565.
reikdas added a comment.

Made some changes to SemaTemplate.cpp based on 
http://clang-developers.42468.n3.nabble.com/Using-clang-tool-to-Exact-type-names-in-template-specification-arguments-td4069210.html


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77598/new/

https://reviews.llvm.org/D77598

Files:
  clang/lib/AST/TemplateBase.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/SemaTemplate/temp_arg_nontype.cpp
  clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp

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<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'?}}
+}
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 <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 {
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<AutoType>())
+      CanonParamType = Context.getAutoType(CanonParamType,
+                                           AutoTypeKeyword::Auto, false, false);
+
     // Convert the APValue to a TemplateArgument.
     switch (Value.getKind()) {
     case APValue::None:
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<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;
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to