diff options
-rw-r--r-- | include/clang/AST/Expr.h | 9 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h | 4 | ||||
-rw-r--r-- | lib/Analysis/CFG.cpp | 75 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 61 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/MemRegion.cpp | 10 | ||||
-rw-r--r-- | test/Analysis/temp-obj-dtors-cfg-output.cpp | 170 | ||||
-rw-r--r-- | test/Analysis/unix-fns.c | 96 | ||||
-rw-r--r-- | test/Sema/warn-unreachable.c | 8 |
8 files changed, 304 insertions, 129 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 09ca2758fe..598f18937f 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2207,6 +2207,15 @@ public: return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); } + /// This method provides fast access to all the subexpressions of + /// a CallExpr without going through the slower virtual child_iterator + /// interface. This provides efficient reverse iteration of the + /// subexpressions. This is currently used for CFG construction. + ArrayRef<Stmt*> getRawSubExprs() { + return ArrayRef<Stmt*>(SubExprs, + getNumPreArgs() + PREARGS_START + getNumArgs()); + } + /// getNumCommas - Return the number of commas that must have been present in /// this function call. unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index b0a44e26fe..59225cb150 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -662,6 +662,10 @@ public: return *this; } }; + + /// Return the original region for a captured region, if + /// one exists. + const VarRegion *getOriginalRegion(const VarRegion *VR) const; referenced_vars_iterator referenced_vars_begin() const; referenced_vars_iterator referenced_vars_end() const; diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index cd0ff0a492..1cbaaee4a1 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -233,6 +233,43 @@ public: } }; +class reverse_children { + llvm::SmallVector<Stmt *, 12> childrenBuf; + ArrayRef<Stmt*> children; +public: + reverse_children(Stmt *S); + + typedef ArrayRef<Stmt*>::reverse_iterator iterator; + iterator begin() const { return children.rbegin(); } + iterator end() const { return children.rend(); } +}; + + +reverse_children::reverse_children(Stmt *S) { + if (CallExpr *CE = dyn_cast<CallExpr>(S)) { + children = CE->getRawSubExprs(); + return; + } + switch (S->getStmtClass()) { + case Stmt::InitListExprClass: { + InitListExpr *IE = cast<InitListExpr>(S); + children = llvm::makeArrayRef(reinterpret_cast<Stmt**>(IE->getInits()), + IE->getNumInits()); + return; + } + default: + break; + } + + // Default case for all other statements. + for (Stmt::child_range I = S->children(); I; ++I) { + childrenBuf.push_back(*I); + } + + // This needs to be done *after* childrenBuf has been populated. + children = childrenBuf; +} + /// CFGBuilder - This class implements CFG construction from an AST. /// The builder is stateful: an instance of the builder should be used to only /// construct a single CFG. @@ -1166,14 +1203,19 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { } /// VisitChildren - Visit the children of a Stmt. -CFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) { - CFGBlock *lastBlock = Block; - for (Stmt::child_range I = Terminator->children(); I; ++I) - if (Stmt *child = *I) - if (CFGBlock *b = Visit(child)) - lastBlock = b; +CFGBlock *CFGBuilder::VisitChildren(Stmt *S) { + CFGBlock *B = Block; - return lastBlock; + // Visit the children in their reverse order so that they appear in + // left-to-right (natural) order in the CFG. + reverse_children RChildren(S); + for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end(); + I != E; ++I) { + if (Stmt *Child = *I) + if (CFGBlock *R = Visit(Child)) + B = R; + } + return B; } CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, @@ -3093,19 +3135,14 @@ tryAgain: CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { // When visiting children for destructors we want to visit them in reverse - // order. Because there's no reverse iterator for children must to reverse - // them in helper vector. - typedef SmallVector<Stmt *, 4> ChildrenVect; - ChildrenVect ChildrenRev; - for (Stmt::child_range I = E->children(); I; ++I) { - if (*I) ChildrenRev.push_back(*I); - } - + // order that they will appear in the CFG. Because the CFG is built + // bottom-up, this means we visit them in their natural order, which + // reverses them in the CFG. CFGBlock *B = Block; - for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(), - L = ChildrenRev.rend(); I != L; ++I) { - if (CFGBlock *R = VisitForTemporaryDtors(*I)) - B = R; + for (Stmt::child_range I = E->children(); I; ++I) { + if (Stmt *Child = *I) + if (CFGBlock *R = VisitForTemporaryDtors(Child)) + B = R; } return B; } diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 3aa351527f..17dd772a68 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -433,42 +433,65 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, llvm::raw_svector_ostream os(sbuf); if (const PostStmt *PS = StoreSite->getLocationAs<PostStmt>()) { - if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { - - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { - os << "Variable '" << *VR->getDecl() << "' "; + const Stmt *S = PS->getStmt(); + const char *action = 0; + const DeclStmt *DS = dyn_cast<DeclStmt>(S); + const VarRegion *VR = dyn_cast<VarRegion>(R); + + if (DS) { + action = "initialized to "; + } else if (isa<BlockExpr>(S)) { + action = "captured by block as "; + if (VR) { + // See if we can get the BlockVarRegion. + ProgramStateRef State = StoreSite->getState(); + SVal V = State->getSVal(S, PS->getLocationContext()); + if (const BlockDataRegion *BDR = + dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { + if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) { + V = State->getSVal(OriginalR); + BR.addVisitor(new FindLastStoreBRVisitor(V, OriginalR)); + } + } } - else - return NULL; + } + + if (action) { + if (!R) + return 0; + + os << "Variable '" << *VR->getDecl() << "' "; if (isa<loc::ConcreteInt>(V)) { bool b = false; if (R->isBoundable()) { if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { if (TR->getValueType()->isObjCObjectPointerType()) { - os << "initialized to nil"; + os << action << "nil"; b = true; } } } if (!b) - os << "initialized to a null pointer value"; + os << action << "a null pointer value"; } else if (isa<nonloc::ConcreteInt>(V)) { - os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); + os << action << cast<nonloc::ConcreteInt>(V).getValue(); } - else if (V.isUndef()) { - if (isa<VarRegion>(R)) { - const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); - if (VD->getInit()) - os << "initialized to a garbage value"; - else - os << "declared without an initial value"; + else if (DS) { + if (V.isUndef()) { + if (isa<VarRegion>(R)) { + const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); + if (VD->getInit()) + os << "initialized to a garbage value"; + else + os << "declared without an initial value"; + } + } + else { + os << "initialized here"; } - } - else { - os << "initialized here"; } } } else if (isa<CallEnter>(StoreSite->getLocation())) { diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 70bb965859..687c7c0188 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -1302,3 +1302,13 @@ BlockDataRegion::referenced_vars_end() const { return BlockDataRegion::referenced_vars_iterator(Vec->end(), VecOriginal->end()); } + +const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const { + for (referenced_vars_iterator I = referenced_vars_begin(), + E = referenced_vars_end(); + I != E; ++I) { + if (I.getCapturedRegion() == R) + return I.getOriginalRegion(); + } + return 0; +} diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp index c8844754be..1ddccb704b 100644 --- a/test/Analysis/temp-obj-dtors-cfg-output.cpp +++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp @@ -207,22 +207,22 @@ TestCtorInits::TestCtorInits() // CHECK: 14: int a = int(A().operator int()) + int(B().operator int()); // CHECK: 15: ~B() (Temporary object destructor) // CHECK: 16: ~A() (Temporary object destructor) -// CHECK: 17: A() (CXXConstructExpr, class A) -// CHECK: 18: [B1.17] (BindTemporary) -// CHECK: 19: [B1.18].operator int -// CHECK: 20: [B1.19]() -// CHECK: 21: [B1.20] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 22: int([B1.21]) (CXXFunctionalCastExpr, NoOp, int) -// CHECK: 23: B() (CXXConstructExpr, class B) -// CHECK: 24: [B1.23] (BindTemporary) -// CHECK: 25: [B1.24].operator int -// CHECK: 26: [B1.25]() -// CHECK: 27: [B1.26] (ImplicitCastExpr, UserDefinedConversion, int) -// CHECK: 28: int([B1.27]) (CXXFunctionalCastExpr, NoOp, int) -// CHECK: 29: [B1.22] + [B1.28] -// CHECK: 30: foo -// CHECK: 31: [B1.30] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) -// CHECK: 32: [B1.31]([B1.29]) +// CHECK: 17: foo +// CHECK: 18: [B1.17] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) +// CHECK: 19: A() (CXXConstructExpr, class A) +// CHECK: 20: [B1.19] (BindTemporary) +// CHECK: 21: [B1.20].operator int +// CHECK: 22: [B1.21]() +// CHECK: 23: [B1.22] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 24: int([B1.23]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 25: B() (CXXConstructExpr, class B) +// CHECK: 26: [B1.25] (BindTemporary) +// CHECK: 27: [B1.26].operator int +// CHECK: 28: [B1.27]() +// CHECK: 29: [B1.28] (ImplicitCastExpr, UserDefinedConversion, int) +// CHECK: 30: int([B1.29]) (CXXFunctionalCastExpr, NoOp, int) +// CHECK: 31: [B1.24] + [B1.30] +// CHECK: 32: [B1.18]([B1.31]) // CHECK: 33: ~B() (Temporary object destructor) // CHECK: 34: ~A() (Temporary object destructor) // CHECK: 35: int b; @@ -242,11 +242,9 @@ TestCtorInits::TestCtorInits() // CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: [B5.6] && [B4.5] -// CHECK: 2: foo -// CHECK: 3: [B3.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) -// CHECK: 4: [B3.3]([B3.1]) -// CHECK: T: [B5.6] && ... +// CHECK: 1: [B5.8] && [B4.5] +// CHECK: 2: [B5.3]([B3.1]) +// CHECK: T: [B5.8] && ... // CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B2 B1 // CHECK: [B4] @@ -259,12 +257,14 @@ TestCtorInits::TestCtorInits() // CHECK: Succs (1): B3 // CHECK: [B5] // CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: A() (CXXConstructExpr, class A) -// CHECK: 3: [B5.2] (BindTemporary) -// CHECK: 4: [B5.3].operator _Bool -// CHECK: 5: [B5.4]() -// CHECK: 6: [B5.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B5.6] && ... +// CHECK: 2: foo +// CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) +// CHECK: 4: A() (CXXConstructExpr, class A) +// CHECK: 5: [B5.4] (BindTemporary) +// CHECK: 6: [B5.5].operator _Bool +// CHECK: 7: [B5.6]() +// CHECK: 8: [B5.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B5.8] && ... // CHECK: Preds (2): B6 B7 // CHECK: Succs (2): B4 B3 // CHECK: [B6] @@ -308,11 +308,9 @@ TestCtorInits::TestCtorInits() // CHECK: Preds (1): B3 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: [B5.6] || [B4.5] -// CHECK: 2: foo -// CHECK: 3: [B3.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) -// CHECK: 4: [B3.3]([B3.1]) -// CHECK: T: [B5.6] || ... +// CHECK: 1: [B5.8] || [B4.5] +// CHECK: 2: [B5.3]([B3.1]) +// CHECK: T: [B5.8] || ... // CHECK: Preds (2): B4 B5 // CHECK: Succs (2): B1 B2 // CHECK: [B4] @@ -325,12 +323,14 @@ TestCtorInits::TestCtorInits() // CHECK: Succs (1): B3 // CHECK: [B5] // CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: A() (CXXConstructExpr, class A) -// CHECK: 3: [B5.2] (BindTemporary) -// CHECK: 4: [B5.3].operator _Bool -// CHECK: 5: [B5.4]() -// CHECK: 6: [B5.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B5.6] || ... +// CHECK: 2: foo +// CHECK: 3: [B5.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(_Bool)) +// CHECK: 4: A() (CXXConstructExpr, class A) +// CHECK: 5: [B5.4] (BindTemporary) +// CHECK: 6: [B5.5].operator _Bool +// CHECK: 7: [B5.6]() +// CHECK: 8: [B5.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B5.8] || ... // CHECK: Preds (2): B6 B7 // CHECK: Succs (2): B3 B4 // CHECK: [B6] @@ -370,17 +370,17 @@ TestCtorInits::TestCtorInits() // CHECK: Preds (2): B2 B3 // CHECK: Succs (1): B0 // CHECK: [B2] -// CHECK: 1: 0 -// CHECK: 2: foo -// CHECK: 3: [B2.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) -// CHECK: 4: [B2.3]([B2.1]) +// CHECK: 1: foo +// CHECK: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) +// CHECK: 3: 0 +// CHECK: 4: [B2.2]([B2.3]) // CHECK: Preds (1): B4 // CHECK: Succs (1): B1 // CHECK: [B3] -// CHECK: 1: 0 -// CHECK: 2: foo -// CHECK: 3: [B3.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) -// CHECK: 4: [B3.3]([B3.1]) +// CHECK: 1: foo +// CHECK: 2: [B3.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int)) +// CHECK: 3: 0 +// CHECK: 4: [B3.2]([B3.3]) // CHECK: Preds (1): B4 // CHECK: Succs (1): B1 // CHECK: [B4] @@ -474,13 +474,11 @@ TestCtorInits::TestCtorInits() // CHECK: Preds (1): B4 // CHECK: Succs (1): B1 // CHECK: [B4] -// CHECK: 1: [B7.6] ? [B5.6] : [B6.15] +// CHECK: 1: [B7.8] ? [B5.6] : [B6.15] // CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B4.2] -// CHECK: 4: foo -// CHECK: 5: [B4.4] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) -// CHECK: 6: [B4.5]([B4.3]) -// CHECK: T: [B7.6] ? ... : ... +// CHECK: 4: [B7.3]([B4.3]) +// CHECK: T: [B7.8] ? ... : ... // CHECK: Preds (2): B5 B6 // CHECK: Succs (2): B2 B3 // CHECK: [B5] @@ -512,12 +510,14 @@ TestCtorInits::TestCtorInits() // CHECK: Succs (1): B4 // CHECK: [B7] // CHECK: 1: ~B() (Temporary object destructor) -// CHECK: 2: B() (CXXConstructExpr, class B) -// CHECK: 3: [B7.2] (BindTemporary) -// CHECK: 4: [B7.3].operator _Bool -// CHECK: 5: [B7.4]() -// CHECK: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B7.6] ? ... : ... +// CHECK: 2: foo +// CHECK: 3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 4: B() (CXXConstructExpr, class B) +// CHECK: 5: [B7.4] (BindTemporary) +// CHECK: 6: [B7.5].operator _Bool +// CHECK: 7: [B7.6]() +// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.8] ? ... : ... // CHECK: Preds (2): B8 B9 // CHECK: Succs (2): B5 B6 // CHECK: [B8] @@ -647,17 +647,15 @@ TestCtorInits::TestCtorInits() // CHECK: Preds (1): B4 // CHECK: Succs (1): B1 // CHECK: [B4] -// CHECK: 1: [B7.3] ?: [B6.6] +// CHECK: 1: [B7.5] ?: [B6.6] // CHECK: 2: [B4.1] (ImplicitCastExpr, NoOp, const class A) // CHECK: 3: [B4.2] -// CHECK: 4: foo -// CHECK: 5: [B4.4] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) -// CHECK: 6: [B4.5]([B4.3]) -// CHECK: T: [B7.6] ? ... : ... +// CHECK: 4: [B7.3]([B4.3]) +// CHECK: T: [B7.8] ? ... : ... // CHECK: Preds (2): B5 B6 // CHECK: Succs (2): B2 B3 // CHECK: [B5] -// CHECK: 1: [B7.3] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 1: [B7.5] (ImplicitCastExpr, NoOp, const class A) // CHECK: 2: [B5.1] // CHECK: 3: [B5.2] (CXXConstructExpr, class A) // CHECK: 4: [B5.3] (BindTemporary) @@ -674,12 +672,14 @@ TestCtorInits::TestCtorInits() // CHECK: Succs (1): B4 // CHECK: [B7] // CHECK: 1: ~A() (Temporary object destructor) -// CHECK: 2: A() (CXXConstructExpr, class A) -// CHECK: 3: [B7.2] (BindTemporary) -// CHECK: 4: [B7.3].operator _Bool -// CHECK: 5: [B7.4]() -// CHECK: 6: [B7.5] (ImplicitCastExpr, UserDefinedConversion, _Bool) -// CHECK: T: [B7.6] ? ... : ... +// CHECK: 2: foo +// CHECK: 3: [B7.2] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 4: A() (CXXConstructExpr, class A) +// CHECK: 5: [B7.4] (BindTemporary) +// CHECK: 6: [B7.5].operator _Bool +// CHECK: 7: [B7.6]() +// CHECK: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK: T: [B7.8] ? ... : ... // CHECK: Preds (2): B9 B8 // CHECK: Succs (2): B5 B6 // CHECK: [B8] @@ -745,13 +745,13 @@ TestCtorInits::TestCtorInits() // CHECK: 3: [B1.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B1.3] // CHECK: 5: const A &a = A(); -// CHECK: 6: A() (CXXConstructExpr, class A) -// CHECK: 7: [B1.6] (BindTemporary) -// CHECK: 8: [B1.7] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 9: [B1.8] -// CHECK: 10: foo -// CHECK: 11: [B1.10] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) -// CHECK: 12: [B1.11]([B1.9]) +// CHECK: 6: foo +// CHECK: 7: [B1.6] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 8: A() (CXXConstructExpr, class A) +// CHECK: 9: [B1.8] (BindTemporary) +// CHECK: 10: [B1.9] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 11: [B1.10] +// CHECK: 12: [B1.7]([B1.11]) // CHECK: 13: ~A() (Temporary object destructor) // CHECK: 14: int b; // CHECK: 15: [B1.5].~A() (Implicit destructor) @@ -787,15 +787,15 @@ TestCtorInits::TestCtorInits() // CHECK: 5: [B1.4] (ImplicitCastExpr, NoOp, const class A) // CHECK: 6: [B1.5] // CHECK: 7: const A &a = A::make(); -// CHECK: 8: A::make -// CHECK: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) -// CHECK: 10: [B1.9]() -// CHECK: 11: [B1.10] (BindTemporary) -// CHECK: 12: [B1.11] (ImplicitCastExpr, NoOp, const class A) -// CHECK: 13: [B1.12] -// CHECK: 14: foo -// CHECK: 15: [B1.14] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) -// CHECK: 16: [B1.15]([B1.13]) +// CHECK: 8: foo +// CHECK: 9: [B1.8] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class A &)) +// CHECK: 10: A::make +// CHECK: 11: [B1.10] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void)) +// CHECK: 12: [B1.11]() +// CHECK: 13: [B1.12] (BindTemporary) +// CHECK: 14: [B1.13] (ImplicitCastExpr, NoOp, const class A) +// CHECK: 15: [B1.14] +// CHECK: 16: [B1.9]([B1.15]) // CHECK: 17: ~A() (Temporary object destructor) // CHECK: 18: int b; // CHECK: 19: [B1.7].~A() (Implicit destructor) diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c index 9db5fa8256..fd9b22dae8 100644 --- a/test/Analysis/unix-fns.c +++ b/test/Analysis/unix-fns.c @@ -1418,12 +1418,12 @@ void test_inline_dispatch_once() { // CHECK-NEXT: <array> // CHECK-NEXT: <dict> // CHECK-NEXT: <key>line</key><integer>190</integer> -// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> // CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: </dict> // CHECK-NEXT: <dict> // CHECK-NEXT: <key>line</key><integer>190</integer> -// CHECK-NEXT: <key>col</key><integer>15</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> // CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: </dict> // CHECK-NEXT: </array> @@ -1435,6 +1435,35 @@ void test_inline_dispatch_once() { // CHECK-NEXT: <key>location</key> // CHECK-NEXT: <dict> // CHECK-NEXT: <key>line</key><integer>190</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <key>ranges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>190</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>194</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>depth</key><integer>0</integer> +// CHECK-NEXT: <key>extended_message</key> +// CHECK-NEXT: <string>Variable 'p' captured by block as a null pointer value</string> +// CHECK-NEXT: <key>message</key> +// CHECK-NEXT: <string>Variable 'p' captured by block as a null pointer value</string> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>event</string> +// CHECK-NEXT: <key>location</key> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>190</integer> // CHECK-NEXT: <key>col</key><integer>3</integer> // CHECK-NEXT: <key>file</key><integer>0</integer> // CHECK-NEXT: </dict> @@ -1739,6 +1768,69 @@ void test_inline_dispatch_once() { // CHECK-NEXT: <string>Variable 'p' initialized to a null pointer value</string> // CHECK-NEXT: </dict> // CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>200</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>200</integer> +// CHECK-NEXT: <key>col</key><integer>5</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>201</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>201</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>event</string> +// CHECK-NEXT: <key>location</key> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>201</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <key>ranges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>201</integer> +// CHECK-NEXT: <key>col</key><integer>24</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>203</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>depth</key><integer>0</integer> +// CHECK-NEXT: <key>extended_message</key> +// CHECK-NEXT: <string>Variable 'p' captured by block as a null pointer value</string> +// CHECK-NEXT: <key>message</key> +// CHECK-NEXT: <string>Variable 'p' captured by block as a null pointer value</string> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> // CHECK-NEXT: <key>kind</key><string>event</string> // CHECK-NEXT: <key>location</key> // CHECK-NEXT: <dict> diff --git a/test/Sema/warn-unreachable.c b/test/Sema/warn-unreachable.c index 2fbe1c78eb..fd74b5c871 100644 --- a/test/Sema/warn-unreachable.c +++ b/test/Sema/warn-unreachable.c @@ -80,8 +80,8 @@ void test2() { - // expected-warning {{will never be executed}} halt(); case 8: - i // expected-warning {{will never be executed}} - += + i + += // expected-warning {{will never be executed}} halt(); case 9: halt() @@ -93,8 +93,8 @@ void test2() { case 11: { int a[5]; live(), - a[halt() // expected-warning {{will never be executed}} - ]; + a[halt() + ]; // expected-warning {{will never be executed}} } } } |