summaryrefslogtreecommitdiffstats
path: root/lldb
diff options
context:
space:
mode:
Diffstat (limited to 'lldb')
-rw-r--r--lldb/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py37
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp55
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h7
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp14
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h5
5 files changed, 100 insertions, 18 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py b/lldb/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py
index 011cf499291..c07acf9c540 100644
--- a/lldb/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py
+++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py
@@ -155,7 +155,9 @@ class TestMembersAndLocalsWithSameName(TestBase):
frame = thread.GetSelectedFrame()
self.assertTrue(frame.IsValid())
+ self.enable_expression_log()
val = frame.EvaluateExpression("a")
+ self.disable_expression_log_and_check_for_locals(['a'])
self.assertTrue(val.IsValid())
self.assertEqual(val.GetValueAsUnsigned(), 12345)
@@ -189,6 +191,12 @@ class TestMembersAndLocalsWithSameName(TestBase):
self.assertTrue(val.IsValid())
self.assertEqual(val.GetValueAsUnsigned(), 10003)
+ self.enable_expression_log()
+ val = frame.EvaluateExpression("c-b")
+ self.disable_expression_log_and_check_for_locals(['c','b'])
+ self.assertTrue(val.IsValid())
+ self.assertEqual(val.GetValueAsUnsigned(), 1)
+
self.process.Continue()
self.assertTrue(
self.process.GetState() == lldb.eStateStopped,
@@ -211,6 +219,13 @@ class TestMembersAndLocalsWithSameName(TestBase):
self.assertTrue(val.IsValid())
self.assertEqual(val.GetValueAsUnsigned(), 778899)
+ self.enable_expression_log()
+ val = frame.EvaluateExpression("a+b")
+ self.disable_expression_log_and_check_for_locals(['a','b'])
+ self.assertTrue(val.IsValid())
+ self.assertEqual(val.GetValueAsUnsigned(), 3)
+
+
def _load_exe(self):
self.build()
@@ -234,7 +249,9 @@ class TestMembersAndLocalsWithSameName(TestBase):
frame = thread.GetSelectedFrame()
self.assertTrue(frame.IsValid())
+ self.enable_expression_log()
val = frame.EvaluateExpression("a")
+ self.disable_expression_log_and_check_for_locals([])
self.assertTrue(val.IsValid())
self.assertEqual(val.GetValueAsUnsigned(), 112233)
@@ -245,3 +262,23 @@ class TestMembersAndLocalsWithSameName(TestBase):
val = frame.EvaluateExpression("c")
self.assertTrue(val.IsValid())
self.assertEqual(val.GetValueAsUnsigned(), 778899)
+
+ def enable_expression_log(self):
+ log_file = os.path.join(self.getBuildDir(), "expr.log")
+ self.runCmd("log enable -f '%s' lldb expr" % (log_file))
+
+ def disable_expression_log_and_check_for_locals(self, variables):
+ log_file = os.path.join(self.getBuildDir(), "expr.log")
+ self.runCmd("log disable lldb expr")
+ local_var_regex = re.compile(r".*__lldb_local_vars::(.*);")
+ matched = []
+ with open(log_file, 'r') as log:
+ for line in log:
+ if line.find('LLDB_BODY_START') != -1:
+ break
+ m = re.match(local_var_regex, line)
+ if m:
+ self.assertIn(m.group(1), variables)
+ matched.append(m.group(1))
+ self.assertEqual([item for item in variables if item not in matched],
+ [])
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
index 2fc690e3d5b..0bc664c93f8 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -8,6 +8,9 @@
#include "ClangExpressionSourceCode.h"
+#include "clang/Basic/CharInfo.h"
+#include "llvm/ADT/StringRef.h"
+
#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Symbol/Block.h"
@@ -161,8 +164,43 @@ static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit,
}
}
+/// Checks if the expression body contains the given variable as a token.
+/// \param body The expression body.
+/// \param var The variable token we are looking for.
+/// \return True iff the expression body containes the variable as a token.
+static bool ExprBodyContainsVar(llvm::StringRef body, llvm::StringRef var) {
+ assert(var.find_if([](char c) { return !clang::isIdentifierBody(c); }) ==
+ llvm::StringRef::npos &&
+ "variable contains non-identifier chars?");
+
+ size_t start = 0;
+ // Iterate over all occurences of the variable string in our expression.
+ while ((start = body.find(var, start)) != llvm::StringRef::npos) {
+ // We found our variable name in the expression. Check that the token
+ // that contains our needle is equal to our variable and not just contains
+ // the character sequence by accident.
+ // Prevents situations where we for example inlcude the variable 'FOO' in an
+ // expression like 'FOObar + 1'.
+ bool has_characters_before =
+ start != 0 && clang::isIdentifierBody(body[start - 1]);
+ bool has_characters_after =
+ start + var.size() < body.size() &&
+ clang::isIdentifierBody(body[start + var.size()]);
+
+ // Our token just contained the variable name as a substring. Continue
+ // searching the rest of the expression.
+ if (has_characters_before || has_characters_after) {
+ ++start;
+ continue;
+ }
+ return true;
+ }
+ return false;
+}
+
static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp,
- StreamString &stream) {
+ StreamString &stream,
+ const std::string &expr) {
for (size_t i = 0; i < var_list_sp->GetSize(); i++) {
lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i);
@@ -170,15 +208,17 @@ static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp,
if (!var_name || var_name == "this" || var_name == ".block_descriptor")
continue;
+ if (!expr.empty() && !ExprBodyContainsVar(expr, var_name.GetStringRef()))
+ continue;
+
stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString());
}
}
-bool ClangExpressionSourceCode::GetText(std::string &text,
- lldb::LanguageType wrapping_language,
- bool static_method,
- ExecutionContext &exe_ctx, bool add_locals,
- llvm::ArrayRef<std::string> modules) const {
+bool ClangExpressionSourceCode::GetText(
+ std::string &text, lldb::LanguageType wrapping_language, bool static_method,
+ ExecutionContext &exe_ctx, bool add_locals, bool force_add_all_locals,
+ llvm::ArrayRef<std::string> modules) const {
const char *target_specific_defines = "typedef signed char BOOL;\n";
std::string module_macros;
@@ -256,7 +296,8 @@ bool ClangExpressionSourceCode::GetText(std::string &text,
if (target->GetInjectLocalVariables(&exe_ctx)) {
lldb::VariableListSP var_list_sp =
frame->GetInScopeVariableList(false, true);
- AddLocalVariableDecls(var_list_sp, lldb_local_var_decls);
+ AddLocalVariableDecls(var_list_sp, lldb_local_var_decls,
+ force_add_all_locals ? "" : m_body);
}
}
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
index 3f20644d33c..89429029583 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
@@ -43,13 +43,14 @@ public:
/// evaluated.
/// \param add_locals True iff local variables should be injected into the
/// expression source code.
+ /// \param force_add_all_locals True iff all local variables should be
+ /// injected even if they are not used in the expression.
/// \param modules A list of (C++) modules that the expression should import.
///
/// \return true iff the source code was successfully generated.
bool GetText(std::string &text, lldb::LanguageType wrapping_language,
- bool static_method,
- ExecutionContext &exe_ctx,
- bool add_locals,
+ bool static_method, ExecutionContext &exe_ctx, bool add_locals,
+ bool force_add_all_locals,
llvm::ArrayRef<std::string> modules) const;
// Given a string returned by GetText, find the beginning and end of the body
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 8e08d4d7554..9fcf2d49845 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -386,7 +386,7 @@ static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
void ClangUserExpression::UpdateLanguageForExpr(
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
- std::vector<std::string> modules_to_import) {
+ std::vector<std::string> modules_to_import, bool for_completion) {
m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown;
std::string prefix = m_expr_prefix;
@@ -407,7 +407,7 @@ void ClangUserExpression::UpdateLanguageForExpr(
if (!source_code->GetText(m_transformed_text, m_expr_lang,
m_in_static_method, exe_ctx, !m_ctx_obj,
- modules_to_import)) {
+ for_completion, modules_to_import)) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"couldn't construct expression body");
return;
@@ -482,7 +482,8 @@ ClangUserExpression::GetModulesToImport(ExecutionContext &exe_ctx) {
}
bool ClangUserExpression::PrepareForParsing(
- DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
+ bool for_completion) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
InstallContext(exe_ctx);
@@ -511,7 +512,8 @@ bool ClangUserExpression::PrepareForParsing(
LLDB_LOG(log, "List of imported modules in expression: {0}",
llvm::make_range(used_modules.begin(), used_modules.end()));
- UpdateLanguageForExpr(diagnostic_manager, exe_ctx, used_modules);
+ UpdateLanguageForExpr(diagnostic_manager, exe_ctx, used_modules,
+ for_completion);
return true;
}
@@ -522,7 +524,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
bool generate_debug_info) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (!PrepareForParsing(diagnostic_manager, exe_ctx))
+ if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))
return false;
if (log)
@@ -721,7 +723,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
// correct.
DiagnosticManager diagnostic_manager;
- if (!PrepareForParsing(diagnostic_manager, exe_ctx))
+ if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))
return false;
if (log)
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index 7cf15536649..24c152bdb45 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -178,11 +178,12 @@ private:
std::vector<std::string> GetModulesToImport(ExecutionContext &exe_ctx);
void UpdateLanguageForExpr(DiagnosticManager &diagnostic_manager,
ExecutionContext &exe_ctx,
- std::vector<std::string> modules_to_import);
+ std::vector<std::string> modules_to_import,
+ bool for_completion);
bool SetupPersistentState(DiagnosticManager &diagnostic_manager,
ExecutionContext &exe_ctx);
bool PrepareForParsing(DiagnosticManager &diagnostic_manager,
- ExecutionContext &exe_ctx);
+ ExecutionContext &exe_ctx, bool for_completion);
ClangUserExpressionHelper m_type_system_helper;
OpenPOWER on IntegriCloud