Skip to content

Commit

Permalink
Fix expression evaluation with operator new
Browse files Browse the repository at this point in the history
Summary:
referencing a user-defined operator new was triggering an assert in clang because we were
registering the function name as string "operator new", instead of using the special operator
enum, which clang has for this purpose. Method operators already had code to handle this, and now
I extend this to cover free standing operator functions as well. Test included.

Reviewers: spyffe

Subscribers: sivachandra, paulherman, lldb-commits

Differential Revision: http://reviews.llvm.org/D17856

llvm-svn: 278670
  • Loading branch information
labath committed Aug 15, 2016
1 parent ad61c17 commit 1ac2b20
Show file tree
Hide file tree
Showing 5 changed files with 342 additions and 249 deletions.
8 changes: 5 additions & 3 deletions lldb/include/lldb/Symbol/ClangASTContext.h
Expand Up @@ -390,10 +390,9 @@ class ClangASTContext : public TypeSystem
static clang::DeclContext *
GetAsDeclContext (clang::ObjCMethodDecl *objc_method_decl);


static bool
CheckOverloadedOperatorKindParameterCount (uint32_t op_kind,
uint32_t num_params);
CheckOverloadedOperatorKindParameterCount(bool is_method, clang::OverloadedOperatorKind op_kind,
uint32_t num_params);

bool
FieldIsBitfield (clang::FieldDecl* field,
Expand Down Expand Up @@ -1188,6 +1187,9 @@ class ClangASTContext : public TypeSystem
return clang::QualType();
}

clang::DeclarationName
GetDeclarationName(const char *name, const CompilerType &function_clang_type);

protected:
//------------------------------------------------------------------
// Classes that inherit from ClangASTContext can see and modify these
Expand Down
Expand Up @@ -10,8 +10,7 @@ class TestCppGlobalOperators(TestBase):

mydir = TestBase.compute_mydir(__file__)

@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_with_run_command(self):
def prepare_executable_and_get_frame(self):
self.build()

# Get main source file
Expand Down Expand Up @@ -42,8 +41,11 @@ def test_with_run_command(self):
self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED)
thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)

# Check if global operators are evaluated
frame = thread.GetSelectedFrame()
return thread.GetSelectedFrame()

@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_equals_operator(self):
frame = self.prepare_executable_and_get_frame()

test_result = frame.EvaluateExpression("operator==(s1, s2)")
self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "operator==(s1, s2) = false")
Expand All @@ -53,3 +55,25 @@ def test_with_run_command(self):

test_result = frame.EvaluateExpression("operator==(s2, s3)")
self.assertTrue(test_result.IsValid() and test_result.GetValue() == "false", "operator==(s2, s3) = false")

def do_new_test(self, frame, expr, expected_value_name):
"""Evaluate a new expression, and check its result"""

expected_value = frame.FindValue(expected_value_name, lldb.eValueTypeVariableGlobal)
self.assertTrue(expected_value.IsValid())

expected_value_addr = expected_value.AddressOf()
self.assertTrue(expected_value_addr.IsValid())

got = frame.EvaluateExpression(expr)
self.assertTrue(got.IsValid())
self.assertEqual(got.GetValueAsUnsigned(), expected_value_addr.GetValueAsUnsigned())
got_type = got.GetType()
self.assertTrue(got_type.IsPointerType())
self.assertEqual(got_type.GetPointeeType().GetName(), "Struct")

def test_operator_new(self):
frame = self.prepare_executable_and_get_frame()

self.do_new_test(frame, "new Struct()", "global_new_buf")
self.do_new_test(frame, "new(new_tag) Struct()", "tagged_new_buf")
@@ -1,3 +1,10 @@
#include <new>

struct new_tag_t
{
};
new_tag_t new_tag;

struct Struct {
int value;
};
Expand All @@ -6,6 +13,25 @@ bool operator==(const Struct &a, const Struct &b) {
return a.value == b.value;
}

typedef char buf_t[sizeof(Struct)];
buf_t global_new_buf, tagged_new_buf;

// This overrides global operator new
// This function and the following does not actually allocate memory. We are merely
// trying to make sure it is getting called.
void *
operator new(std::size_t count)
{
return &global_new_buf;
}

// A custom allocator
void *
operator new(std::size_t count, const new_tag_t &)
{
return &tagged_new_buf;
}

int main() {
Struct s1, s2, s3;
s1.value = 3;
Expand Down
Expand Up @@ -2081,13 +2081,10 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
StreamString ss;

function->DumpSymbolContext(&ss);

log->Printf(" CEDM::FEVD[%u] Imported decl for function %s (description %s), returned %s",
current_id,
copied_function_decl->getName().str().c_str(),
ss.GetData(),
current_id, copied_function_decl->getNameAsString().c_str(), ss.GetData(),
ast_dumper.GetCString());

}

context.AddNamedDecl(copied_function_decl);
Expand Down

0 comments on commit 1ac2b20

Please sign in to comment.