lichray updated this revision to Diff 391744.
lichray added a comment.

Ensure the ellipses output is never shorter than the normal ones (will look at 
review comments later)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D115031

Files:
  clang/lib/AST/APValue.cpp
  clang/test/SemaTemplate/temp_arg_string_printing.cpp

Index: clang/test/SemaTemplate/temp_arg_string_printing.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaTemplate/temp_arg_string_printing.cpp
@@ -0,0 +1,137 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -ast-print %s | FileCheck %s
+
+using size_t = __SIZE_TYPE__;
+static_assert(__has_builtin(__make_integer_seq));
+
+template <class T, T... I> class idx_seq {};
+template <size_t N> using make_idx_seq = __make_integer_seq<idx_seq, size_t, N>;
+
+template <class CharT, size_t N>
+struct Str {
+  constexpr Str(CharT const (&s)[N]) : Str(s, make_idx_seq<N>()) {}
+  CharT value[N];
+
+private:
+  template <size_t... I>
+  constexpr Str(CharT const (&s)[N], idx_seq<size_t, I...>) : value{s[I]...} {}
+};
+
+template <Str> class ASCII {};
+
+void narrow() {
+  // CHECK{LITERAL}: ASCII<{""}>
+  new ASCII<"">;
+  // CHECK{LITERAL}: ASCII<{"the quick brown fox jumps"}>
+  new ASCII<"the quick brown fox jumps">;
+  // CHECK{LITERAL}: ASCII<{"OVER THE LAZY DOG 0123456789"}>
+  new ASCII<"OVER THE LAZY DOG 0123456789">;
+  // CHECK{LITERAL}: ASCII<{"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
+  new ASCII<R"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
+  // CHECK{LITERAL}: ASCII<{"escape\0"}>
+  new ASCII<"escape\0">;
+  // CHECK{LITERAL}: ASCII<{"escape\r\n"}>
+  new ASCII<"escape\r\n">;
+  // CHECK{LITERAL}: ASCII<{"escape\\\t\'\f\v"}>
+  new ASCII<"escape\\\t'\f\v">;
+  // CHECK{LITERAL}: ASCII<{"escape\a\bc"}>
+  new ASCII<"escape\a\b\c">;
+  // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}>
+  new ASCII<"not\x11">;
+  // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 0}}>
+  new ASCII<"\x12\x14\x7f\x10\x01 abc">;
+  // CHECK{LITERAL}: ASCII<{{18, 20, 127, 16, 1, 32, 97, 98, 99, 100, ...}}>
+  new ASCII<"\x12\x14\x7f\x10\x01 abcd">;
+  // CHECK{LITERAL}: ASCII<{"print more characters as string"}>
+  new ASCII<"print more characters as string">;
+  // CHECK{LITERAL}: ASCII<{"print even more characters as string"}>
+  new ASCII<"print even more characters as string">;
+  // CHECK{LITERAL}: ASCII<{"print many characters no more than[...]"}>
+  new ASCII<"print many characters no more than a limit">;
+  // CHECK{LITERAL}: ASCII<{"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}>
+  new ASCII<"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0">;
+  // CHECK{LITERAL}: ASCII<{"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}>
+  new ASCII<"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">;
+}
+
+void wide() {
+  // CHECK{LITERAL}: ASCII<{L""}>
+  new ASCII<L"">;
+  // CHECK{LITERAL}: ASCII<{L"the quick brown fox jumps"}>
+  new ASCII<L"the quick brown fox jumps">;
+  // CHECK{LITERAL}: ASCII<{L"OVER THE LAZY DOG 0123456789"}>
+  new ASCII<L"OVER THE LAZY DOG 0123456789">;
+  // CHECK{LITERAL}: ASCII<{L"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
+  new ASCII<LR"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
+  // CHECK{LITERAL}: ASCII<{L"escape\0"}>
+  new ASCII<L"escape\0">;
+  // CHECK{LITERAL}: ASCII<{L"escape\r\n"}>
+  new ASCII<L"escape\r\n">;
+  // CHECK{LITERAL}: ASCII<{L"escape\\\t\f\v"}>
+  new ASCII<L"escape\\\t\f\v">;
+  // CHECK{LITERAL}: ASCII<{L"escape\a\bc"}>
+  new ASCII<L"escape\a\b\c">;
+  // CHECK{LITERAL}: ASCII<{{110, 111, 116, 17, 0}}>
+  new ASCII<L"not\x11">;
+  // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 0}}>
+  new ASCII<L"\x12\x14\xff\x597d\x88 abc">;
+  // CHECK{LITERAL}: ASCII<{{18, 20, 255, 22909, 136, 32, 97, 98, 99, 100, ...}}>
+  new ASCII<L"\x12\x14\xff\x597d\x88 abcd">;
+  // CHECK{LITERAL}: ASCII<{L"print more characters as string"}>
+  new ASCII<L"print more characters as string">;
+  // CHECK{LITERAL}: ASCII<{L"print even more characters as string"}>
+  new ASCII<L"print even more characters as string">;
+  // CHECK{LITERAL}: ASCII<{L"print many characters no more than[...]"}>
+  new ASCII<L"print many characters no more than a limit">;
+  // CHECK{LITERAL}: ASCII<{L"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}>
+  new ASCII<L"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0">;
+  // CHECK{LITERAL}: ASCII<{L"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[...]"}>
+  new ASCII<L"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n">;
+}
+
+void utf8()
+{
+  // CHECK{LITERAL}: ASCII<{u8""}>
+  new ASCII<u8"">;
+  // CHECK{LITERAL}: ASCII<{u8"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
+  new ASCII<u8R"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
+  // CHECK{LITERAL}: ASCII<{u8"escape\0"}>
+  new ASCII<u8"escape\0">;
+  // CHECK{LITERAL}: ASCII<{u8"escape\r\n"}>
+  new ASCII<u8"escape\r\n">;
+  // CHECK{LITERAL}: ASCII<{{229, 165, 189, 239, 191, 189, 0}}>
+  new ASCII<u8"\u597d\ufffd">;
+  // CHECK{LITERAL}: ASCII<{u8"print many characters no more than[...]"}>
+  new ASCII<u8"print many characters no more than a limit">;
+}
+
+void utf16()
+{
+  // CHECK{LITERAL}: ASCII<{u""}>
+  new ASCII<u"">;
+  // CHECK{LITERAL}: ASCII<{u"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
+  new ASCII<uR"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
+  // CHECK{LITERAL}: ASCII<{u"escape\0"}>
+  new ASCII<u"escape\0">;
+  // CHECK{LITERAL}: ASCII<{u"escape\r\n"}>
+  new ASCII<u"escape\r\n">;
+  // CHECK{LITERAL}: ASCII<{{22909, 65533, 0}}>
+  new ASCII<u"\u597d\ufffd">;
+  // CHECK{LITERAL}: ASCII<{u"print many characters no more than[...]"}>
+  new ASCII<u"print many characters no more than a limit">;
+}
+
+void utf32()
+{
+  // CHECK{LITERAL}: ASCII<{U""}>
+  new ASCII<U"">;
+  // CHECK{LITERAL}: ASCII<{U"\\`~!@#$%^&*()_+-={}[]|\'\";:,.<>?/"}>
+  new ASCII<UR"(\`~!@#$%^&*()_+-={}[]|'";:,.<>?/)">;
+  // CHECK{LITERAL}: ASCII<{U"escape\0"}>
+  new ASCII<U"escape\0">;
+  // CHECK{LITERAL}: ASCII<{U"escape\r\n"}>
+  new ASCII<U"escape\r\n">;
+  // CHECK{LITERAL}: ASCII<{{22909, 131358, 0}}>
+  new ASCII<U"\u597d\U0002011E">;
+  // CHECK{LITERAL}: ASCII<{U"print many characters no more than[...]"}>
+  new ASCII<U"print many characters no more than a limit">;
+}
Index: clang/lib/AST/APValue.cpp
===================================================================
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -625,6 +625,99 @@
   return V.convertToDouble();
 }
 
+static bool TryPrintAsStringLiteral(raw_ostream &Out, const ArrayType *ATy,
+                                    const APValue *Data, size_t Size) {
+  if (Size == 0)
+    return false;
+
+  QualType Ty = ATy->getElementType();
+  if (!Ty->isAnyCharacterType())
+    return false;
+
+  // Nothing we can do about a sequence that is not null-terminated
+  if (!Data[--Size].getInt().isZero())
+    return false;
+
+  constexpr size_t MaxN = 36;
+  char Buf[MaxN * 2 + 3] = {'"'}; // "At most 36 escaped chars" + \0
+  auto *pBuf = Buf + 1;
+
+  // Better than printing a two-digit sequence of 10 integers.
+  StringRef Ellipsis;
+  if (Size > MaxN) {
+    Ellipsis = "[...]";
+    auto Room = Ellipsis.size() / 2; // May step on the last \0
+    Size = std::min(MaxN - Room, Size);
+  }
+
+  auto writeEscape = [](char *Ptr, char Ch) {
+    Ptr[0] = '\\';
+    Ptr[1] = Ch;
+    return Ptr + 2;
+  };
+
+  for (auto &Val : ArrayRef<const APValue>(Data, Size)) {
+    auto Char64 = Val.getInt().getExtValue();
+    if (Char64 > 0x7f)
+      return false; // Bye bye, see you in integers.
+    switch (auto Ch = static_cast<unsigned char>(Char64)) {
+    default:
+      if (isPrintable(Ch)) {
+        *pBuf++ = Ch;
+        break;
+      }
+      return false;
+    case '\\':
+    case '\'': // The diagnostic message is 'quoted'
+    case '"':
+      pBuf = writeEscape(pBuf, Ch);
+      break;
+    case '\0':
+      pBuf = writeEscape(pBuf, '0');
+      break;
+    case '\a':
+      pBuf = writeEscape(pBuf, 'a');
+      break;
+    case '\b':
+      pBuf = writeEscape(pBuf, 'b');
+      break;
+    case '\f':
+      pBuf = writeEscape(pBuf, 'f');
+      break;
+    case '\n':
+      pBuf = writeEscape(pBuf, 'n');
+      break;
+    case '\r':
+      pBuf = writeEscape(pBuf, 'r');
+      break;
+    case '\t':
+      pBuf = writeEscape(pBuf, 't');
+      break;
+    case '\v':
+      pBuf = writeEscape(pBuf, 'v');
+      break;
+    }
+  }
+
+  if (!Ellipsis.empty()) {
+    memcpy(pBuf, Ellipsis.data(), Ellipsis.size());
+    pBuf += Ellipsis.size();
+  }
+  *pBuf++ = '"';
+
+  if (Ty->isWideCharType())
+    Out << 'L';
+  else if (Ty->isChar8Type())
+    Out << "u8";
+  else if (Ty->isChar16Type())
+    Out << 'u';
+  else if (Ty->isChar32Type())
+    Out << 'U';
+
+  Out << StringRef(Buf, pBuf - Buf);
+  return true;
+}
+
 void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx,
                           QualType Ty) const {
   printPretty(Out, Ctx.getPrintingPolicy(), Ty, &Ctx);
@@ -795,17 +888,24 @@
   }
   case APValue::Array: {
     const ArrayType *AT = Ty->castAsArrayTypeUnsafe();
+    unsigned N = getArrayInitializedElts();
+    if (N != 0 &&
+        TryPrintAsStringLiteral(Out, AT, &getArrayInitializedElt(0), N))
+      return;
     QualType ElemTy = AT->getElementType();
     Out << '{';
-    if (unsigned N = getArrayInitializedElts()) {
-      getArrayInitializedElt(0).printPretty(Out, Policy, ElemTy, Ctx);
-      for (unsigned I = 1; I != N; ++I) {
+    unsigned I = 0;
+    switch (N) {
+    case 0:
+      for (; I != N; ++I) {
         Out << ", ";
         if (I == 10) {
           // Avoid printing out the entire contents of large arrays.
-          Out << "...";
-          break;
+          Out << "...}";
+          return;
         }
+        LLVM_FALLTHROUGH;
+      default:
         getArrayInitializedElt(I).printPretty(Out, Policy, ElemTy, Ctx);
       }
     }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to