[Lldb-commits] [lldb] 02114e1 - [lldb] Allow limiting the number of error diagnostics when parsing an expression

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 13 08:13:03 PDT 2020


Author: Raphael Isemann
Date: 2020-10-13T17:12:43+02:00
New Revision: 02114e15daad7f02e65289412d37334618386ce5

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

LOG: [lldb] Allow limiting the number of error diagnostics when parsing an expression

While debugging another bug I found out that we currently don't set any limit
for the number of diagnostics Clang emits. If a user does something that
generates a lot of errors (like including some long header file from within the
expression function), then we currently spam the LLDB output with potentially
thousands of Clang error diagnostics.

Clang sets a default limit of 20 errors, but given that LLDB is often used
interactively for small expressions I would say a limit of 5 is enough. The
limit is implemented as a setting, so if a user cares about seeing having a
million errors printed to their terminal then they can just increase the
settings value.

Reviewed By: shafik, mib

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

Added: 
    lldb/test/API/commands/expression/error-limit/Makefile
    lldb/test/API/commands/expression/error-limit/TestExprErrorLimit.py
    lldb/test/API/commands/expression/error-limit/main.cpp

Modified: 
    lldb/include/lldb/Target/Target.h
    lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
    lldb/source/Target/Target.cpp
    lldb/source/Target/TargetProperties.td

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index f371c4fd6956..0a27147cb61d 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -173,6 +173,8 @@ class TargetProperties : public Properties {
 
   llvm::StringRef GetExpressionPrefixContents();
 
+  uint64_t GetExprErrorLimit() const;
+
   bool GetUseHexImmediates() const;
 
   bool GetUseFastStepping() const;

diff  --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 202eb87cca3d..8ad39ecd2707 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -454,6 +454,10 @@ ClangExpressionParser::ClangExpressionParser(
 
   // 4. Create and install the target on the compiler.
   m_compiler->createDiagnostics();
+  // Limit the number of error diagnostics we emit.
+  // A value of 0 means no limit for both LLDB and Clang.
+  m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
+
   auto target_info = TargetInfo::CreateTargetInfo(
       m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts);
   if (log) {

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 6ce613697825..5cbdb4995c75 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -4026,6 +4026,12 @@ llvm::StringRef TargetProperties::GetExpressionPrefixContents() {
   return "";
 }
 
+uint64_t TargetProperties::GetExprErrorLimit() const {
+  const uint32_t idx = ePropertyExprErrorLimit;
+  return m_collection_sp->GetPropertyAtIndexAsUInt64(
+      nullptr, idx, g_target_properties[idx].default_uint_value);
+}
+
 bool TargetProperties::GetBreakpointsConsultPlatformAvoidList() {
   const uint32_t idx = ePropertyBreakpointUseAvoidList;
   return m_collection_sp->GetPropertyAtIndexAsBoolean(

diff  --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 7fb9b105ceef..c624bc35d16e 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -20,6 +20,10 @@ let Definition = "target" in {
   def ExprPrefix: Property<"expr-prefix", "FileSpec">,
     DefaultStringValue<"">,
     Desc<"Path to a file containing expressions to be prepended to all expressions.">;
+  def ExprErrorLimit: Property<"expr-error-limit", "UInt64">,
+    DefaultUnsignedValue<5>,
+    Desc<"The maximum amount of errors to emit while parsing an expression. "
+         "A value of 0 means to always continue parsing if possible.">;
   def PreferDynamic: Property<"prefer-dynamic-value", "Enum">,
     DefaultEnumValue<"eDynamicDontRunTarget">,
     EnumValues<"OptionEnumValues(g_dynamic_value_types)">,

diff  --git a/lldb/test/API/commands/expression/error-limit/Makefile b/lldb/test/API/commands/expression/error-limit/Makefile
new file mode 100644
index 000000000000..99998b20bcb0
--- /dev/null
+++ b/lldb/test/API/commands/expression/error-limit/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules

diff  --git a/lldb/test/API/commands/expression/error-limit/TestExprErrorLimit.py b/lldb/test/API/commands/expression/error-limit/TestExprErrorLimit.py
new file mode 100644
index 000000000000..30e003787ec5
--- /dev/null
+++ b/lldb/test/API/commands/expression/error-limit/TestExprErrorLimit.py
@@ -0,0 +1,60 @@
+"""
+Tests target.expr-error-limit.
+"""
+
+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__)
+
+    @no_debug_info_test
+    def test(self):
+        # FIXME: The only reason this test needs to create a real target is because
+        # the settings of the dummy target can't be changed with `settings set`.
+        self.build()
+        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+
+        # Our test expression that is just several lines of malformed
+        # integer literals (with a 'yerror' integer suffix). Every error
+        # has its own unique string (1, 2, 3, 4) and is on its own line
+        # that we can later find it when Clang prints the respective source
+        # code for each error to the error output.
+        # For example, in the error output below we would look for the
+        # unique `1yerror` string:
+        #     error: <expr>:1:2: invalid suffix 'yerror' on integer constant
+        #     1yerror
+        #     ^
+        expr = "1yerror;\n2yerror;\n3yerror;\n4yerror;"
+
+        options = lldb.SBExpressionOptions()
+        options.SetAutoApplyFixIts(False)
+
+        # Evaluate the expression and check that only the first 2 errors are
+        # emitted.
+        self.runCmd("settings set target.expr-error-limit 2")
+        eval_result = target.EvaluateExpression(expr, options)
+        self.assertIn("1yerror", str(eval_result.GetError()))
+        self.assertIn("2yerror", str(eval_result.GetError()))
+        self.assertNotIn("3yerror", str(eval_result.GetError()))
+        self.assertNotIn("4yerror", str(eval_result.GetError()))
+
+        # Change to a 3 errors and check again which errors are emitted.
+        self.runCmd("settings set target.expr-error-limit 3")
+        eval_result = target.EvaluateExpression(expr, options)
+        self.assertIn("1yerror", str(eval_result.GetError()))
+        self.assertIn("2yerror", str(eval_result.GetError()))
+        self.assertIn("3yerror", str(eval_result.GetError()))
+        self.assertNotIn("4yerror", str(eval_result.GetError()))
+
+        # Disable the error limit and make sure all errors are emitted.
+        self.runCmd("settings set target.expr-error-limit 0")
+        eval_result = target.EvaluateExpression(expr, options)
+        self.assertIn("1yerror", str(eval_result.GetError()))
+        self.assertIn("2yerror", str(eval_result.GetError()))
+        self.assertIn("3yerror", str(eval_result.GetError()))
+        self.assertIn("4yerror", str(eval_result.GetError()))

diff  --git a/lldb/test/API/commands/expression/error-limit/main.cpp b/lldb/test/API/commands/expression/error-limit/main.cpp
new file mode 100644
index 000000000000..ba45ee316cd4
--- /dev/null
+++ b/lldb/test/API/commands/expression/error-limit/main.cpp
@@ -0,0 +1,3 @@
+int main() {
+  return 0; // break here
+}


        


More information about the lldb-commits mailing list