Szelethus updated this revision to Diff 201679.
Szelethus added a comment.

Correctly use `reverse(children<NodePtr>(N))` and 
`inverse_children<NodePtr>(N)`, based on the original code:

  template <bool Inverse>
  struct ChildrenGetter {
    using ResultTy = SmallVector<NodePtr, 8>;
  
    static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) {
      auto RChildren = reverse(children<NodePtr>(N));
      return ResultTy(RChildren.begin(), RChildren.end());
    }
  
    static ResultTy Get(NodePtr N, std::integral_constant<bool, true>) {
      auto IChildren = inverse_children<NodePtr>(N);
      return ResultTy(IChildren.begin(), IChildren.end());
    }
  
    using Tag = std::integral_constant<bool, Inverse>;
  
    // etc etc...


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D62507/new/

https://reviews.llvm.org/D62507

Files:
  clang/include/clang/Analysis/Analyses/Dominators.h
  clang/test/Analysis/domtest.cpp

Index: clang/test/Analysis/domtest.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/domtest.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN:   -analyzer-checker=debug.DumpCFG \
+// RUN:   -analyzer-checker=debug.DumpDominators \
+// RUN:   2>&1 | FileCheck %s
+
+namespace pr42041_unreachable_cfg_successor {
+enum Kind {
+  A
+};
+
+void f() {
+  switch(Kind{}) {
+  case A:
+    break;
+  }
+}
+} // end of namespace pr42041_unreachable_cfg_successor
+
+// CHECK:      void f()
+// CHECK-NEXT:  [B3 (ENTRY)]
+// CHECK-NEXT:    Succs (1): B1
+//
+// CHECK:       [B1]
+// CHECK-NEXT:    1: {}
+// CHECK-NEXT:    2: pr42041_unreachable_cfg_successor::Kind[B1.1]
+// CHECK-SAME:                    (CXXFunctionalCastExpr, NoOp,
+// CHECK-SAME:                     enum pr42041_unreachable_cfg_successor::Kind)
+// CHECK-NEXT:    3: [B1.2] (ImplicitCastExpr, IntegralCast, int)
+// CHECK-NEXT:    T: switch [B1.3]
+// CHECK-NEXT:    Preds (1): B3
+// CHECK-NEXT:    Succs (2): B2 B0(Unreachable)
+//
+// CHECK:       [B2]
+// CHECK-NEXT:   case A:
+// CHECK-NEXT:    T: break;
+// CHECK-NEXT:    Preds (1): B1
+// CHECK-NEXT:    Succs (1): B0
+//
+// CHECK:       [B0 (EXIT)]
+// CHECK-NEXT:    Preds (2): B2 B1(Unreachable)
+//
+// CHECK:      Immediate dominance tree (Node#,IDom#):
+// CHECK-NEXT: (0,2)
+// CHECK-NEXT: (1,3)
+// CHECK-NEXT: (2,1)
+// CHECK-NEXT: (3,3)
Index: clang/include/clang/Analysis/Analyses/Dominators.h
===================================================================
--- clang/include/clang/Analysis/Analyses/Dominators.h
+++ clang/include/clang/Analysis/Analyses/Dominators.h
@@ -155,13 +155,51 @@
 
 } // namespace clang
 
+namespace llvm {
+
+/// Clang's CFG contains nullpointers for unreachable succesors, e.g. when an
+/// if statement's condition is always false, it's 'then' branch is represented
+/// with a nullptr. This however will result in a nullpointer derefernece for
+/// dominator tree calculation.
+///
+/// To circumvent this, let's just crudely specialize the children getters
+/// used in LLVM's dominator tree builder.
+namespace DomTreeBuilder {
+
+using ClangCFGDomChildrenGetter =
+SemiNCAInfo<DomTreeBase<clang::CFGBlock>>::ChildrenGetter</*Inverse=*/false>;
+
+template <>
+template <>
+ClangCFGDomChildrenGetter::ResultTy ClangCFGDomChildrenGetter::Get(
+    clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/false>) {
+  auto RChildren = reverse(children<NodePtr>(N));
+  ResultTy Ret(RChildren.begin(), RChildren.end());
+  Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
+  return Ret;
+}
+
+using ClangCFGDomReverseChildrenGetter =
+SemiNCAInfo<DomTreeBase<clang::CFGBlock>>::ChildrenGetter</*Inverse=*/true>;
+
+template <>
+template <>
+ClangCFGDomReverseChildrenGetter::ResultTy
+ClangCFGDomReverseChildrenGetter::Get(
+    clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/true>) {
+  auto RChildren = inverse_children<NodePtr>(N);
+  ResultTy Ret(RChildren.begin(), RChildren.end());
+  Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
+  return Ret;
+}
+
+} // end of namespace DomTreeBuilder
+
 //===-------------------------------------
 /// DominatorTree GraphTraits specialization so the DominatorTree can be
 /// iterable by generic graph iterators.
 ///
-namespace llvm {
-
-template <> struct GraphTraits< ::clang::DomTreeNode* > {
+template <> struct GraphTraits<clang::DomTreeNode *> {
   using NodeRef = ::clang::DomTreeNode *;
   using ChildIteratorType = ::clang::DomTreeNode::iterator;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to