summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavide Italiano <davide@freebsd.org>2018-03-20 19:46:32 +0000
committerDavide Italiano <davide@freebsd.org>2018-03-20 19:46:32 +0000
commitc78a4fe9b00a8ea6366523a7338a074c8ea92103 (patch)
tree9304c6b88b244fcbf8bd98dff97cb5614db6a5cb
parent17e38ad863d0cd1baff9149848d92a5f304ee21b (diff)
[ExpressionParser] Re-implement r327356 in a less disruptive way.
Instead of applying the sledgehammer of refusing to insert any C++ symbol in the ASTContext, try to validate the decl if what we have is an operator. There was other code in lldb which was responsible for this, just not really exposed (or used) in this codepath. Also, add a better/more comprehensive test. <rdar://problem/35645893> git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@328025 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/lldb/Symbol/ClangASTContext.h3
-rw-r--r--lit/Expr/Inputs/basic.cpp12
-rw-r--r--lit/Expr/TestCallCppSym.test6
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/operator-overload/Makefile20
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/operator-overload/TestOperatorOverload.py22
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/operator-overload/a.cpp9
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/operator-overload/b.cpp10
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp12
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp9
-rw-r--r--source/Symbol/ClangASTContext.cpp4
10 files changed, 78 insertions, 29 deletions
diff --git a/include/lldb/Symbol/ClangASTContext.h b/include/lldb/Symbol/ClangASTContext.h
index 2d2c804eb..e02e05dd5 100644
--- a/include/lldb/Symbol/ClangASTContext.h
+++ b/include/lldb/Symbol/ClangASTContext.h
@@ -253,6 +253,9 @@ public:
&type_fields,
bool packed = false);
+ static bool IsOperator(const char *name,
+ clang::OverloadedOperatorKind &op_kind);
+
//------------------------------------------------------------------
// Structure, Unions, Classes
//------------------------------------------------------------------
diff --git a/lit/Expr/Inputs/basic.cpp b/lit/Expr/Inputs/basic.cpp
deleted file mode 100644
index 80a79379a..000000000
--- a/lit/Expr/Inputs/basic.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-class Patatino {
-private:
- long tinky;
-
-public:
- Patatino(long tinky) { this->tinky = tinky; }
-};
-
-int main(void) {
- Patatino *a = new Patatino(26);
- return 0;
-}
diff --git a/lit/Expr/TestCallCppSym.test b/lit/Expr/TestCallCppSym.test
deleted file mode 100644
index ac48c6f51..000000000
--- a/lit/Expr/TestCallCppSym.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# RUN: %cxx %p/Inputs/basic.cpp -g -o %t && %lldb -b -s %s -- %t 2>&1 | FileCheck %s
-
-breakpoint set --file basic.cpp --line 12
-run
-call (int)_Znwm(23)
-# CHECK: error: use of undeclared identifier '_Znwm'
diff --git a/packages/Python/lldbsuite/test/lang/cpp/operator-overload/Makefile b/packages/Python/lldbsuite/test/lang/cpp/operator-overload/Makefile
new file mode 100644
index 000000000..7d85a3a81
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/cpp/operator-overload/Makefile
@@ -0,0 +1,20 @@
+LEVEL = ../../../make
+
+CXX_SOURCES = a.cpp b.cpp
+CXXFLAGS_NO_DEBUGINFO = -c
+CXXFLAGS_DEBUGINFO = -c -g
+
+all: main
+
+main: a.o b.o
+ $(CXX) a.o b.o -o main $(LDFLAGS)
+
+a.o: a.cpp
+ $(CXX) $(SRCDIR)/a.cpp $(CXXFLAGS_NO_DEBUGINFO) -o a.o
+
+b.o: b.cpp
+ $(CXX) $(SRCDIR)/b.cpp $(CXXFLAGS_DEBUGINFO) -o b.o
+
+clean: OBJECTS += a.o b.o main
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/lang/cpp/operator-overload/TestOperatorOverload.py b/packages/Python/lldbsuite/test/lang/cpp/operator-overload/TestOperatorOverload.py
new file mode 100644
index 000000000..0191e08d2
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/cpp/operator-overload/TestOperatorOverload.py
@@ -0,0 +1,22 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestOperatorOverload(TestBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test_overload(self):
+ self.build()
+ (target, process, thread,
+ main_breakpoint) = lldbutil.run_to_source_breakpoint(self,
+ "break here", lldb.SBFileSpec("b.cpp"), exe_name = "main")
+ frame = thread.GetSelectedFrame()
+ value = frame.EvaluateExpression("x == nil")
+ self.assertTrue(str(value.GetError())
+ .find("comparison between NULL and non-pointer ('Tinky' and NULL)")
+ != -1)
+ self.assertTrue(str(value.GetError())
+ .find("invalid operands to binary expression ('Tinky' and 'long')")
+ != -1)
+ self.assertFalse(value.GetError().Success())
diff --git a/packages/Python/lldbsuite/test/lang/cpp/operator-overload/a.cpp b/packages/Python/lldbsuite/test/lang/cpp/operator-overload/a.cpp
new file mode 100644
index 000000000..77b2f6ace
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/cpp/operator-overload/a.cpp
@@ -0,0 +1,9 @@
+class Patatino {
+public:
+ double _blah;
+ Patatino(int blah) : _blah(blah) {}
+};
+
+bool operator==(const Patatino& a, const Patatino& b) {
+ return a._blah < b._blah;
+}
diff --git a/packages/Python/lldbsuite/test/lang/cpp/operator-overload/b.cpp b/packages/Python/lldbsuite/test/lang/cpp/operator-overload/b.cpp
new file mode 100644
index 000000000..c0eb29bb7
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/cpp/operator-overload/b.cpp
@@ -0,0 +1,10 @@
+class Tinky {
+public:
+ int _meh;
+ Tinky(int meh) : _meh(meh) {}
+};
+
+int main(void) {
+ Tinky x(12);
+ return 0; // break here
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 7f031356b..b929a052d 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -2156,6 +2156,18 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
log->Printf("Function type wasn't a FunctionProtoType");
}
+ // If this is an operator (e.g. operator new or operator==), only insert
+ // the declaration we inferred from the symbol if we can provide the correct
+ // number of arguments. We shouldn't really inject random decl(s) for
+ // functions that are analyzed semantically in a special way, otherwise we
+ // will crash in clang.
+ clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
+ if (func_proto_type &&
+ ClangASTContext::IsOperator(decl_name.getAsString().c_str(), op_kind)) {
+ if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount(
+ false, op_kind, func_proto_type->getNumParams()))
+ return NULL;
+ }
m_decls.push_back(func_decl);
return func_decl;
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 093be6c89..07ff2e97a 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -2072,15 +2072,6 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
return;
}
} else if (symbol) {
- // Don't insert a generic function decl for C++ symbol names.
- // Creating a generic function decl is almost surely going to cause troubles
- // as it breaks Clang/Sema invariants and causes crashes in clang while
- // we're trying to evaluate the expression.
- // This means users can't call C++ functions by mangled name when there
- // are no debug info (as it happens for C symbol, e.g. printf()).
- if (CPlusPlusLanguage::IsCPPMangledName(
- symbol->GetMangled().GetMangledName().GetCString()))
- return;
fun_address = symbol->GetAddress();
function_decl = context.AddGenericFunDecl();
is_indirect_function = symbol->IsIndirect();
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index 8cb5a0694..df2d25c8d 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -138,8 +138,8 @@ static ClangASTMap &GetASTMap() {
return *g_map_ptr;
}
-static bool IsOperator(const char *name,
- clang::OverloadedOperatorKind &op_kind) {
+bool ClangASTContext::IsOperator(const char *name,
+ clang::OverloadedOperatorKind &op_kind) {
if (name == nullptr || name[0] == '\0')
return false;