1// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core -fblocks -analyzer-opt-analyze-nested-blocks -verify -x objective-c++ %s 2// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-config cfg-rich-constructors=false %s > %t 2>&1 3// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s 4// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,debug.DumpCFG -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-config cfg-rich-constructors=true %s > %t 2>&1 5// RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s 6 7// This file tests how we construct two different flavors of the Clang CFG - 8// the CFG used by the Sema analysis-based warnings and the CFG used by the 9// static analyzer. The difference in the behavior is checked via FileCheck 10// prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer 11// flags, no new run lines should be added - just these flags would go to the 12// respective line depending on where is it turned on and where is it turned 13// off. Feel free to add tests that test only one of the CFG flavors if you're 14// not sure how the other flavor is supposed to work in your case. 15 16// expected-no-diagnostics 17 18void testBlockWithoutCopyExpression(int i) { 19 // Captures i, with no copy expression. 20 (void)(^void() { 21 (void)i; 22 }); 23} 24 25// CHECK-LABEL:void testBlockWithoutCopyExpression(int i) 26// CHECK-NEXT: [B2 (ENTRY)] 27// CHECK-NEXT: Succs (1): B1 28 29// CHECK: [B1] 30// CHECK-NEXT: 1: ^{ } 31// CHECK-NEXT: 2: (void)([B1.1]) (CStyleCastExpr, ToVoid, void) 32// CHECK-NEXT: Preds (1): B2 33// CHECK-NEXT: Succs (1): B0 34 35// CHECK: [B0 (EXIT)] 36// CHECK-NEXT: Preds (1): B1 37 38struct StructWithCopyConstructor { 39 StructWithCopyConstructor(int i); 40 StructWithCopyConstructor(const StructWithCopyConstructor &s); 41}; 42void testBlockWithCopyExpression(StructWithCopyConstructor s) { 43 // Captures s, with a copy expression calling the copy constructor for StructWithCopyConstructor. 44 (void)(^void() { 45 (void)s; 46 }); 47} 48 49// CHECK-LABEL:void testBlockWithCopyExpression(StructWithCopyConstructor s) 50// CHECK-NEXT: [B2 (ENTRY)] 51// CHECK-NEXT: Succs (1): B1 52 53// CHECK: [B1] 54// CHECK-NEXT: 1: s 55// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NoOp, const struct StructWithCopyConstructor) 56// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, const struct StructWithCopyConstructor) 57// CHECK-NEXT: 4: ^{ } 58// CHECK-NEXT: 5: (void)([B1.4]) (CStyleCastExpr, ToVoid, void) 59// CHECK-NEXT: Preds (1): B2 60// CHECK-NEXT: Succs (1): B0 61 62// CHECK: [B0 (EXIT)] 63// CHECK-NEXT: Preds (1): B1 64 65void testBlockWithCaptureByReference() { 66 __block StructWithCopyConstructor s(5); 67 // Captures s by reference, so no copy expression. 68 (void)(^void() { 69 (void)s; 70 }); 71} 72 73// CHECK-LABEL:void testBlockWithCaptureByReference() 74// CHECK-NEXT: [B2 (ENTRY)] 75// CHECK-NEXT: Succs (1): B1 76 77// CHECK: [B1] 78// CHECK-NEXT: 1: 5 79// WARNINGS-NEXT: 2: [B1.1] (CXXConstructExpr, struct StructWithCopyConstructor) 80// ANALYZER-NEXT: 2: [B1.1] (CXXConstructExpr, [B1.3], struct StructWithCopyConstructor) 81// CHECK-NEXT: 3: StructWithCopyConstructor s(5) __attribute__((blocks("byref"))); 82// CHECK-NEXT: 4: ^{ } 83// CHECK-NEXT: 5: (void)([B1.4]) (CStyleCastExpr, ToVoid, void) 84// CHECK-NEXT: Preds (1): B2 85// CHECK-NEXT: Succs (1): B0 86 87// CHECK: [B0 (EXIT)] 88// CHECK-NEXT: Preds (1): B1 89