Browse Source

PrintCallStack: "Fix" entry suppression

Backtraces may contain non-specific entries (n.b. FromListFilePath in
cmListFileContext). Our prior expectation is that these will ALWAYS
replaced by more specific entries. However, with the previous change to
allow users to create arbitrary stack entries, this is no longer the
case. Modify PrintCallStack to only skip printing these non-specific
entries if they were in fact preceded by a more specific entry.

This, and the functionality of the preceding commit, is intended to be
used for CPS dependency resolution. Because said resolution may fail at
a non-trivial depth, it is important to be able to provide the user with
the path of packages that led to the failure. However, because this
happens through parsing JSON, there is no listfile function to associate
with the stack entries, nor do we attempt to keep track of line numbers
from the JSON. As a result, these entries will never be more specific
than the name of the CPS file whose dependencies we are trying to
locate.
Matthew Woehlke 11 months ago
parent
commit
dcaa52c6c3
2 changed files with 12 additions and 7 deletions
  1. 4 4
      Source/cmListFileCache.h
  2. 8 3
      Source/cmMessenger.cxx

+ 4 - 4
Source/cmListFileCache.h

@@ -138,10 +138,10 @@ public:
 
   static cmListFileContext FromListFilePath(std::string const& filePath)
   {
-    // We are entering a file-level scope but have not yet reached
-    // any specific line or command invocation within it.  This context
-    // is useful to print when it is at the top but otherwise can be
-    // skipped during call stack printing.
+    // We are entering a file-level scope but have not yet reached any specific
+    // line or command invocation within it.  This context is useful to print
+    // when it is at the top, but otherwise can be skipped during call stack
+    // printing if preceded by a more specific entry.
     cmListFileContext lfc;
     lfc.FilePath = filePath;
     return lfc;

+ 8 - 3
Source/cmMessenger.cxx

@@ -116,6 +116,7 @@ void PrintCallStack(std::ostream& out, cmListFileBacktrace bt,
   if (bt.Empty()) {
     return;
   }
+  std::string lastFilePath = bt.Top().FilePath;
   bt = bt.Pop();
   if (bt.Empty()) {
     return;
@@ -125,15 +126,19 @@ void PrintCallStack(std::ostream& out, cmListFileBacktrace bt,
   for (; !bt.Empty(); bt = bt.Pop()) {
     cmListFileContext lfc = bt.Top();
     if (lfc.Name.empty() &&
-        lfc.Line != cmListFileContext::DeferPlaceholderLine) {
-      // Skip this whole-file scope.  When we get here we already will
-      // have printed a more-specific context within the file.
+        lfc.Line != cmListFileContext::DeferPlaceholderLine &&
+        lfc.FilePath == lastFilePath) {
+      // An entry with no function name is frequently preceded (in the stack)
+      // by a more specific entry.  When this happens (as verified by the
+      // preceding entry referencing the same file path), skip the less
+      // specific entry, as we have already printed the more specific one.
       continue;
     }
     if (first) {
       first = false;
       out << "Call Stack (most recent call first):\n";
     }
+    lastFilePath = lfc.FilePath;
     if (topSource) {
       lfc.FilePath = cmSystemTools::RelativeIfUnder(*topSource, lfc.FilePath);
     }