Simplify; adapt to new Value.

This commit is contained in:
Axel Naumann 2014-03-09 13:53:19 +01:00 committed by sftnight
parent 93970e8c35
commit d00d9e8d54
10 changed files with 96 additions and 78 deletions

View File

@ -20,7 +20,7 @@ CLINGDEP := $(CLINGO:.o=.d)
CLINGETC_CLING := DynamicExprInfo.h DynamicLookupRuntimeUniverse.h \
DynamicLookupLifetimeHandler.h Interpreter.h InvocationOptions.h \
RuntimeUniverse.h StoredValueRef.h Value.h \
RuntimeUniverse.h Value.h \
ValuePrinter.h ValuePrinterInfo.h RuntimeException.h
CLINGETC_LLVM := llvm/ADT/IntrusiveRefCntPtr.h \

View File

@ -16,7 +16,7 @@
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/DynamicExprInfo.h"
#include "cling/Interpreter/DynamicLookupLifetimeHandler.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"
namespace cling {
@ -45,7 +45,7 @@ namespace runtime {
/// evaluated at runtime.
template<typename T>
T EvaluateT(DynamicExprInfo* ExprInfo, clang::DeclContext* DC ) {
StoredValueRef result(
Value result(
cling::runtime::gCling->Evaluate(ExprInfo->getExpr(), DC,
ExprInfo->isValuePrinterRequested())
);
@ -53,7 +53,7 @@ namespace runtime {
// Check whether the expected return type and the actual return type are
// compatible with Sema::CheckAssingmentConstraints or
// ASTContext::typesAreCompatible.
return result.get().getAs<T>();
return result.simplisticCastAs<T>();
return T();
}

View File

@ -56,69 +56,69 @@ namespace cling {
///\brief Set the value of the GenericValue for the expression
/// evaluated at the prompt.
///\param [in] vpI - The cling::Interpreter for StoredValueRef.
///\param [in] vpI - The cling::Interpreter for Value.
///\param [in] vpQT - The opaque ptr for the clang::QualType of value.
///\param [in] value - The float value of the assignment to be stored
/// in GenericValue.
///\param [out] vpSVR - The StoredValueRef that is created.
///\param [out] vpSVR - The Value that is created.
///
void setValueNoAlloc(void* vpI, void* vpSVR, void* vpQT, float value);
void setValueNoAlloc(void* vpI, void* vpV, void* vpQT, float value);
///\brief Set the value of the GenericValue for the expression
/// evaluated at the prompt.
///\param [in] vpI - The cling::Interpreter for StoredValueRef.
///\param [in] vpI - The cling::Interpreter for Value.
///\param [in] vpQT - The opaque ptr for the clang::QualType of value.
///\param [in] value - The double value of the assignment to be stored
/// in GenericValue.
///\param [out] vpSVR - The StoredValueRef that is created.
///\param [out] vpSVR - The Value that is created.
///
void setValueNoAlloc(void* vpI, void* vpSVR, void* vpQT, double value);
void setValueNoAlloc(void* vpI, void* vpV, void* vpQT, double value);
///\brief Set the value of the GenericValue for the expression
/// evaluated at the prompt. Extract through
/// APFloat(ASTContext::getFloatTypeSemantics(QT), const APInt &)
///\param [in] vpI - The cling::Interpreter for StoredValueRef.
///\param [in] vpI - The cling::Interpreter for Value.
///\param [in] vpQT - The opaque ptr for the clang::QualType of value.
///\param [in] value - The value of the assignment to be stored
/// in GenericValue.
///\param [out] vpSVR - The StoredValueRef that is created.
///\param [out] vpSVR - The Value that is created.
///
void setValueNoAlloc(void* vpI, void* vpSVR, void* vpQT,
void setValueNoAlloc(void* vpI, void* vpV, void* vpQT,
long double value);
///\brief Set the value of the GenericValue for the expression
/// evaluated at the prompt.
/// We are using unsigned long long instead of uint64, because we don't
/// want to #include the header.
///\param [in] vpI - The cling::Interpreter for StoredValueRef.
///\param [in] vpI - The cling::Interpreter for Value.
///\param [in] vpQT - The opaque ptr for the clang::QualType of value.
///\param [in] value - The uint64_t value of the assignment to be stored
/// in GenericValue.
///\param [out] vpSVR - The StoredValueRef that is created.
///\param [out] vpSVR - The Value that is created.
///
void setValueNoAlloc(void* vpI, void* vpSVR, void* vpQT,
void setValueNoAlloc(void* vpI, void* vpV, void* vpQT,
unsigned long long value);
///\brief Set the value of the GenericValue for the expression
/// evaluated at the prompt.
///\param [in] vpI - The cling::Interpreter for StoredValueRef.
///\param [in] vpI - The cling::Interpreter for Value.
///\param [in] vpQT - The opaque ptr for the clang::QualType of value.
///\param [in] value - The void* value of the assignment to be stored
/// in GenericValue.
///\param [out] vpSVR - The StoredValueRef that is created.
///\param [out] vpV - The Value that is created.
///
void setValueNoAlloc(void* vpI, void* vpSVR, void* vpQT,
void setValueNoAlloc(void* vpI, void* vpV, void* vpQT,
const void* value);
///\brief Set the value of the Generic value and return the address
/// for the allocated storage space.
///\param [in] vpI - The cling::Interpreter for StoredValueRef.
///\param [in] vpI - The cling::Interpreter for Value.
///\param [in] vpQT - The opaque ptr for the clang::QualType of value.
///\param [out] vpSVR - The StoredValueRef that is created.
///\param [out] vpV - The Value that is created.
///
///\returns the address where the value should be put.
///
void* setValueWithAlloc(void* vpI, void* vpSVR, void* vpQT);
void* setValueWithAlloc(void* vpI, void* vpV, void* vpQT);
///\brief Placement new doesn't work for arrays. It needs to be called on
/// each element. For non-PODs we also need to call the *structors. This

View File

@ -61,10 +61,6 @@ namespace cling {
/// \brief Retrieve the underlying, canonical, desugared, unqualified type.
EStorageType getStorageType() const;
/// \brief Whether this type needs managed heap, i.e. the storage provided
/// by Storage is insufficient.
bool needsManagedAllocation() const;
/// \brief Allocate storage as needed by the type.
void ManagedAllocate(Interpreter* interp);
@ -79,7 +75,7 @@ namespace cling {
public:
/// \brief Default constructor, creates a value that IsInvalid().
Value() {}
Value(): m_Type(0) {}
/// \brief Copy a value.
Value(const Value& other);
/// \brief Construct a valid but ininitialized Value. After this call the
@ -93,6 +89,11 @@ namespace cling {
clang::QualType getType() const;
/// \brief Whether this type needs managed heap, i.e. the storage provided
/// by the m_Storage member is insufficient, or a non-trivial destructor
/// must be called.
bool needsManagedAllocation() const;
/// \brief Determine whether the Value has been set.
//
/// Determine whether the Value has been set by checking
@ -100,14 +101,14 @@ namespace cling {
bool isValid() const;
/// \brief Determine whether the Value is set but void.
bool isVoid(const clang::ASTContext& ASTContext) const;
bool isVoid(const clang::ASTContext& Ctx) const;
/// \brief Determine whether the Value is set and not void.
//
/// Determine whether the Value is set and not void.
/// Only in this case can getAs() or simplisticCastAs() be called.
bool hasValue(const clang::ASTContext& ASTContext) const {
return isValid() && !isVoid(ASTContext); }
bool hasValue(const clang::ASTContext& Ctx) const {
return isValid() && !isVoid(Ctx); }
/// \brief Get a reference to the value without type checking.
/// T *must* correspond to type. Else use simplisticCastAs()!
@ -120,7 +121,7 @@ namespace cling {
T getAs() const { return const_cast<Value*>(this)->getAs<T>(); }
template <typename T>
T* getAs(T**) const { return (T*)getAs((void**)0); }
T*& getAs(T**) const { return (T*&)getAs((void**)0); }
void*& getAs(void**) { return m_Storage.m_Ptr; }
double& getAs(double*) { return m_Storage.m_Double; }
long double& getAs(long double*) { return m_Storage.m_LongDouble; }
@ -128,7 +129,21 @@ namespace cling {
long long& getAs(long long*) { return m_Storage.m_LL; }
unsigned long long& getAs(unsigned long long*) { return m_Storage.m_ULL; }
/// \brief Get the value.
void*& getPtr() { return m_Storage.m_Ptr; }
double& getDouble() { return m_Storage.m_Double; }
long double& getLongDouble() { return m_Storage.m_LongDouble; }
float& getFloat() { return m_Storage.m_Float; }
long long& getLL() { return m_Storage.m_LL; }
unsigned long long& getULL() { return m_Storage.m_ULL; }
void* getPtr() const { return m_Storage.m_Ptr; }
double getDouble() const { return m_Storage.m_Double; }
long double getLongDouble() const { return m_Storage.m_LongDouble; }
float getFloat() const { return m_Storage.m_Float; }
long long getLL() const { return m_Storage.m_LL; }
unsigned long long getULL() const { return m_Storage.m_ULL; }
/// \brief Get the value with cast.
//
/// Get the value cast to T. This is similar to reinterpret_cast<T>(value),
/// casting the value of builtins (except void), enums and pointers.

View File

@ -37,7 +37,6 @@ add_cling_library(clingInterpreter
RequiredSymbols.cpp
ValueExtractionSynthesizer.cpp
RuntimeException.cpp
StoredValueRef.cpp
Transaction.cpp
TransactionTransformer.cpp
TransactionUnloader.cpp

View File

@ -957,10 +957,6 @@ namespace cling {
m_Executor->installLazyFunctionCreator(fp);
}
void Interpreter::suppressLazyFunctionCreatorDiags(bool suppressed/*=true*/) {
m_Executor->suppressLazyFunctionCreatorDiags(suppressed);
}
Value Interpreter::Evaluate(const char* expr, DeclContext* DC,
bool ValuePrinterReq) {
Sema& TheSema = getCI()->getSema();

View File

@ -74,7 +74,8 @@ namespace {
namespace cling {
Value::Value(const Value& other) : m_Type(other.m_Type) {
Value::Value(const Value& other):
m_Type(other.m_Type), m_Storage(other.m_Storage) {
if (needsManagedAllocation())
AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Retain();
}
@ -86,7 +87,13 @@ Value::Value(clang::QualType clangTy, Interpreter* Interp):
}
Value& Value::operator =(const Value& other) {
// Release old value.
if (needsManagedAllocation())
AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Release();
// Retain new one.
m_Type = other.m_Type;
m_Storage = other.m_Storage;
if (needsManagedAllocation())
AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Retain();
return *this;
@ -103,8 +110,8 @@ clang::QualType Value::getType() const {
bool Value::isValid() const { return !getType().isNull(); }
bool Value::isVoid(const clang::ASTContext& ASTContext) const {
return isValid() && ASTContext.hasSameType(getType(), ASTContext.VoidTy);
bool Value::isVoid(const clang::ASTContext& Ctx) const {
return isValid() && Ctx.hasSameType(getType(), Ctx.VoidTy);
}
Value::EStorageType Value::getStorageType() const {
@ -130,14 +137,16 @@ Value::EStorageType Value::getStorageType() const {
}
bool Value::needsManagedAllocation() const {
return !getType()->getUnqualifiedDesugaredType()->isBuiltinType();
if (!isValid()) return false;
const clang::Type* UnqDes = getType()->getUnqualifiedDesugaredType();
return UnqDes->isRecordType() || UnqDes->isArrayType()
|| UnqDes->isMemberPointerType();
}
void Value::ManagedAllocate(Interpreter* interp) {
assert(interp && "This type requires the interpreter for value allocation");
void* dtorFunc = 0;
if (const clang::RecordType* RTy
= clang::dyn_cast<clang::RecordType>(getType()))
if (const clang::RecordType* RTy = getType()->getAs<clang::RecordType>())
dtorFunc = GetDtorWrapperPtr(RTy->getDecl(), *interp);
const clang::ASTContext& ctx = interp->getCI()->getASTContext();

View File

@ -73,7 +73,7 @@ public:
/// call to cling::runtime::internal::copyArray(...)
///
/// We need to synthesize later:
/// Wrapper has signature: void w(cling::StoredValueRef SVR)
/// Wrapper has signature: void w(cling::Value V)
/// case 1):
/// setValueNoAlloc(gCling, &SVR, lastExprTy, lastExpr())
/// case 2):

View File

@ -9,44 +9,44 @@
// RUN: cat %s | %cling -Xclang -verify | FileCheck %s
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"
cling::StoredValueRef V;
V // CHECK: (cling::StoredValueRef) <<<invalid>>> @0x{{.*}}
cling::Value V;
V // CHECK: (cling::Value) <<<invalid>>> @0x{{.*}}
gCling->evaluate("return 1;", V);
V // CHECK: (cling::StoredValueRef) boxes [(int) 1]
V // CHECK: (cling::Value) boxes [(int) 1]
// Returns must put the result in the StoredValueRef.
// Returns must put the result in the Value.
bool cond = true;
gCling->evaluate("if (cond) return \"true\"; else return 0;", V);
V // CHECK: (cling::StoredValueRef) boxes [(const char [5]) "true"]
V // CHECK: (cling::Value) boxes [(const char [5]) "true"]
gCling->evaluate("cond = false; if (cond) return \"true\"; else return 0;", V);
V // CHECK: (cling::StoredValueRef) boxes [(int) 0]
V // CHECK: (cling::Value) boxes [(int) 0]
gCling->evaluate("auto a = 12.3; a;", V);
V // CHECK: (cling::StoredValueRef) boxes [(double) 1.230000e+01]
V // CHECK: (cling::Value) boxes [(double) 1.230000e+01]
long LongV = 17;
gCling->evaluate("LongV;", V);
V // CHECK: (cling::StoredValueRef) boxes [(long) 17]
V // CHECK: (cling::Value) boxes [(long) 17]
int* IntP = (int*)0x12;
gCling->evaluate("IntP;", V);
V // CHECK: (cling::StoredValueRef) boxes [(int *) 0x12]
V // CHECK: (cling::Value) boxes [(int *) 0x12]
cling::StoredValueRef Result;
cling::Value Result;
gCling->evaluate("V", Result);
// Here we check what happens for record type like cling::StoredValueRef; they are returned by reference.
Result // CHECK: (cling::StoredValueRef) boxes [(cling::StoredValueRef &) boxes [(int *) 0x12]]
V // CHECK: (cling::StoredValueRef) boxes [(int *) 0x12]
// Here we check what happens for record type like cling::Value; they are returned by reference.
Result // CHECK: (cling::Value) boxes [(cling::Value &) boxes [(int *) 0x12]]
V // CHECK: (cling::Value) boxes [(int *) 0x12]
// Savannah #96277
gCling->evaluate("gCling->declare(\"double sin(double);\"); double one = sin(3.141/2);", V);
V // CHECK: (cling::StoredValueRef) boxes [(double) 1.000000e+00]
V // CHECK: (cling::Value) boxes [(double) 1.000000e+00]
gCling->process("double one = sin(3.141/2);", &V);
V // CHECK: (cling::StoredValueRef) boxes [(double) 1.000000e+00]
V // CHECK: (cling::Value) boxes [(double) 1.000000e+00]
one // CHECK: (double) 1.000
int one; // expected-error {{redefinition of 'one' with a different type: 'int' vs 'double'}} expected-note {{previous definition is here}}
@ -59,7 +59,7 @@ gCling->evaluate("f", V);
V.isValid() //CHECK: {{\([_]B|b}}ool) true
// end PR#98434
// Check lifetime of objects in StoredValue
// Check lifetime of objects in Value
.rawInput 1
struct WithDtor {
static int fgCount;
@ -73,25 +73,24 @@ WithDtor getWithDtor() { return WithDtor(); }
std::vector<WithDtor> getWithDtorVec() { std::vector<WithDtor> ret; ret.resize(7); return ret; }
.rawInput 0
cling::StoredValueRef* VOnHeap = new cling::StoredValueRef();
cling::Value* VOnHeap = new cling::Value();
gCling->evaluate("getWithDtor()", *VOnHeap);
*VOnHeap //CHECK: (cling::StoredValueRef) boxes [(WithDtor) @0x{{.*}}]
*VOnHeap //CHECK: (cling::Value) boxes [(WithDtor) @0x{{.*}}]
WithDtor::fgCount //CHECK: (int) 1
delete VOnHeap;
WithDtor::fgCount //CHECK: (int) 0
// Check destructor call for templates
VOnHeap = new cling::StoredValueRef();
VOnHeap = new cling::Value();
gCling->evaluate("getWithDtorVec()", *VOnHeap);
*VOnHeap //CHECK: (cling::StoredValueRef) boxes [(std::vector<WithDtor>) @0x{{.*}}]
*VOnHeap //CHECK: (cling::Value) boxes [(std::vector<WithDtor>) @0x{{.*}}]
WithDtor::fgCount //CHECK: (int) 7
delete VOnHeap;
WithDtor::fgCount //CHECK: (int) 0
// long doubles (tricky for the JIT).
gCling->evaluate("17.42L", V);
V // CHECK: (cling::StoredValueRef) boxes [(long double) 17.4200000{{[0-9]*}}L]
V // CHECK: (cling::Value) boxes [(long double) 17.42{{[0-9]*}}L]
// Test references, temporaries
.rawInput 1
@ -121,19 +120,19 @@ namespace cling {
return p->asStr();
}
}
void dumpTracerSVR(cling::StoredValueRef& svr) {
((Tracer*)svr.get().getAs<void*>())->dump("dump");
void dumpTracerSVR(cling::Value& svr) {
((Tracer*)svr.getAs<void*>())->dump("dump");
}
.rawInput 0
// Creating the static in constructs one object. It gets returned by
// reference; it should only be destructed by ~JIT, definitely not by
// ~StoredValueRef (which should only store a Tracer&)
// ~Value (which should only store a Tracer&)
gCling->evaluate("RefMaker()", V);
// This is the local static:
// CHECK: REF{1}:ctor
printf("RefMaker() done\n"); // CHECK-NEXT: RefMaker() done
V // CHECK-NEXT: (cling::StoredValueRef) boxes [(Tracer &) @{{.*}}]
V // CHECK-NEXT: (cling::Value) boxes [(Tracer &) @{{.*}}]
dumpTracerSVR(V); // CHECK-NEXT: REF{1}:dump
// Setting a new value should destruct the old - BUT it's a ref thus no
@ -146,7 +145,7 @@ gCling->evaluate("ObjMaker()", V);
// The temporary gets created:
// CHECK-NEXT:MADE{2}:ctor
printf("ObjMaker() done\n"); //CHECK-NEXT: ObjMaker() done
V // CHECK-NEXT: (cling::StoredValueRef) boxes [(Tracer) @{{.*}}]
V // CHECK-NEXT: (cling::Value) boxes [(Tracer) @{{.*}}]
dumpTracerSVR(V); // CHECK-NEXT: MADE{2}:dump
// Creating a variable:
@ -160,17 +159,17 @@ Tracer RT("VAR"); // CHECK-NEXT: VAR{3}:ctor
// CHECK-NEXT: MADE{2}:dtor
gCling->evaluate("RT", V); // should not call any ctor!
printf("RT done\n"); //CHECK-NEXT: RT done
V // CHECK-NEXT: (cling::StoredValueRef) boxes [(Tracer &) @{{.*}}]
V // CHECK-NEXT: (cling::Value) boxes [(Tracer &) @{{.*}}]
dumpTracerSVR(V); // CHECK-NEXT: VAR{2}:dump
// The following creates a copy, explicitly. This temporary object is then put
// into the StoredValueRef.
// into the Value.
//
gCling->evaluate("(Tracer)RT", V);
// Copies RT:
//CHECK-NEXT: VAR+{3}:copy
printf("(Tracer)RT done\n"); //CHECK-NEXT: RT done
V // CHECK-NEXT: (cling::StoredValueRef) boxes [(Tracer) @{{.*}}]
V // CHECK-NEXT: (cling::Value) boxes [(Tracer) @{{.*}}]
dumpTracerSVR(V); // CHECK-NEXT: VAR+{3}:dump
// Destruct the variables with static storage:

View File

@ -13,10 +13,10 @@
// PR #96277
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"
#include <stdio.h>
gCling->declare("int print() { printf(\"print is run.\\n\"); return 1; }");
cling::StoredValueRef V;
cling::Value V;
gCling->process("int a = print();",&V);
//CHECK: print is run.
gCling->process("a", &V);
@ -28,7 +28,7 @@ gCling->process("a;", &V);
gCling->process("\"Root\"", &V);
// CHECK: (const char [5]) "Root"
V
// CHECK: (cling::StoredValueRef) boxes [(const char *) "Root"]
// CHECK: (cling::Value) boxes [(const char *) "Root"]
// End PR #98146
typedef enum {k1,k2} enumName;
enumName var