blob: 6ff998244e994e55735628567f946dc51dbb9d25 [file] [log] [blame]
commit 4125b46232caf6a558470670f87b56ccb46d61aa
Author: Raphael Isemann <teemperor@gmail.com>
Date: Fri Jun 11 14:51:17 2021 +0200
Revert "[lldb] Add support for evaluating expressions in static member functions"
This reverts commit 00764c36edf88ae9806e8d57a6addb782e6ceae8 and the
follow up d2223c7a49973a61cc2de62992662afa8d19065a.
The original patch broke that one could use static member variables while
inside a static member functions without having a running target. It seems that
LLDB currently requires that static variables are only found via the global
variable lookup so that they can get materialized and mapped to the argument
struct of the expression.
After 00764c36edf88ae9806e8d57a6addb782e6ceae8 static variables of the current
class could be found via Clang's lookup which LLDB isn't observing. This
resulting in expressions actually containing these variables as normal
globals that can't be rewritten to a member of the argument struct.
More specifically, in the test TestCPPThis, the expression
`expr --j false -- s_a` is now only passing if we have a runnable target.
I'll revert the patch as the possible fixes aren't trivial and it degrades
the debugging experience more than the issue that the revert patch addressed.
The underlying bug can be reproduced before/after this patch by stopping
in `TestCPPThis` main function and running: `e -j false -- my_a; A<int>::s_a`.
The `my_a` will pull in the `A<int>` class and the second expression will
be resolved by Clang on its own (which causes LLDB to not materialize the
static variable).
Note: A workaround is to just do `::s_a` which will force LLDB to take the global
variable lookup.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 761e6aa273f7..731b81c61a6f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -810,7 +810,7 @@ void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context) {
LLDB_LOG(log, " CEDM::FEVD Adding type for $__lldb_class: {1}",
class_qual_type.getAsString());
- AddContextClassType(context, class_user_type, method_decl);
+ AddContextClassType(context, class_user_type);
if (method_decl->isInstance()) {
// self is a pointer to the object
@@ -1890,9 +1890,8 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
}
}
-void ClangExpressionDeclMap::AddContextClassType(
- NameSearchContext &context, const TypeFromUser &ut,
- CXXMethodDecl *context_method) {
+void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context,
+ const TypeFromUser &ut) {
CompilerType copied_clang_type = GuardedCopyType(ut);
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -1914,12 +1913,7 @@ void ClangExpressionDeclMap::AddContextClassType(
void_clang_type, &void_ptr_clang_type, 1, false, 0);
const bool is_virtual = false;
- // If we evaluate an expression inside a static method, we also need to
- // make our lldb_expr method static so that Clang denies access to
- // non-static members.
- // If we don't have a context_method we are evaluating within a context
- // object and we can allow access to non-static members.
- const bool is_static = context_method ? context_method->isStatic() : false;
+ const bool is_static = false;
const bool is_inline = false;
const bool is_explicit = false;
const bool is_attr_used = true;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index 1af5df95821e..93060bd6b587 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -607,13 +607,8 @@ private:
///
/// \param[in] type
/// The type of the class that serves as the evaluation context.
- ///
- /// \param[in] context_method
- /// The member function declaration in which the expression is being
- /// evaluated or null if the expression is not evaluated in the context
- /// of a member function.
- void AddContextClassType(NameSearchContext &context, const TypeFromUser &type,
- clang::CXXMethodDecl *context_method = nullptr);
+ void AddContextClassType(NameSearchContext &context,
+ const TypeFromUser &type);
/// Move a type out of the current ASTContext into another, but make sure to
/// export all components of the type also.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
index 1a050fc5ffb4..31707f81a270 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -420,7 +420,6 @@ bool ClangExpressionSourceCode::GetText(
module_imports.c_str(), m_name.c_str(),
lldb_local_var_decls.GetData(), tagged_body.c_str());
break;
- case WrapKind::CppStaticMemberFunction:
case WrapKind::CppMemberFunction:
wrap_stream.Printf("%s"
"void \n"
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
index 509cab98c875..54ae837fb30f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
@@ -33,13 +33,12 @@ public:
enum class WrapKind {
/// Wrapped in a non-static member function of a C++ class.
CppMemberFunction,
- /// Wrapped in a static member function of a C++ class.
- CppStaticMemberFunction,
/// Wrapped in an instance Objective-C method.
ObjCInstanceMethod,
/// Wrapped in a static Objective-C method.
ObjCStaticMethod,
/// Wrapped in a non-member function.
+ /// Note that this is also used for static member functions of a C++ class.
Function
};
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 978eb7d0a4f1..7db813d06a1c 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -155,35 +155,32 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
m_needs_object_ptr = true;
} else if (clang::CXXMethodDecl *method_decl =
TypeSystemClang::DeclContextGetAsCXXMethodDecl(decl_context)) {
- if (m_allow_cxx) {
- if (method_decl->isInstance()) {
- if (m_enforce_valid_object) {
- lldb::VariableListSP variable_list_sp(
- function_block->GetBlockVariableList(true));
+ if (m_allow_cxx && method_decl->isInstance()) {
+ if (m_enforce_valid_object) {
+ lldb::VariableListSP variable_list_sp(
+ function_block->GetBlockVariableList(true));
- const char *thisErrorString =
- "Stopped in a C++ method, but 'this' "
- "isn't available; pretending we are in a "
- "generic context";
+ const char *thisErrorString = "Stopped in a C++ method, but 'this' "
+ "isn't available; pretending we are in a "
+ "generic context";
- if (!variable_list_sp) {
- err.SetErrorString(thisErrorString);
- return;
- }
+ if (!variable_list_sp) {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
- lldb::VariableSP this_var_sp(
- variable_list_sp->FindVariable(ConstString("this")));
+ lldb::VariableSP this_var_sp(
+ variable_list_sp->FindVariable(ConstString("this")));
- if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
- !this_var_sp->LocationIsValidForFrame(frame)) {
- err.SetErrorString(thisErrorString);
- return;
- }
+ if (!this_var_sp || !this_var_sp->IsInScope(frame) ||
+ !this_var_sp->LocationIsValidForFrame(frame)) {
+ err.SetErrorString(thisErrorString);
+ return;
}
- m_needs_object_ptr = true;
}
+
m_in_cplusplus_method = true;
- m_in_static_method = !method_decl->isInstance();
+ m_needs_object_ptr = true;
}
} else if (clang::ObjCMethodDecl *method_decl =
TypeSystemClang::DeclContextGetAsObjCMethodDecl(
@@ -405,11 +402,9 @@ ClangExpressionSourceCode::WrapKind ClangUserExpression::GetWrapKind() const {
assert(m_options.GetExecutionPolicy() != eExecutionPolicyTopLevel &&
"Top level expressions aren't wrapped.");
using Kind = ClangExpressionSourceCode::WrapKind;
- if (m_in_cplusplus_method) {
- if (m_in_static_method)
- return Kind::CppStaticMemberFunction;
+ if (m_in_cplusplus_method)
return Kind::CppMemberFunction;
- } else if (m_in_objectivec_method) {
+ else if (m_in_objectivec_method) {
if (m_in_static_method)
return Kind::ObjCStaticMethod;
return Kind::ObjCInstanceMethod;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index 5f6db2f80978..b628f6debf66 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -254,7 +254,7 @@ private:
bool m_in_objectivec_method = false;
/// True if the expression is compiled as a static (or class) method
/// (currently true if it was parsed when exe_ctx was in an Objective-C class
- /// method or static C++ member function).
+ /// method).
bool m_in_static_method = false;
/// True if "this" or "self" must be looked up and passed in. False if the
/// expression doesn't really use them and they can be NULL.
diff --git a/lldb/test/API/lang/cpp/stopped_in_static_member_function/Makefile b/lldb/test/API/lang/cpp/stopped_in_static_member_function/Makefile
deleted file mode 100644
index 99998b20bcb0..000000000000
--- a/lldb/test/API/lang/cpp/stopped_in_static_member_function/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-CXX_SOURCES := main.cpp
-
-include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/stopped_in_static_member_function/TestStoppedInStaticMemberFunction.py b/lldb/test/API/lang/cpp/stopped_in_static_member_function/TestStoppedInStaticMemberFunction.py
deleted file mode 100644
index b69263a00fd2..000000000000
--- a/lldb/test/API/lang/cpp/stopped_in_static_member_function/TestStoppedInStaticMemberFunction.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class TestCase(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- # On Windows we can lookup the declarations of static members but finding
- # up the underlying symbols doesn't work yet.
- @expectedFailureAll(oslist=["windows"])
- @no_debug_info_test
- def test(self):
- self.build()
- lldbutil.run_to_source_breakpoint(self, "// break in static member function", lldb.SBFileSpec("main.cpp"))
-
- # Evaluate a static member and call a static member function.
- self.expect_expr("static_member_var", result_type="int", result_value="2")
- self.expect_expr("static_const_member_var", result_type="const int", result_value="3")
- self.expect_expr("static_constexpr_member_var", result_type="const int", result_value="4")
- self.expect_expr("static_func()", result_type="int", result_value="6")
-
- # Check that accessing non-static members just reports a diagnostic.
- self.expect("expr member_var", error=True,
- substrs=["invalid use of member 'member_var' in static member function"])
- self.expect("expr member_func()", error=True,
- substrs=["call to non-static member function without an object argument"])
- self.expect("expr this", error=True,
- substrs=["invalid use of 'this' outside of a non-static member function"])
-
- # Continue to a non-static member function of the same class and make
- # sure that evaluating non-static members now works.
- breakpoint = self.target().BreakpointCreateBySourceRegex(
- "// break in member function", lldb.SBFileSpec("main.cpp"))
- self.assertNotEqual(breakpoint.GetNumResolvedLocations(), 0)
- stopped_threads = lldbutil.continue_to_breakpoint(self.process(), breakpoint)
-
- self.expect_expr("member_var", result_type="int", result_value="1")
- self.expect_expr("member_func()", result_type="int", result_value="5")
diff --git a/lldb/test/API/lang/cpp/stopped_in_static_member_function/main.cpp b/lldb/test/API/lang/cpp/stopped_in_static_member_function/main.cpp
deleted file mode 100644
index 8c8b7c183903..000000000000
--- a/lldb/test/API/lang/cpp/stopped_in_static_member_function/main.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-struct A {
- int member_var = 1;
- static int static_member_var;
- static const int static_const_member_var;
- static constexpr int static_constexpr_member_var = 4;
- int member_func() { return 5; }
- static int static_func() { return 6; }
-
- static int context_static_func() {
- int i = static_member_var;
- i += static_func();
- return i; // break in static member function
- }
-
- int context_member_func() {
- int i = member_var;
- i += member_func();
- return i; // break in member function
- }
-};
-
-int A::static_member_var = 2;
-const int A::static_const_member_var = 3;
-constexpr int A::static_constexpr_member_var;
-
-int main() {
- int i = A::context_static_func();
- A a;
- a.context_member_func();
- return i;
-}