Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print value fixes and removal of the old code #76

Closed
wants to merge 10 commits into from
1 change: 1 addition & 0 deletions core/base/inc/TString.h
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ namespace llvm {
namespace cling {
std::string printValue(const TString &val);
std::string printValue(const TSubString &val);
std::string printValue(const std::string_view &val);
}

#endif
9 changes: 9 additions & 0 deletions core/base/src/TString.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2633,3 +2633,12 @@ std::string cling::printValue(const TSubString &val) {
TString s = TString::Format("\"%.*s\"[%d]", (int)val.Length(), val.Data(), (int)val.Length());
return s.Data();
}

////////////////////////////////////////////////////////////////////////////////
/// Print a TString in the cling interpreter:

std::string cling::printValue(const std::string_view &val) {
std::string str(val);
TString s = TString::Format("\"%s\"[%d]", str.c_str(), (int)val.length());
return s.Data();
}
2 changes: 1 addition & 1 deletion interpreter/cling/Module.mk
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ CLINGETC_CLING := DynamicExprInfo.h DynamicLookupRuntimeUniverse.h \
CLINGETC_LLVM := llvm/ADT/IntrusiveRefCntPtr.h \
llvm/ADT/StringRef.h \
llvm/ADT/SmallVector.h \
llvm/ADT/iterator_range.h \
llvm/ADT/iterator_range.h \
llvm/Config/llvm-config.h \
llvm/Support/AlignOf.h \
llvm/Support/Allocator.h \
Expand Down
128 changes: 66 additions & 62 deletions interpreter/cling/include/cling/Interpreter/RuntimePrintValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
#include <string>
#include "Value.h"

#ifndef _Bool
#define _Bool bool
#endif

namespace cling {

// void pointer
Expand Down Expand Up @@ -66,95 +62,103 @@ namespace cling {
// cling::Value
std::string printValue(const Value &value);

// Maps declaration
template<typename CollectionType>
auto printValue_impl(const CollectionType &obj, short)
namespace internal {
// Maps declaration
template<typename CollectionType>
auto printValue_impl(const CollectionType &obj, short)
-> decltype(
++(obj.begin()), obj.end(),
obj.begin()->first, obj.begin()->second,
std::string());
obj.begin()->first, obj.begin()->second,
std::string());

// Collections like vector, set, deque etc. declaration
template<typename CollectionType>
auto printValue_impl(const CollectionType &obj, int)
// Collections like vector, set, deque etc. declaration
template<typename CollectionType>
auto printValue_impl(const CollectionType &obj, int)
-> decltype(
++(obj.begin()), obj.end(),
*(obj.begin()),
std::string());
*(obj.begin()),
std::string());

// General fallback - print object address declaration
template<typename T>
std::string printValue_impl(const T &obj, long);
// General fallback - print object address declaration
template<typename T>
std::string printValue_impl(const T &obj, long);
}

// Collections and general fallback entry function
template<typename CollectionType>
auto printValue(const CollectionType &obj)
-> decltype(printValue_impl(obj, 0), std::string())
-> decltype(internal::printValue_impl(obj, 0), std::string())
{
return printValue_impl(obj, (short)0); // short -> int -> long = priority order
return internal::printValue_impl(obj, (short)0); // short -> int -> long = priority order
}

// Arrays
template<typename T, size_t N>
std::string printValue(const T (&obj)[N]) {
std::string str = "{ ";

for(int i = 0; i < N; ++i) {
for (int i = 0; i < N; ++i) {
str = str + printValue(obj[i]);
if (i < N-1) str = str + ", ";
}

return str + " }";
}

// Maps
template<typename CollectionType>
auto printValue_impl(const CollectionType &obj, short)
namespace internal {
// Maps
template<typename CollectionType>
auto printValue_impl(const CollectionType &obj, short)
-> decltype(
++(obj.begin()), obj.end(),
obj.begin()->first, obj.begin()->second,
std::string())
{
std::string str = "{ ";

auto iter = obj.begin();
auto iterEnd = obj.end();
while (iter != iterEnd) {
str = str + printValue(iter->first);
str = str + " => ";
str = str + printValue(iter->second);
++iter;
if (iter != iterEnd) str = str + ", ";
++(obj.begin()), obj.end(),
obj.begin()->first, obj.begin()->second,
std::string())
{
std::string str = "{ ";

auto iter = obj.begin();
auto iterEnd = obj.end();
while (iter != iterEnd) {
str = str + printValue(iter->first);
str = str + " => ";
str = str + printValue(iter->second);
++iter;
if (iter != iterEnd) {
str = str + ", ";
}
}

return str + " }";
}

return str + " }";
}

// Collections like vector, set, deque etc.
template<typename CollectionType>
auto printValue_impl(const CollectionType &obj, int)
// Collections like vector, set, deque etc.
template<typename CollectionType>
auto printValue_impl(const CollectionType &obj, int)
-> decltype(
++(obj.begin()), obj.end(),
*(obj.begin()),
std::string())
{
std::string str = "{ ";

auto iter = obj.begin();
auto iterEnd = obj.end();
while (iter != iterEnd) {
str = str + printValue(*iter);
++iter;
if (iter != iterEnd) str = str + ", ";
++(obj.begin()), obj.end(),
*(obj.begin()),
std::string())
{
std::string str = "{ ";

auto iter = obj.begin();
auto iterEnd = obj.end();
while (iter != iterEnd) {
str = str + printValue(*iter);
++iter;
if (iter != iterEnd) {
str = str + ", ";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

str += ", "; - several occurrences.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}

return str + " }";
}

return str + " }";
}

// General fallback - print object address
template<typename T>
std::string printValue_impl(const T &obj, long) {
return "@" + printValue((void *) &obj);
// General fallback - print object address
template<typename T>
std::string printValue_impl(const T &obj, long) {
return "@" + printValue((void *) &obj);
}
}

}
Expand Down
82 changes: 0 additions & 82 deletions interpreter/cling/lib/Interpreter/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,7 @@
#include <iostream>
#include <sstream>

// For address validation
#ifdef LLVM_ON_WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif

namespace {
static bool isAddressValid(void* P) {
if (!P || P == (void*)-1)
return false;

#ifdef LLVM_ON_WIN32
MEMORY_BASIC_INFORMATION MBI;
if (!VirtualQuery(P, &MBI, sizeof(MBI)))
return false;
if (MBI.State != MEM_COMMIT)
return false;
return true;
#else
// There is a POSIX way of finding whether an address can be accessed for
// reading: write() will return EFAULT if not.
int FD[2];
if (pipe(FD))
return false; // error in pipe()? Be conservative...
int NBytes = write(FD[1], P, 1/*byte*/);
close(FD[0]);
close(FD[1]);
if (NBytes != 1) {
assert(errno == EFAULT && "unexpected pipe write error");
return false;
}
return true;
#endif
}

///\brief The allocation starts with this layout; it is followed by the
/// value's object at m_Payload. This class does not inherit from
Expand Down Expand Up @@ -305,54 +271,6 @@ namespace cling {
false /*withAccessControl*/);
}

static bool hasViableCandidateToCall(clang::LookupResult& R,
const cling::Value& V) {
if (R.empty())
return false;
using namespace clang;
ASTContext& C = V.getASTContext();
Sema& SemaR = R.getSema();
OverloadCandidateSet overloads(SourceLocation(),
OverloadCandidateSet::CSK_Normal);
QualType Ty = V.getType().getNonReferenceType();
if (!Ty->isPointerType())
Ty = C.getPointerType(Ty);

NamespaceDecl* ClingNSD = utils::Lookup::Namespace(&SemaR, "cling");
RecordDecl* ClingValueDecl
= dyn_cast<RecordDecl>(utils::Lookup::Named(&SemaR, "Value",
ClingNSD));
assert(ClingValueDecl && "Declaration must be found!");
QualType ClingValueTy = C.getTypeDeclType(ClingValueDecl);

// The OverloadCandidateSet requires a QualType to be passed in through an
// Expr* as part of Args. We know that we won't be using any node generated.
// We need only an answer whether there is an overload taking these argument
// types. We cannot afford to create useless Expr* on the AST for this
// utility function which may be called thousands of times. Instead, we
// create them on the stack and pretend they are on the heap. We get our
// answer and forget about doing anything wrong.
llvm::SmallVector<Expr, 4> exprsOnStack;
SourceLocation noLoc;
exprsOnStack.push_back(CXXNullPtrLiteralExpr(Ty, noLoc));
exprsOnStack.push_back(CXXNullPtrLiteralExpr(Ty, noLoc));
exprsOnStack.push_back(CXXNullPtrLiteralExpr(ClingValueTy, noLoc));
llvm::SmallVector<Expr*, 4> exprsFakedOnHeap;
exprsFakedOnHeap.push_back(&exprsOnStack[0]);
exprsFakedOnHeap.push_back(&exprsOnStack[1]);
exprsFakedOnHeap.push_back(&exprsOnStack[2]);
llvm::ArrayRef<Expr*> Args = llvm::makeArrayRef(exprsFakedOnHeap.data(),
exprsFakedOnHeap.size());
// Could trigger deserialization of decls.
cling::Interpreter::PushTransactionRAII RAII(V.getInterpreter());
SemaR.AddFunctionCandidates(R.asUnresolvedSet(), Args, overloads);

OverloadCandidateSet::iterator Best;
OverloadingResult OR = overloads.BestViableFunction(SemaR,
SourceLocation(), Best);
return OR == OR_Success;
}

namespace valuePrinterInternal {
std::string printType_New(const Value& V);
std::string printValue_New(const Value& V);
Expand Down
Loading