Merge remote-tracking branch 'origin/swift-3.1-branch' into stable
* origin/swift-3.1-branch:
[Profile] Update testcase for r283948 (NFC)
[Coverage] Support for C++17 if initializers
[Coverage] Support for C++17 switch initializers
[ubsan] Disable bounds-check for flexible array ivars
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index e2943b3..a38dc22 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -708,6 +708,8 @@
DeclContext::decl_iterator(const_cast<FieldDecl *>(FD)));
return ++FI == FD->getParent()->field_end();
}
+ } else if (const auto *IRE = dyn_cast<ObjCIvarRefExpr>(E)) {
+ return IRE->getDecl()->getNextIvar() == nullptr;
}
return false;
diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp
index 4eefdd7..c6c3fa4 100644
--- a/lib/CodeGen/CodeGenPGO.cpp
+++ b/lib/CodeGen/CodeGenPGO.cpp
@@ -458,6 +458,8 @@
void VisitSwitchStmt(const SwitchStmt *S) {
RecordStmtCount(S);
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getCond());
CurrentCount = 0;
BreakContinueStack.push_back(BreakContinue());
@@ -488,6 +490,8 @@
void VisitIfStmt(const IfStmt *S) {
RecordStmtCount(S);
uint64_t ParentCount = CurrentCount;
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getCond());
// Counter tracks the "then" part of an if statement. The count for
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index 0e51658..66b70e0 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -813,6 +813,8 @@
void VisitSwitchStmt(const SwitchStmt *S) {
extendRegion(S);
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getCond());
BreakContinueStack.push_back(BreakContinue());
@@ -873,6 +875,9 @@
void VisitIfStmt(const IfStmt *S) {
extendRegion(S);
+ if (S->getInit())
+ Visit(S->getInit());
+
// Extend into the condition before we propagate through it below - this is
// needed to handle macros that generate the "if" but not the condition.
extendRegion(S->getCond());
diff --git a/test/CodeGenObjC/ubsan-array-bounds.m b/test/CodeGenObjC/ubsan-array-bounds.m
new file mode 100644
index 0000000..38d1eb3
--- /dev/null
+++ b/test/CodeGenObjC/ubsan-array-bounds.m
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -Wno-objc-root-class -fsanitize=array-bounds %s -o - | FileCheck %s
+
+@interface FlexibleArray1 {
+@public
+ char chars[0];
+}
+@end
+@implementation FlexibleArray1
+@end
+
+// CHECK-LABEL: test_FlexibleArray1
+char test_FlexibleArray1(FlexibleArray1 *FA1) {
+ // CHECK-NOT: !nosanitize
+ return FA1->chars[1];
+ // CHECK: }
+}
+
+@interface FlexibleArray2 {
+@public
+ char chars[0];
+}
+@end
+@implementation FlexibleArray2 {
+@public
+ char chars2[0];
+}
+@end
+
+// CHECK-LABEL: test_FlexibleArray2_1
+char test_FlexibleArray2_1(FlexibleArray2 *FA2) {
+ // CHECK: !nosanitize
+ return FA2->chars[1];
+ // CHECK: }
+}
+
+// CHECK-LABEL: test_FlexibleArray2_2
+char test_FlexibleArray2_2(FlexibleArray2 *FA2) {
+ // CHECK-NOT: !nosanitize
+ return FA2->chars2[1];
+ // CHECK: }
+}
+
+@interface FlexibleArray3 {
+@public
+ char chars[0];
+}
+@end
+@implementation FlexibleArray3 {
+@public
+ int i;
+}
+@end
+
+// CHECK-LABEL: test_FlexibleArray3
+char test_FlexibleArray3(FlexibleArray3 *FA3) {
+ // CHECK: !nosanitize
+ return FA3->chars[1];
+ // CHECK: }
+}
diff --git a/test/CoverageMapping/if.c b/test/CoverageMapping/if.cpp
similarity index 70%
rename from test/CoverageMapping/if.c
rename to test/CoverageMapping/if.cpp
index 69544f6..95e6d8a 100644
--- a/test/CoverageMapping/if.c
+++ b/test/CoverageMapping/if.cpp
@@ -1,5 +1,16 @@
-// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name if.c %s | FileCheck %s
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++1z -triple %itanium_abi_triple -main-file-name if.cpp %s | FileCheck %s
+int nop() { return 0; }
+
+// CHECK-LABEL: _Z3foov:
+void foo() { // CHECK-NEXT: [[@LINE]]:12 -> [[@LINE+5]]:2 = #0
+ if (int j = true ? nop() // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = #2
+ : nop(); // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = (#0 - #2)
+ j) // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:8 = #0
+ ++j; // CHECK-NEXT: [[@LINE]]:5 -> [[@LINE]]:8 = #1
+}
+
+// CHECK-LABEL: main:
int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = #0
int i = 0;
// CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #0
diff --git a/test/CoverageMapping/switch.c b/test/CoverageMapping/switch.cpp
similarity index 81%
rename from test/CoverageMapping/switch.c
rename to test/CoverageMapping/switch.cpp
index 9463eb3..312f26c 100644
--- a/test/CoverageMapping/switch.c
+++ b/test/CoverageMapping/switch.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name switch.c %s | FileCheck %s
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++1z -triple %itanium_abi_triple -main-file-name switch.cpp %s | FileCheck %s
+
// CHECK: foo
void foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+8]]:2 = #0
switch(i) {
@@ -10,7 +11,7 @@
int x = 0; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #1
}
-void nop() {}
+int nop() { return 0; }
// CHECK: bar
void bar(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+20]]:2 = #0
@@ -35,8 +36,16 @@
nop(); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #6
}
+ // CHECK: baz
+void baz() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+5]]:2 = #0
+ switch (int i = true ? nop() // CHECK-NEXT: [[@LINE]]:26 -> [[@LINE]]:31 = #2
+ : nop(); // CHECK-NEXT: [[@LINE]]:26 -> [[@LINE]]:31 = (#0 - #2)
+ i) {}
+ nop(); // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:2 = #1
+}
+
// CHECK-NEXT: main
-int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+34]]:2 = #0
+int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+35]]:2 = #0
int i = 0;
switch(i) {
case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+7]]:10 = #2
@@ -48,7 +57,7 @@
default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #4
break;
}
- switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+22]]:2 = #1
+ switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+23]]:2 = #1
case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+6]]:10 = #6
i = 1;
break;
@@ -58,7 +67,7 @@
break;
}
- switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+12]]:2 = #5
+ switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+13]]:2 = #5
case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:11 = #10
case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:11 = (#10 + #11)
i = 11;
@@ -67,7 +76,8 @@
i = 99;
}
- foo(1); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:11 = #9
+ foo(1); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:11 = #9
bar(1);
+ baz();
return 0;
}
diff --git a/test/Profile/c-linkage-available_externally.c b/test/Profile/c-linkage-available_externally.c
index 8907839..5ac777b 100644
--- a/test/Profile/c-linkage-available_externally.c
+++ b/test/Profile/c-linkage-available_externally.c
@@ -3,7 +3,7 @@
// RUN: %clang_cc1 -O2 -triple x86_64-apple-macosx10.9 -main-file-name c-linkage-available_externally.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck %s
// CHECK: @__profc_foo = linkonce_odr hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
-// CHECK: @__profd_foo = linkonce_odr hidden global {{.*}} i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_foo, i32 0, i32 0){{.*}}, section "__DATA,__llvm_prf_data", align 8
+// CHECK: @__profd_foo = linkonce_odr hidden global {{.*}} i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_foo, i32 0, i32 0){{.*}}, section "__DATA,__llvm_prf_data,regular,live_support", align 8
inline int foo(void) { return 1; }
int main(void) {
diff --git a/test/Profile/cxx-stmt-initializers.cpp b/test/Profile/cxx-stmt-initializers.cpp
new file mode 100644
index 0000000..44f7edd
--- /dev/null
+++ b/test/Profile/cxx-stmt-initializers.cpp
@@ -0,0 +1,29 @@
+// Tests for instrumentation of C++17 statement initializers
+
+// RUN: %clang_cc1 -x c++ %s -triple %itanium_abi_triple -main-file-name cxx-stmt-initializers.cpp -std=c++1z -o - -emit-llvm -fprofile-instrument=clang > %tgen
+// RUN: FileCheck --input-file=%tgen -check-prefix=CHECK -check-prefix=PGOGEN %s
+
+// PGOGEN: @[[SIC:__profc__Z11switch_initv]] = private global [3 x i64] zeroinitializer
+// PGOGEN: @[[IIC:__profc__Z7if_initv]] = private global [3 x i64] zeroinitializer
+
+// Note: We expect counters for the function entry block, the condition in the
+// switch initializer, and the switch successor block.
+//
+// CHECK-LABEL: define {{.*}}void @_Z11switch_initv()
+// PGOGEN: store {{.*}} @[[SIC]], i64 0, i64 0
+void switch_init() {
+ switch (int i = true ? 0 : 1; i) {}
+ // PGOGEN: store {{.*}} @[[SIC]], i64 0, i64 2
+ // PGOGEN: store {{.*}} @[[SIC]], i64 0, i64 1
+}
+
+// Note: We expect counters for the function entry block, the condition in the
+// if initializer, and the if successor block.
+//
+// CHECK-LABEL: define {{.*}}void @_Z7if_initv()
+// PGOGEN: store {{.*}} @[[IIC]], i64 0, i64 0
+void if_init() {
+ if (int i = true ? 0 : 1; i) {}
+ // PGOGEN: store {{.*}} @[[IIC]], i64 0, i64 2
+ // PGOGEN: store {{.*}} @[[IIC]], i64 0, i64 1
+}