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

Fix failed assertion


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

Index: clang/lib/AST/APValue.cpp
===================================================================
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -625,6 +625,97 @@
   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 = " [...]";
+    Size = std::min(MaxN - Ellipsis.size(), 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'
+      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 +886,23 @@
   }
   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