[clang] [PATCH] [clang-repl] Builtin Type printing in ValuePrinter.cpp (PR #88729)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 15 06:43:28 PDT 2024
https://github.com/wlonestar updated https://github.com/llvm/llvm-project/pull/88729
>From c953691de3eda4b72e16d215a6a0e5d230742c59 Mon Sep 17 00:00:00 2001
From: wlonestar <68649094+wlonestar at users.noreply.github.com>
Date: Mon, 15 Apr 2024 13:12:55 +0000
Subject: [PATCH 1/2] [PATCH] [clang-repl] Builtin Type printing in
ValuePrinter.cpp
---
clang/include/clang/Interpreter/Interpreter.h | 2 +
clang/include/clang/Interpreter/Value.h | 8 +-
clang/lib/Interpreter/CMakeLists.txt | 1 +
clang/lib/Interpreter/IncrementalParser.h | 1 +
clang/lib/Interpreter/Interpreter.cpp | 8 +-
clang/lib/Interpreter/InterpreterUtils.cpp | 2 +-
clang/lib/Interpreter/InterpreterUtils.h | 2 +-
clang/lib/Interpreter/Value.cpp | 13 +-
clang/lib/Interpreter/ValuePrinter.cpp | 751 ++++++++++++++++++
9 files changed, 779 insertions(+), 9 deletions(-)
create mode 100644 clang/lib/Interpreter/ValuePrinter.cpp
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 970e0245417b51..3be29bd75cfca7 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -149,6 +149,8 @@ class Interpreter {
CompilerInstance *getCompilerInstance();
llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine();
+ Sema &getSema() const;
+
llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code);
llvm::Error Execute(PartialTranslationUnit &T);
llvm::Error ParseAndExecute(llvm::StringRef Code, Value *V = nullptr);
diff --git a/clang/include/clang/Interpreter/Value.h b/clang/include/clang/Interpreter/Value.h
index d70e8f8719026b..186299a84db444 100644
--- a/clang/include/clang/Interpreter/Value.h
+++ b/clang/include/clang/Interpreter/Value.h
@@ -35,6 +35,7 @@
#include "llvm/Support/Compiler.h"
#include <cstdint>
+#include <string>
// NOTE: Since the REPL itself could also include this runtime, extreme caution
// should be taken when MAKING CHANGES to this file, especially when INCLUDE NEW
@@ -117,6 +118,8 @@ class REPL_EXTERNAL_VISIBILITY Value {
Value &operator=(Value &&RHS) noexcept;
~Value();
+ std::string printValueInternal() const;
+
void printType(llvm::raw_ostream &Out) const;
void printData(llvm::raw_ostream &Out) const;
void print(llvm::raw_ostream &Out) const;
@@ -126,7 +129,7 @@ class REPL_EXTERNAL_VISIBILITY Value {
ASTContext &getASTContext();
const ASTContext &getASTContext() const;
Interpreter &getInterpreter();
- const Interpreter &getInterpreter() const;
+ Interpreter &getInterpreter() const;
QualType getType() const;
bool isValid() const { return ValueKind != K_Unspecified; }
@@ -136,6 +139,8 @@ class REPL_EXTERNAL_VISIBILITY Value {
Kind getKind() const { return ValueKind; }
void setKind(Kind K) { ValueKind = K; }
void setOpaqueType(void *Ty) { OpaqueType = Ty; }
+ void setName(std::string name) { Name = name; }
+ std::string getName() const { return Name; }
void *getPtr() const;
void setPtr(void *Ptr) { Data.m_Ptr = Ptr; }
@@ -197,6 +202,7 @@ class REPL_EXTERNAL_VISIBILITY Value {
Storage Data;
Kind ValueKind = K_Unspecified;
bool IsManuallyAlloc = false;
+ std::string Name;
};
template <> inline void *Value::as() const {
diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt
index 9065f998f73c47..ea00bdc80f595d 100644
--- a/clang/lib/Interpreter/CMakeLists.txt
+++ b/clang/lib/Interpreter/CMakeLists.txt
@@ -20,6 +20,7 @@ add_clang_library(clangInterpreter
Interpreter.cpp
InterpreterUtils.cpp
Value.cpp
+ ValuePrinter.cpp
DEPENDS
intrinsics_gen
diff --git a/clang/lib/Interpreter/IncrementalParser.h b/clang/lib/Interpreter/IncrementalParser.h
index e13b74c7f65948..c9acc59b1ed602 100644
--- a/clang/lib/Interpreter/IncrementalParser.h
+++ b/clang/lib/Interpreter/IncrementalParser.h
@@ -67,6 +67,7 @@ class IncrementalParser {
CompilerInstance *getCI() { return CI.get(); }
CodeGenerator *getCodeGen() const;
+ Parser &getParser() const { return *P; }
/// Parses incremental input by creating an in-memory file.
///\returns a \c PartialTranslationUnit which holds information about the
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index cf31456b6950ac..aa6f6657670bca 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -336,6 +336,8 @@ llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {
return IncrExecutor->GetExecutionEngine();
}
+Sema &Interpreter::getSema() const { return getCompilerInstance()->getSema(); }
+
ASTContext &Interpreter::getASTContext() {
return getCompilerInstance()->getASTContext();
}
@@ -427,7 +429,7 @@ llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
}
llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
-
+ std::string name = Code.str();
auto PTU = Parse(Code);
if (!PTU)
return PTU.takeError();
@@ -437,10 +439,12 @@ llvm::Error Interpreter::ParseAndExecute(llvm::StringRef Code, Value *V) {
if (LastValue.isValid()) {
if (!V) {
+ LastValue.setName(name);
LastValue.dump();
LastValue.clear();
- } else
+ } else {
*V = std::move(LastValue);
+ }
}
return llvm::Error::success();
}
diff --git a/clang/lib/Interpreter/InterpreterUtils.cpp b/clang/lib/Interpreter/InterpreterUtils.cpp
index c19cf6aa3156c9..cba64add8c54a7 100644
--- a/clang/lib/Interpreter/InterpreterUtils.cpp
+++ b/clang/lib/Interpreter/InterpreterUtils.cpp
@@ -102,7 +102,7 @@ NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name,
return nullptr;
}
-std::string GetFullTypeName(ASTContext &Ctx, QualType QT) {
+std::string GetFullTypeName(const ASTContext &Ctx, QualType QT) {
PrintingPolicy Policy(Ctx.getPrintingPolicy());
Policy.SuppressScope = false;
Policy.AnonymousTagLocations = false;
diff --git a/clang/lib/Interpreter/InterpreterUtils.h b/clang/lib/Interpreter/InterpreterUtils.h
index 8df158c17d4919..5699060754fb4d 100644
--- a/clang/lib/Interpreter/InterpreterUtils.h
+++ b/clang/lib/Interpreter/InterpreterUtils.h
@@ -48,7 +48,7 @@ NamespaceDecl *LookupNamespace(Sema &S, llvm::StringRef Name,
NamedDecl *LookupNamed(Sema &S, llvm::StringRef Name,
const DeclContext *Within);
-std::string GetFullTypeName(ASTContext &Ctx, QualType QT);
+std::string GetFullTypeName(const ASTContext &Ctx, QualType QT);
} // namespace clang
#endif
diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp
index eb2ce9c9fd3302..ca11093481be89 100644
--- a/clang/lib/Interpreter/Value.cpp
+++ b/clang/lib/Interpreter/Value.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Interpreter/Value.h"
+#include "InterpreterUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/Interpreter/Interpreter.h"
@@ -222,6 +223,7 @@ void Value::clear() {
OpaqueType = nullptr;
Interp = nullptr;
IsManuallyAlloc = false;
+ Name = "";
}
Value::~Value() { clear(); }
@@ -241,7 +243,7 @@ Interpreter &Value::getInterpreter() {
return *Interp;
}
-const Interpreter &Value::getInterpreter() const {
+Interpreter &Value::getInterpreter() const {
assert(Interp != nullptr &&
"Can't get interpreter from a default constructed value");
return *Interp;
@@ -256,14 +258,17 @@ const ASTContext &Value::getASTContext() const {
void Value::dump() const { print(llvm::outs()); }
void Value::printType(llvm::raw_ostream &Out) const {
- Out << "Not implement yet.\n";
+ Out << "(" << GetFullTypeName(getASTContext(), getType()) << ")\n";
}
+
void Value::printData(llvm::raw_ostream &Out) const {
- Out << "Not implement yet.\n";
+ Out << printValueInternal() << "\n";
}
+
void Value::print(llvm::raw_ostream &Out) const {
assert(OpaqueType != nullptr && "Can't print default Value");
- Out << "Not implement yet.\n";
+ Out << "(" << GetFullTypeName(getASTContext(), getType()) << ")" << ' '
+ << printValueInternal() << "\n";
}
} // namespace clang
diff --git a/clang/lib/Interpreter/ValuePrinter.cpp b/clang/lib/Interpreter/ValuePrinter.cpp
new file mode 100644
index 00000000000000..19b9dcd3d89504
--- /dev/null
+++ b/clang/lib/Interpreter/ValuePrinter.cpp
@@ -0,0 +1,751 @@
+//===--- ValuePrinter.cpp - Value Printer -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements some value printer functions for clang-repl.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Interpreter/Interpreter.h"
+#include "clang/Interpreter/Value.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedAttr.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_os_ostream.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "InterpreterUtils.h"
+
+#include <cassert>
+#include <codecvt>
+#include <cstddef>
+#include <cstdint>
+#include <locale>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+namespace clang {
+
+std::string printAddress(const void *Ptr, const char Prefix = 0) {
+ if (!Ptr) {
+ return "nullptr";
+ }
+ std::ostringstream ostr;
+ if (Prefix) {
+ ostr << Prefix;
+ }
+ ostr << Ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const void *ptr) { return printAddress(ptr, '@'); }
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const void **ptr) { return printAddress(*ptr); }
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const bool *ptr) { return *ptr ? "true" : "false"; }
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const char *ptr) {
+ std::string value = "'";
+ switch (*ptr) {
+ case '\t':
+ value += "\\t";
+ break;
+ case '\n':
+ value += "\\n";
+ break;
+ case '\r':
+ value += "\\r";
+ break;
+ case '\f':
+ value += "\\f";
+ break;
+ case '\v':
+ value += "\\v";
+ break;
+ default:
+ value += *ptr;
+ }
+ value += "'";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const signed char *ptr) {
+ std::string value = "'";
+ switch (*ptr) {
+ case '\t':
+ value += "\\t";
+ break;
+ case '\n':
+ value += "\\n";
+ break;
+ case '\r':
+ value += "\\r";
+ break;
+ case '\f':
+ value += "\\f";
+ break;
+ case '\v':
+ value += "\\v";
+ break;
+ default:
+ value += *ptr;
+ }
+ value += "'";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const unsigned char *ptr) {
+ std::string value = "'";
+ switch (*ptr) {
+ case '\t':
+ value += "\\t";
+ break;
+ case '\n':
+ value += "\\n";
+ break;
+ case '\r':
+ value += "\\r";
+ break;
+ case '\f':
+ value += "\\f";
+ break;
+ case '\v':
+ value += "\\v";
+ break;
+ default:
+ value += *ptr;
+ }
+ value += "'";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const wchar_t *ptr) {
+ std::string value = "'";
+ switch (*ptr) {
+ case '\t':
+ value += "\\t";
+ break;
+ case '\n':
+ value += "\\n";
+ break;
+ case '\r':
+ value += "\\r";
+ break;
+ case '\f':
+ value += "\\f";
+ break;
+ case '\v':
+ value += "\\v";
+ break;
+ default:
+ value += *ptr;
+ }
+ value += "'";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const char16_t *ptr) {
+ std::string value = "'";
+ switch (*ptr) {
+ case '\t':
+ value += "\\t";
+ break;
+ case '\n':
+ value += "\\n";
+ break;
+ case '\r':
+ value += "\\r";
+ break;
+ case '\f':
+ value += "\\f";
+ break;
+ case '\v':
+ value += "\\v";
+ break;
+ default:
+ value += *ptr;
+ }
+ value += "'";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const char32_t *ptr) {
+ std::string value = "'";
+ switch (*ptr) {
+ case '\t':
+ value += "\\t";
+ break;
+ case '\n':
+ value += "\\n";
+ break;
+ case '\r':
+ value += "\\r";
+ break;
+ case '\f':
+ value += "\\f";
+ break;
+ case '\v':
+ value += "\\v";
+ break;
+ default:
+ value += *ptr;
+ }
+ value += "'";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const unsigned short *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const short *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const unsigned int *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const int *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const unsigned long *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const long *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const unsigned long long *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const long long *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const float *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const double *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const long double *ptr) {
+ std::ostringstream ostr;
+ ostr << *ptr;
+ return ostr.str();
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(char *ptr, bool seq) {
+ std::string value = "\"";
+ char *p = ptr;
+ while (*p != '\0') {
+ value += *p;
+ p++;
+ }
+ value += "\"";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(signed char *ptr, bool seq) {
+ std::string value = "\"";
+ signed char *p = ptr;
+ while (*p != '\0') {
+ value += *p;
+ p++;
+ }
+ value += "\"";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(unsigned char *ptr, bool seq) {
+ std::string value = "\"";
+ unsigned char *p = ptr;
+ while (*p != '\0') {
+ value += *p;
+ p++;
+ }
+ value += "\"";
+ return value;
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(wchar_t *ptr, bool seq) {
+ std::wstring value;
+ wchar_t *p = ptr;
+ while (*p != '\0') {
+ value += *p;
+ p++;
+ }
+ std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
+ return "\"" + converter.to_bytes(value) + "\"";
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(char16_t *ptr, bool seq) {
+ std::u16string value;
+ char16_t *p = ptr;
+ while (*p != '\0') {
+ value += *p;
+ p++;
+ }
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
+ return "\"" + converter.to_bytes(value) + "\"";
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(char32_t *ptr, bool seq) {
+ std::u32string value;
+ char32_t *p = ptr;
+ while (*p != '\0') {
+ value += *p;
+ p++;
+ }
+ std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
+ return "\"" + converter.to_bytes(value) + "\"";
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const std::string *ptr) { return "\"" + *ptr + "\""; }
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const std::wstring *ptr) {
+ std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
+ return "\"" + converter.to_bytes(*ptr) + "\"";
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const std::u16string *ptr) {
+ std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
+ return "\"" + converter.to_bytes(*ptr) + "\"";
+}
+
+REPL_EXTERNAL_VISIBILITY
+std::string printValue(const std::u32string *ptr) {
+ std::wstring_convert<std::codecvt_utf8_utf16<char32_t>, char32_t> converter;
+ return "\"" + converter.to_bytes(*ptr) + "\"";
+}
+
+std::string printBuiltinTypeValue(const Value &V, BuiltinType::Kind Kind) {
+ switch (Kind) {
+ case BuiltinType::Bool:
+ return V.convertTo<bool>() ? "true" : "false";
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar: {
+ auto val = V.convertTo<unsigned char>();
+ return printValue(&val);
+ }
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar: {
+ auto val = V.convertTo<signed char>();
+ return printValue(&val);
+ }
+ case BuiltinType::WChar_S: {
+ auto val = V.convertTo<wchar_t>();
+ return printValue(&val);
+ }
+ case BuiltinType::Char16: {
+ auto val = V.convertTo<char16_t>();
+ return printValue(&val);
+ }
+ case BuiltinType::Char32: {
+ auto val = V.convertTo<char32_t>();
+ return printValue(&val);
+ }
+ case BuiltinType::UShort:
+ return std::to_string(V.convertTo<unsigned short>());
+ case BuiltinType::Short:
+ return std::to_string(V.convertTo<short>());
+ case BuiltinType::UInt:
+ return std::to_string(V.convertTo<unsigned int>());
+ case BuiltinType::Int:
+ return std::to_string(V.convertTo<int>());
+ case BuiltinType::ULong:
+ return std::to_string(V.convertTo<unsigned long>());
+ case BuiltinType::Long:
+ return std::to_string(V.convertTo<long>());
+ case BuiltinType::ULongLong:
+ return std::to_string(V.convertTo<unsigned long long>());
+ case BuiltinType::LongLong:
+ return std::to_string(V.convertTo<long long>());
+ case BuiltinType::Float:
+ return std::to_string(V.convertTo<float>());
+ case BuiltinType::Double:
+ return std::to_string(V.convertTo<double>());
+ case BuiltinType::LongDouble:
+ return std::to_string(V.convertTo<long double>());
+ default:
+ break;
+ }
+ return "";
+}
+
+std::string printValueByPtr(void *Ptr, QualType Type, uint64_t Offset) {
+ if (const BuiltinType *bt =
+ llvm::dyn_cast<BuiltinType>(Type.getCanonicalType().getTypePtr())) {
+ std::ostringstream os;
+ Ptr = (void *)((char *)Ptr + Offset);
+ switch (bt->getKind()) {
+ case BuiltinType::Bool:
+ return printValue((bool *)Ptr);
+ case BuiltinType::Char_U:
+ return printValue((unsigned char *)Ptr);
+ case BuiltinType::UChar:
+ return printValue((unsigned char *)Ptr);
+ case BuiltinType::Char_S:
+ return printValue((signed char *)Ptr);
+ case BuiltinType::SChar:
+ return printValue((signed char *)Ptr);
+ case BuiltinType::WChar_S:
+ return printValue((wchar_t *)Ptr);
+ case BuiltinType::Char16:
+ return printValue((char16_t *)Ptr);
+ case BuiltinType::Char32:
+ return printValue((char32_t *)Ptr);
+ case BuiltinType::UShort:
+ return printValue((unsigned short *)Ptr);
+ case BuiltinType::Short:
+ return printValue((short *)Ptr);
+ case BuiltinType::UInt:
+ return printValue((unsigned int *)Ptr);
+ case BuiltinType::Int:
+ return printValue((int *)Ptr);
+ case BuiltinType::ULong:
+ return printValue((unsigned long *)Ptr);
+ case BuiltinType::Long:
+ return printValue((long *)Ptr);
+ case BuiltinType::ULongLong:
+ return printValue((unsigned long long *)Ptr);
+ case BuiltinType::LongLong:
+ return printValue((long long *)Ptr);
+ case BuiltinType::Float:
+ return printValue((float *)Ptr);
+ case BuiltinType::Double:
+ return printValue((double *)Ptr);
+ case BuiltinType::LongDouble:
+ return printValue((long double *)Ptr);
+ default:
+ break;
+ }
+ }
+ if (!Ptr) {
+ return "nullptr";
+ }
+ return printAddress(Ptr, '@');
+}
+
+std::string printEnumValue(const Value &V, QualType Type) {
+ std::ostringstream ostr;
+ const ASTContext &C = V.getASTContext();
+ const EnumType *EnumTy = Type->getAs<EnumType>();
+ assert(EnumTy && "printEnumValue invoked for a non enum type");
+ EnumDecl *decl = EnumTy->getDecl();
+ uint64_t value = V.getULongLong();
+ bool isFirst = true;
+ llvm::APSInt valAsAPSInt = C.MakeIntValue(value, Type);
+ for (EnumDecl::enumerator_iterator I = decl->enumerator_begin(),
+ E = decl->enumerator_end();
+ I != E; ++I) {
+ if (I->getInitVal() == valAsAPSInt) {
+ if (!isFirst) {
+ ostr << " ? ";
+ }
+ ostr << "(" << I->getQualifiedNameAsString() << ")";
+ isFirst = false;
+ }
+ }
+ ostr << " : " << decl->getIntegerType().getAsString() << " "
+ << llvm::toString(valAsAPSInt, 10);
+ return ostr.str();
+}
+
+std::string printArrayValue(const Value &V, QualType Type) {
+ if (const ArrayType *decl = Type->getAsArrayTypeUnsafe()) {
+ if (const ConstantArrayType *cdecl =
+ dyn_cast<const ConstantArrayType>(decl)) {
+ QualType elemType = decl->getElementType();
+ uint64_t size = cdecl->getSize().getZExtValue();
+ std::ostringstream ostr;
+ ostr << "{ ";
+ const ASTContext &C = V.getASTContext();
+ uint64_t elemSize = C.getTypeSize(elemType) / 8;
+ for (uint64_t i = 0; i < size; i++) {
+ ostr << printValueByPtr(V.getPtr(), elemType, i * elemSize);
+ if (i != size - 1) {
+ ostr << ", ";
+ }
+ }
+ ostr << " }";
+ return ostr.str();
+ }
+ }
+
+ if (Type->isPointerType()) {
+ QualType elemType = Type->getPointeeType();
+ if (elemType->isPointerType()) {
+ return "";
+ }
+ const BuiltinType *bt = llvm::dyn_cast<BuiltinType>(elemType.getTypePtr());
+ BuiltinType::Kind Kind = bt->getKind();
+ switch (Kind) {
+ case BuiltinType::Char_U:
+ return printValue((unsigned char *)V.getPtr(), true);
+ case BuiltinType::UChar:
+ return printValue((unsigned char *)V.getPtr(), true);
+ case BuiltinType::Char_S:
+ return printValue((signed char *)V.getPtr(), true);
+ case BuiltinType::SChar:
+ return printValue((signed char *)V.getPtr(), true);
+ case BuiltinType::WChar_S:
+ return printValue((wchar_t *)V.getPtr(), true);
+ case BuiltinType::Char16:
+ return printValue((char16_t *)V.getPtr(), true);
+ case BuiltinType::Char32:
+ return printValue((char32_t *)V.getPtr(), true);
+ default:
+ break;
+ }
+ }
+ return "";
+}
+
+std::string printStringValue(const Value &V, QualType Type) {
+ const ASTContext &C = V.getASTContext();
+ std::string typeStr = GetFullTypeName(C, Type);
+ std::string stringVal = "";
+ if (typeStr == "std::string")
+ stringVal = printValue((std::string *)V.getPtr());
+ if (typeStr == "std::wstring")
+ stringVal = printValue((std::wstring *)V.getPtr());
+ if (typeStr == "std::u16string")
+ stringVal = printValue((std::u16string *)V.getPtr());
+ if (typeStr == "std::u32string")
+ stringVal = printValue((std::u32string *)V.getPtr());
+ return stringVal;
+}
+
+template <typename T> std::string printVectorValue(void *ptr) {
+ std::vector<T> *vecPtr = static_cast<std::vector<T> *>(ptr);
+ std::ostringstream ostr;
+ ostr << "{ ";
+ for (uint64_t i = 0; i < vecPtr->size(); i++) {
+ ostr << (*vecPtr)[i];
+ if (i != vecPtr->size() - 1) {
+ ostr << ", ";
+ }
+ }
+ ostr << " }";
+ return ostr.str();
+}
+
+std::string printRecordValue(const Value &V, const CXXRecordDecl *RecordDecl) {
+ const ASTContext &C = V.getASTContext();
+ Sema &S = V.getInterpreter().getSema();
+ std::string Name = V.getName();
+ NamedDecl *namedDecl = LookupNamed(S, Name, nullptr);
+
+ ValueDecl *valueDecl = llvm::dyn_cast<ValueDecl>(namedDecl);
+ if (valueDecl != nullptr) {
+ QualType Type = valueDecl->getType();
+ std::string str = printStringValue(V, Type);
+ if (!str.empty()) {
+ return str;
+ }
+
+ if (llvm::StringRef(GetFullTypeName(C, Type)).starts_with("std::vector")) {
+ const auto *specDecl =
+ dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
+ if (specDecl) {
+ const TemplateArgumentList &tplArgs = specDecl->getTemplateArgs();
+ assert(tplArgs.size != 0);
+ const TemplateArgument &tplArg = tplArgs[0];
+ if (tplArg.getKind() == TemplateArgument::Type) {
+ if (const BuiltinType *BT =
+ dyn_cast<BuiltinType>(tplArg.getAsType().getTypePtr())) {
+ void *ptr = V.getPtr();
+ switch (BT->getKind()) {
+ case BuiltinType::Bool:
+ return printVectorValue<bool>(ptr);
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ return printVectorValue<unsigned char>(ptr);
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return printVectorValue<signed char>(ptr);
+ case BuiltinType::WChar_S:
+ return printVectorValue<wchar_t>(ptr);
+ case BuiltinType::Char16:
+ return printVectorValue<char16_t>(ptr);
+ case BuiltinType::Char32:
+ return printVectorValue<char32_t>(ptr);
+ case BuiltinType::UShort:
+ return printVectorValue<unsigned short>(ptr);
+ case BuiltinType::Short:
+ return printVectorValue<short>(ptr);
+ case BuiltinType::UInt:
+ return printVectorValue<unsigned int>(ptr);
+ case BuiltinType::Int:
+ return printVectorValue<int>(ptr);
+ case BuiltinType::ULong:
+ return printVectorValue<unsigned long>(ptr);
+ case BuiltinType::Long:
+ return printVectorValue<long>(ptr);
+ case BuiltinType::ULongLong:
+ return printVectorValue<unsigned long long>(ptr);
+ case BuiltinType::LongLong:
+ return printVectorValue<long long>(ptr);
+ case BuiltinType::Float:
+ return printVectorValue<float>(ptr);
+ case BuiltinType::Double:
+ return printVectorValue<double>(ptr);
+ case BuiltinType::LongDouble:
+ return printVectorValue<long double>(ptr);
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return "";
+ }
+ }
+
+ std::ostringstream values;
+ auto fields = RecordDecl->fields();
+ for (auto I = fields.begin(), E = fields.end(), tmp = I; I != E;
+ ++I, tmp = I) {
+ FieldDecl *field = *I;
+ QualType fieldType = field->getType();
+ size_t offset = C.getFieldOffset(field) /* bits */ / 8;
+ values << field->getNameAsString() << ": "
+ << printValueByPtr(V.getPtr(), fieldType, offset);
+ if (++tmp != E) {
+ values << ", ";
+ }
+ }
+ if (!values.str().empty()) {
+ return "{ " + values.str() + " }";
+ }
+ return "";
+}
+
+std::string printUnpackedValue(const Value &V) {
+ const ASTContext &C = V.getASTContext();
+ const QualType Td = V.getType().getDesugaredType(C);
+ const QualType Ty = Td.getNonReferenceType();
+
+ if (!V.getPtr()) {
+ return "nullptr";
+ }
+ if (Ty->isNullPtrType()) {
+ return "nullptr_t";
+ }
+ if (Ty->isEnumeralType()) {
+ return printEnumValue(V, Ty);
+ }
+ if (CXXRecordDecl *RecordDecl = Ty->getAsCXXRecordDecl()) {
+ if (RecordDecl->isLambda()) {
+ return printAddress(V.getPtr(), '@');
+ }
+ std::string str = printRecordValue(V, RecordDecl);
+ if (!str.empty()) {
+ return str;
+ }
+ } else if (const BuiltinType *BT = llvm::dyn_cast<BuiltinType>(
+ Td.getCanonicalType().getTypePtr())) {
+ BuiltinType::Kind Kind = BT->getKind();
+ std::string str = printBuiltinTypeValue(V, Kind);
+ if (!str.empty()) {
+ return str;
+ }
+ } else {
+ std::string str = printArrayValue(V, Ty);
+ if (!str.empty()) {
+ return str;
+ }
+ }
+ return printAddress(V.getPtr(), '@');
+}
+
+std::string Value::printValueInternal() const {
+ return printUnpackedValue(*this);
+}
+
+} // namespace clang
>From 157d1744ece696da80f8562ae537a8e97f27b28b Mon Sep 17 00:00:00 2001
From: wlonestar <68649094+wlonestar at users.noreply.github.com>
Date: Mon, 15 Apr 2024 21:43:21 +0800
Subject: [PATCH 2/2] [clang-repl] fix bugs in method call
---
clang/lib/Interpreter/ValuePrinter.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Interpreter/ValuePrinter.cpp b/clang/lib/Interpreter/ValuePrinter.cpp
index 19b9dcd3d89504..84269eff755893 100644
--- a/clang/lib/Interpreter/ValuePrinter.cpp
+++ b/clang/lib/Interpreter/ValuePrinter.cpp
@@ -633,7 +633,7 @@ std::string printRecordValue(const Value &V, const CXXRecordDecl *RecordDecl) {
dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
if (specDecl) {
const TemplateArgumentList &tplArgs = specDecl->getTemplateArgs();
- assert(tplArgs.size != 0);
+ assert(tplArgs.size() != 0);
const TemplateArgument &tplArg = tplArgs[0];
if (tplArg.getKind() == TemplateArgument::Type) {
if (const BuiltinType *BT =
More information about the cfe-commits
mailing list