Fix crash when analyzing C++ code involving constant enums and switch statements (<rdar://problem/10202899>).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140844 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 8f2b55c..2ff2be9 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -301,7 +301,10 @@
class BlockEdge : public ProgramPoint {
public:
BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
- : ProgramPoint(B1, B2, BlockEdgeKind, L) {}
+ : ProgramPoint(B1, B2, BlockEdgeKind, L) {
+ assert(B1 && "BlockEdge: source block must be non-null");
+ assert(B2 && "BlockEdge: destination block must be non-null");
+ }
const CFGBlock *getSrc() const {
return static_cast<const CFGBlock*>(getData1());
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index 20b86a8f..2511ca7 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -697,13 +697,18 @@
SwitchNodeBuilder::generateDefaultCaseNode(const ProgramState *St,
bool isSink) {
// Get the block for the default case.
- assert (Src->succ_rbegin() != Src->succ_rend());
+ assert(Src->succ_rbegin() != Src->succ_rend());
CFGBlock *DefaultBlock = *Src->succ_rbegin();
+ // Sanity check for default blocks that are unreachable and not caught
+ // by earlier stages.
+ if (!DefaultBlock)
+ return NULL;
+
bool IsNew;
ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock,
- Pred->getLocationContext()), St, &IsNew);
+ Pred->getLocationContext()), St, &IsNew);
Succ->addPredecessor(Pred, *Eng.G);
if (IsNew) {
diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp
index 1d055d5..37153f7 100644
--- a/test/Analysis/misc-ps-region-store.cpp
+++ b/test/Analysis/misc-ps-region-store.cpp
@@ -441,3 +441,29 @@
return 0;
}
+// Regression test against global constants and switches.
+enum rdar10202899_ValT { rdar10202899_ValTA, rdar10202899_ValTB, rdar10202899_ValTC };
+const rdar10202899_ValT val = rdar10202899_ValTA;
+void rdar10202899_test1() {
+ switch (val) {
+ case rdar10202899_ValTA: {}
+ };
+}
+
+void rdar10202899_test2() {
+ if (val == rdar10202899_ValTA)
+ return;
+ int *p = 0;
+ *p = 0xDEADBEEF;
+}
+
+void rdar10202899_test3() {
+ switch (val) {
+ case rdar10202899_ValTA: return;
+ default: ;
+ };
+ int *p = 0;
+ *p = 0xDEADBEEF;
+}
+
+