diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp --- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp +++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/PriorityQueue.h" +#include "llvm/Support/ConvertUTF.h" #include #include @@ -463,8 +464,29 @@ } if (auto *D = dyn_cast(S)) return getRelativeName(D->getDecl(), getEnclosingDeclContext(AST, S)); - if (auto *String = dyn_cast(S)) + if (auto *String = dyn_cast(S)) { + if (String->isWide() || String->isUTF16() || String->isUTF32()) { + std::string UTF8Str; + unsigned int NumChars = String->getLength(); + const char *Bytes = String->getBytes().data(); + if (String->isWide()) { + const auto *Chars = reinterpret_cast(Bytes); + if (!convertWideToUTF8({Chars, NumChars}, UTF8Str)) + return ""; + } else if (String->isUTF16()) { + const auto *Chars = reinterpret_cast(Bytes); + if (!convertUTF16ToUTF8String({Chars, NumChars}, UTF8Str)) + return ""; + } else { + assert(String->isUTF32() && "Unsupported string encoding."); + const auto *Chars = reinterpret_cast(Bytes); + if (!convertUTF32ToUTF8String({Chars, NumChars}, UTF8Str)) + return ""; + } + return UTF8Str; + } return std::string(String->getString()); + } if (auto *B = dyn_cast(S)) return B->getValue() ? "true" : "false"; return ""; diff --git a/clang/test/Tooling/clang-diff-ast.cpp b/clang/test/Tooling/clang-diff-ast.cpp --- a/clang/test/Tooling/clang-diff-ast.cpp +++ b/clang/test/Tooling/clang-diff-ast.cpp @@ -47,6 +47,12 @@ if (i == 0) // CHECK: StringLiteral: foo( return "foo"; + // CHECK: StringLiteral: wide( + (void)L"wide"; + // CHECK: StringLiteral: utf-16( + (void)u"utf-16"; + // CHECK: StringLiteral: utf-32( + (void)U"utf-32"; // CHECK-NOT: ImplicitCastExpr return 0; }