[Lldb-commits] [lldb] cb81e66 - [lldb] Reject redefinitions of persistent variables

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Wed Oct 14 01:25:07 PDT 2020


Author: Raphael Isemann
Date: 2020-10-14T10:24:35+02:00
New Revision: cb81e662a58908913f342520e4c010564a68126a

URL: https://github.com/llvm/llvm-project/commit/cb81e662a58908913f342520e4c010564a68126a
DIFF: https://github.com/llvm/llvm-project/commit/cb81e662a58908913f342520e4c010564a68126a.diff

LOG: [lldb] Reject redefinitions of persistent variables

Currently one can redefine a persistent variable and LLDB will just silently
ignore the second definition:

```
(lldb) expr int $i = 1
(lldb) expr int $i = 2
(lldb) expr $i
(int) $i = 1
```

This patch makes this an error and rejects the expression with the second
definition.

A nice follow up would be to refactor LLDB's persistent variables to not just be
a pair of type and name, but also contain some way to obtain the original
declaration and source code that declared the variable. That way we could
actually make a full diagnostic as we would get from redefining a variable twice
in the same expression.

Reviewed By: labath, shafik, JDevlieghere

Differential Revision: https://reviews.llvm.org/D89310

Added: 
    

Modified: 
    lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
    lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
    lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
    lldb/test/API/commands/expression/persistent_variables/TestPersistentVariables.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 8c49898e1d6c..7d8cd85500ae 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -19,6 +19,7 @@
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Expression/DiagnosticManager.h"
 #include "lldb/Expression/Materializer.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/CompilerDecl.h"
@@ -125,6 +126,12 @@ void ClangExpressionDeclMap::InstallCodeGenerator(
   m_parser_vars->m_code_gen = code_gen;
 }
 
+void ClangExpressionDeclMap::InstallDiagnosticManager(
+    DiagnosticManager &diag_manager) {
+  assert(m_parser_vars);
+  m_parser_vars->m_diagnostics = &diag_manager;
+}
+
 void ClangExpressionDeclMap::DidParse() {
   if (m_parser_vars && m_parser_vars->m_persistent_vars) {
     for (size_t entity_index = 0, num_entities = m_found_entities.GetSize();
@@ -196,6 +203,17 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
   if (ast == nullptr)
     return false;
 
+  // Check if we already declared a persistent variable with the same name.
+  if (lldb::ExpressionVariableSP conflicting_var =
+          m_parser_vars->m_persistent_vars->GetVariable(name)) {
+    std::string msg = llvm::formatv("redefinition of persistent variable '{0}'",
+                                    name).str();
+    m_parser_vars->m_diagnostics->AddDiagnostic(
+        msg, DiagnosticSeverity::eDiagnosticSeverityError,
+        DiagnosticOrigin::eDiagnosticOriginLLDB);
+    return false;
+  }
+
   if (m_parser_vars->m_materializer && is_result) {
     Status err;
 

diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index 6974535a8993..0c81d46c6c52 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -102,6 +102,8 @@ class ClangExpressionDeclMap : public ClangASTSource {
 
   void InstallCodeGenerator(clang::ASTConsumer *code_gen);
 
+  void InstallDiagnosticManager(DiagnosticManager &diag_manager);
+
   /// Disable the state needed for parsing and IR transformation.
   void DidParse();
 
@@ -330,6 +332,8 @@ class ClangExpressionDeclMap : public ClangASTSource {
     clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator
                                               ///that receives new top-level
                                               ///functions.
+    DiagnosticManager *m_diagnostics = nullptr;
+
   private:
     ParserVars(const ParserVars &) = delete;
     const ParserVars &operator=(const ParserVars &) = delete;

diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 8ad39ecd2707..bd0d831f0ca7 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -1078,6 +1078,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
   ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap();
   if (decl_map) {
     decl_map->InstallCodeGenerator(&m_compiler->getASTConsumer());
+    decl_map->InstallDiagnosticManager(diagnostic_manager);
 
     clang::ExternalASTSource *ast_source = decl_map->CreateProxy();
 

diff  --git a/lldb/test/API/commands/expression/persistent_variables/TestPersistentVariables.py b/lldb/test/API/commands/expression/persistent_variables/TestPersistentVariables.py
index ebe180998c63..bdd1ccc59696 100644
--- a/lldb/test/API/commands/expression/persistent_variables/TestPersistentVariables.py
+++ b/lldb/test/API/commands/expression/persistent_variables/TestPersistentVariables.py
@@ -41,3 +41,19 @@ def test_persistent_variables(self):
         # Test that $200 wasn't created by the previous expression.
         self.expect("expr $200", error=True,
             substrs=["use of undeclared identifier '$200'"])
+
+        # Try redeclaring the persistent variable with the same type.
+        # This should be rejected as we treat them as if they are globals.
+        self.expect("expr int $i = 123", error=True,
+                    substrs=["error: redefinition of persistent variable '$i'"])
+        self.expect_expr("$i", result_type="int", result_value="5")
+
+        # Try redeclaring the persistent variable with another type. Should
+        # also be rejected.
+        self.expect("expr long $i = 123", error=True,
+                    substrs=["error: redefinition of persistent variable '$i'"])
+        self.expect_expr("$i", result_type="int", result_value="5")
+
+        # Try assigning the persistent variable a new value.
+        self.expect("expr $i = 55")
+        self.expect_expr("$i", result_type="int", result_value="55")


        


More information about the lldb-commits mailing list