diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-09-28 18:44:09 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-09-28 18:44:09 +0000 |
| commit | 8baa50013c86c34a58d8327c5d1a043898b86398 (patch) | |
| tree | c3e17acda6afd5e69242ee9dd6d330796f1c3670 /clang/test | |
| parent | 8e90bad63d3a448ed680616b393a47d25280fd87 (diff) | |
| download | bcm5719-llvm-8baa50013c86c34a58d8327c5d1a043898b86398.tar.gz bcm5719-llvm-8baa50013c86c34a58d8327c5d1a043898b86398.zip | |
[cxx2a] P0614R1: Support init-statements in range-based for loops.
We don't yet support this for the case where a range-based for loop is
implicitly rewritten to an ObjC for..in statement.
llvm-svn: 343350
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist | 281 | ||||
| -rw-r--r-- | clang/test/Analysis/cxx-for-range.cpp | 5 | ||||
| -rw-r--r-- | clang/test/Analysis/scopes-cfg-output.cpp | 5 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/cxx2a-init-statement.cpp | 10 | ||||
| -rw-r--r-- | clang/test/Import/cxx-for-range/Inputs/F.cpp | 3 | ||||
| -rw-r--r-- | clang/test/Import/cxx-for-range/test.cpp | 5 | ||||
| -rw-r--r-- | clang/test/PCH/cxx2a-for-init-statement.cpp | 8 | ||||
| -rw-r--r-- | clang/test/Parser/cxx2a-init-statement.cpp | 34 | ||||
| -rw-r--r-- | clang/test/SemaCXX/constant-expression-cxx2a.cpp | 7 | ||||
| -rw-r--r-- | clang/test/SemaCXX/cxx17-compat.cpp | 9 | ||||
| -rw-r--r-- | clang/test/SemaObjCXX/foreach.mm | 8 |
11 files changed, 370 insertions, 5 deletions
diff --git a/clang/test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist b/clang/test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist index 040c66a1790..9afb8055793 100644 --- a/clang/test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist +++ b/clang/test/Analysis/Inputs/expected-plists/cxx-for-range.cpp.plist @@ -1670,6 +1670,287 @@ </array> </dict> </dict> + <dict> + <key>path</key> + <array> + <dict> + <key>kind</key><string>control</string> + <key>edges</key> + <array> + <dict> + <key>start</key> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>3</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>5</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + <key>end</key> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>8</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>10</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + </dict> + </array> + </dict> + <dict> + <key>kind</key><string>event</string> + <key>location</key> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>8</integer> + <key>file</key><integer>0</integer> + </dict> + <key>ranges</key> + <array> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>8</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>15</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + </array> + <key>depth</key><integer>0</integer> + <key>extended_message</key> + <string>Initializing to a null pointer value</string> + <key>message</key> + <string>Initializing to a null pointer value</string> + </dict> + <dict> + <key>kind</key><string>control</string> + <key>edges</key> + <array> + <dict> + <key>start</key> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>8</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>10</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + <key>end</key> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>58</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>58</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + </dict> + </array> + </dict> + <dict> + <key>kind</key><string>event</string> + <key>location</key> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>58</integer> + <key>file</key><integer>0</integer> + </dict> + <key>ranges</key> + <array> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>58</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>58</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + </array> + <key>depth</key><integer>0</integer> + <key>extended_message</key> + <string>Entering loop body</string> + <key>message</key> + <string>Entering loop body</string> + </dict> + <dict> + <key>kind</key><string>control</string> + <key>edges</key> + <array> + <dict> + <key>start</key> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>58</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>58</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + <key>end</key> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>51</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>53</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + </dict> + </array> + </dict> + <dict> + <key>kind</key><string>event</string> + <key>location</key> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>51</integer> + <key>file</key><integer>0</integer> + </dict> + <key>ranges</key> + <array> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>51</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>56</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + </array> + <key>depth</key><integer>0</integer> + <key>extended_message</key> + <string>'p' initialized to a null pointer value</string> + <key>message</key> + <string>'p' initialized to a null pointer value</string> + </dict> + <dict> + <key>kind</key><string>control</string> + <key>edges</key> + <array> + <dict> + <key>start</key> + <array> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>51</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>102</integer> + <key>col</key><integer>53</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + <key>end</key> + <array> + <dict> + <key>line</key><integer>103</integer> + <key>col</key><integer>8</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>103</integer> + <key>col</key><integer>8</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + </dict> + </array> + </dict> + <dict> + <key>kind</key><string>event</string> + <key>location</key> + <dict> + <key>line</key><integer>103</integer> + <key>col</key><integer>8</integer> + <key>file</key><integer>0</integer> + </dict> + <key>ranges</key> + <array> + <array> + <dict> + <key>line</key><integer>103</integer> + <key>col</key><integer>6</integer> + <key>file</key><integer>0</integer> + </dict> + <dict> + <key>line</key><integer>103</integer> + <key>col</key><integer>6</integer> + <key>file</key><integer>0</integer> + </dict> + </array> + </array> + <key>depth</key><integer>0</integer> + <key>extended_message</key> + <string>Dereference of null pointer (loaded from variable 'p')</string> + <key>message</key> + <string>Dereference of null pointer (loaded from variable 'p')</string> + </dict> + </array> + <key>description</key><string>Dereference of null pointer (loaded from variable 'p')</string> + <key>category</key><string>Logic error</string> + <key>type</key><string>Dereference of null pointer</string> + <key>check_name</key><string>core.NullDereference</string> + <!-- This hash is experimental and going to change! --> + <key>issue_hash_content_of_line_in_context</key><string>ad377f8d4510dfd77d6485c402d57a2d</string> + <key>issue_context_kind</key><string>function</string> + <key>issue_context</key><string>testForRangeInit</string> + <key>issue_hash_function_offset</key><string>2</string> + <key>location</key> + <dict> + <key>line</key><integer>103</integer> + <key>col</key><integer>8</integer> + <key>file</key><integer>0</integer> + </dict> + <key>ExecutedLines</key> + <dict> + <key>0</key> + <array> + <integer>101</integer> + <integer>102</integer> + <integer>103</integer> + </array> + </dict> + </dict> </array> <key>files</key> <array> diff --git a/clang/test/Analysis/cxx-for-range.cpp b/clang/test/Analysis/cxx-for-range.cpp index d9ea1c12c27..8bcad89b6d9 100644 --- a/clang/test/Analysis/cxx-for-range.cpp +++ b/clang/test/Analysis/cxx-for-range.cpp @@ -97,3 +97,8 @@ void testLoopErrorInRange() { *(volatile int *)0 = 1; // no-warning } + +void testForRangeInit() { + for (int *arr[3] = {nullptr, nullptr, nullptr}; int *p : arr) // expected-warning {{extension}} + *p = 1; // expected-warning {{Dereference of null pointer}} +} diff --git a/clang/test/Analysis/scopes-cfg-output.cpp b/clang/test/Analysis/scopes-cfg-output.cpp index 0f2201abb09..f8d84b60deb 100644 --- a/clang/test/Analysis/scopes-cfg-output.cpp +++ b/clang/test/Analysis/scopes-cfg-output.cpp @@ -820,10 +820,9 @@ void test_for_compound_and_break() { // CHECK-NEXT: 3: __end1 // CHECK-NEXT: 4: [B2.3] (ImplicitCastExpr, LValueToRValue, class A *) // CHECK-NEXT: 5: [B2.2] != [B2.4] -// CHECK-NEXT: T: for (auto &i : [B5.4]) { +// CHECK-NEXT: T: for (auto &i : [B5.4]) // CHECK: [B4.11]; -// CHECK-NEXT:} -// CHECK-NEXT: Preds (2): B3 B5 +// CHECK: Preds (2): B3 B5 // CHECK-NEXT: Succs (2): B4 B1 // CHECK: [B3] // CHECK-NEXT: 1: __begin1 diff --git a/clang/test/CodeGenCXX/cxx2a-init-statement.cpp b/clang/test/CodeGenCXX/cxx2a-init-statement.cpp new file mode 100644 index 00000000000..eb48d4a1782 --- /dev/null +++ b/clang/test/CodeGenCXX/cxx2a-init-statement.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++2a -triple x86_64-apple-macosx10.7.0 -emit-llvm -o - %s -w | FileCheck %s + +// CHECK: @_ZZ1fvE3arr = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 + +void f() { + // CHECK: %[[ARR:.*]] = alloca [3 x i32], align 4 + // CHECK: call void @llvm.memcpy{{.*}}({{.*}} @_ZZ1fvE3arr + for (int arr[3] = {1, 2, 3}; int a : arr) + ; +} diff --git a/clang/test/Import/cxx-for-range/Inputs/F.cpp b/clang/test/Import/cxx-for-range/Inputs/F.cpp index 700feb01224..26a3a4e1d3f 100644 --- a/clang/test/Import/cxx-for-range/Inputs/F.cpp +++ b/clang/test/Import/cxx-for-range/Inputs/F.cpp @@ -4,8 +4,7 @@ struct Container { }; void f() { - Container c; - for (int varname : c) { + for (Container c; int varname : c) { return; } } diff --git a/clang/test/Import/cxx-for-range/test.cpp b/clang/test/Import/cxx-for-range/test.cpp index 1c9d40cf881..019fc20bee1 100644 --- a/clang/test/Import/cxx-for-range/test.cpp +++ b/clang/test/Import/cxx-for-range/test.cpp @@ -4,6 +4,11 @@ // CHECK-NEXT: DeclStmt // CHECK-NEXT: VarDecl +// CHECK-SAME: c 'Container' +// CHECK-NEXT: CXXConstructExpr + +// CHECK-NEXT: DeclStmt +// CHECK-NEXT: VarDecl // CHECK-NEXT: DeclRefExpr // CHECK-SAME: 'c' // CHECK-SAME: Container diff --git a/clang/test/PCH/cxx2a-for-init-statement.cpp b/clang/test/PCH/cxx2a-for-init-statement.cpp new file mode 100644 index 00000000000..2147c0f8a2a --- /dev/null +++ b/clang/test/PCH/cxx2a-for-init-statement.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -emit-pch -std=c++2a -o %t %s +// RUN: %clang_cc1 -std=c++2a -x ast -ast-print %t | FileCheck %s + +void f() { + // CHECK: for (int arr[3]; int n : arr) { + // CHECK-NEXT: } + for (int arr[3]; int n : arr) {} +} diff --git a/clang/test/Parser/cxx2a-init-statement.cpp b/clang/test/Parser/cxx2a-init-statement.cpp new file mode 100644 index 00000000000..3b1862f1d3c --- /dev/null +++ b/clang/test/Parser/cxx2a-init-statement.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +template<int N> struct A {}; + +using F = bool(*)(int); +extern F *p; +extern int m; + +struct Convertible { template<typename T> operator T(); }; + +void f() { + int arr1[3]; + for (int n = 5; int x : arr1) {} + + int A<0>::*arr2[3]; + for (int n = 5; int A<true ? 0 : 1>::*x : arr2) {} + + F (*arr3[3])(int); + for (int n = 5; F (*p)(int n) : arr3) {} + for (int n = 5; F (*p)(int (n)) : arr3) {} + + // Here, we have a declaration rather than an expression. + for (int n = 5; F (*p)(int (n)); ++n) {} + + // We detect whether we have a for-range-declaration before parsing so that + // we can give different diagnostics for for-range-declarations versus + // conditions (even though the rules are currently identical). + Convertible arr4[3]; + for (int n = 0; struct { operator bool(); } x = {}; ++n) {} // expected-error {{cannot be defined in a condition}} + for (int n = 0; struct { operator bool(); } x : arr4) {} // expected-error {{may not be defined in a for range declaration}} + + for (int n = 0; static int m = 0; ++n) {} // expected-error {{type name does not allow storage class}} + for (int n = 0; static int m : arr1) {} // expected-error {{loop variable 'm' may not be declared 'static'}} +} diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 18c4a726fd0..bb2a4a07dd8 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -204,3 +204,10 @@ static_assert(complex_test(makeComplex<_Complex int>(0, 0), std::strong_equality::nonequal)); // TODO: defaulted operator <=> } // namespace ThreeWayComparison + +constexpr bool for_range_init() { + int k = 0; + for (int arr[3] = {1, 2, 3}; int n : arr) k += n; + return k == 6; +} +static_assert(for_range_init()); diff --git a/clang/test/SemaCXX/cxx17-compat.cpp b/clang/test/SemaCXX/cxx17-compat.cpp index 93e052fe7e7..eee9c239d18 100644 --- a/clang/test/SemaCXX/cxx17-compat.cpp +++ b/clang/test/SemaCXX/cxx17-compat.cpp @@ -54,3 +54,12 @@ struct DefaultDeleteWrongType : DefaultDeleteWrongTypeBase { // expected-warning@-4 {{explicitly defaulting this copy constructor with a type different from the implicit type is incompatible with C++ standards before C++2a}} #endif }; + +void ForRangeInit() { + for (int arr[3] = {1, 2, 3}; int n : arr) {} +#if __cplusplus <= 201703L + // expected-warning@-2 {{range-based for loop initialization statements are a C++2a extension}} +#else + // expected-warning@-4 {{range-based for loop initialization statements are incompatible with C++ standards before C++2a}} +#endif +} diff --git a/clang/test/SemaObjCXX/foreach.mm b/clang/test/SemaObjCXX/foreach.mm index 99f5d0ce55e..e39815d3e9c 100644 --- a/clang/test/SemaObjCXX/foreach.mm +++ b/clang/test/SemaObjCXX/foreach.mm @@ -14,6 +14,14 @@ void f(NSArray *a) { for (auto thisKey : keys) { } // expected-warning{{'auto' deduced as 'id' in declaration of 'thisKey'}} } +void for_init_stmt() { + for (id keys; id key : keys) {} // expected-warning{{extension}} expected-error{{not supported}} +} +template<typename T> void for_init_stmt_tmpl() { + for (T keys; id key : keys) {} // expected-warning{{extension}} expected-error{{not supported}} +} +template void for_init_stmt_tmpl<id>(); // expected-note {{in instantiation of}} + template<typename Collection> void ft(Collection col) { for (id x : col) { } |

