Removed unused function hasViableCandidateToCall (overload resolution and general fallback deals with this now). Moved isAddressValid function from Value.cpp to ValuePrinter.cpp and implemented the check for void*.

This commit is contained in:
Boris Perovic 2015-08-17 13:04:00 +02:00 committed by sftnight
parent 517eab8df1
commit a9825d50dc
2 changed files with 41 additions and 82 deletions

View File

@ -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
@ -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);

View File

@ -46,6 +46,13 @@
//#endif
#endif
// For address validation
#ifdef LLVM_ON_WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
using namespace cling;
// Implements the CValuePrinter interface.
@ -61,6 +68,36 @@ extern "C" void cling_PrintValue(void* /*cling::Value**/ V) {
//std::string valueStr = printValue(value->getPtr(), value->getPtr(), *value);
}
// Checking whether the pointer points to a valid memory location
// Used for checking of void* output
// Should be moved to earlier stages (ex. IR) in the future
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
}
static void StreamValue(llvm::raw_ostream& o, const void* V, clang::QualType QT,
cling::Interpreter& interp);
@ -583,6 +620,10 @@ namespace cling {
strm << "<<<NULL>>>";
} else {
strm << ptr;
if (isAddressValid(ptr))
strm << " VALID";
else
strm << " INVALID";
}
return strm.str();
}