diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-10 01:32:12 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-10 01:32:12 +0000 |
commit | 7bdcc4a9da8ccbafb15872083f551366cdaf3b51 (patch) | |
tree | bb52354737aeaa0e413fe20cb96e321ba9e47aac /clang/test | |
parent | 076b3041c0706a957766f7e5e885f05b2eaf255e (diff) | |
download | bcm5719-llvm-7bdcc4a9da8ccbafb15872083f551366cdaf3b51.tar.gz bcm5719-llvm-7bdcc4a9da8ccbafb15872083f551366cdaf3b51.zip |
Disambiguation of '[[':
* In C++11, '[[' is ill-formed unless it starts an attribute-specifier. Reject
array sizes and array indexes which begin with a lambda-expression. Recover by
parsing the lambda as a lambda.
* In Objective-C++11, either '[' could be the start of a message-send.
Fully disambiguate this case: it turns out that the grammars of message-sends,
lambdas and attributes do not actually overlap. Accept any occurrence of '[['
where either '[' starts a message send, but reject a lambda in an array index
just like in C++11 mode.
Implement a couple of changes to the attribute wording which occurred after our
attributes implementation landed:
* In a function-declaration, the attributes go after the exception specification,
not after the right paren.
* A reference type can have attributes applied.
* An 'identifier' in an attribute can also be a keyword. Support for alternative
tokens (iso646 keywords) in attributes to follow.
And some bug fixes:
* Parse attributes after declarator-ids, even if they are not simple identifiers.
* Do not accept attributes after a parenthesized declarator.
* Accept attributes after an array size in a new-type-id.
* Partially disamiguate 'delete' followed by a lambda. More work is required
here for the case where the lambda-introducer is '[]'.
llvm-svn: 154369
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp | 13 | ||||
-rw-r--r-- | clang/test/Parser/cxx0x-attributes.cpp | 15 | ||||
-rw-r--r-- | clang/test/Parser/objcxx11-attributes.mm | 42 | ||||
-rw-r--r-- | clang/test/SemaCXX/new-delete-0x.cpp | 32 | ||||
-rw-r--r-- | clang/test/SemaCXX/new-delete.cpp | 3 |
5 files changed, 100 insertions, 5 deletions
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp new file mode 100644 index 00000000000..f9702ba7ccb --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace std_example { + +int p[10]; +void f() { + int x = 42, y[5]; + // FIXME: Produce a better diagnostic for this case. + int(p[[x] { return x; }()]); // expected-error {{expected ']'}} + y[[] { return 2; }()] = 2; // expected-error {{consecutive left square brackets}} +} + +} diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index 198da778cd0..b20873509b6 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -5,11 +5,17 @@ int [[]] between_attr; int after_attr [[]]; int * [[]] ptr_attr; +int & [[]] ref_attr = after_attr; +int && [[]] rref_attr = 0; int array_attr [1] [[]]; alignas(8) int aligned_attr; [[test::valid(for 42 [very] **** '+' symbols went on a trip; the end.)]] int garbage_attr; void fn_attr () [[]]; +void noexcept_fn_attr () noexcept [[]]; +struct MemberFnOrder { + virtual void f() const volatile && noexcept [[]] final = 0; +}; class [[]] class_attr {}; extern "C++" [[]] int extern_attr; template <typename T> [[]] void template_attr (); @@ -17,10 +23,10 @@ template <typename T> [[]] void template_attr (); int comma_attr [[,]]; // expected-error {{expected identifier}} int scope_attr [[foo::]]; // expected-error {{expected identifier}} +int (paren_attr) [[]]; // expected-error {{an attribute list cannot appear here}} unsigned [[]] int attr_in_decl_spec; // expected-error {{expected unqualified-id}} -int & [[]] ref_attr = after_attr; // expected-error {{an attribute list cannot appear here}} class foo { - void after_const_attr () const [[]]; // expected-error {{expected body of lambda expression}} + void const_after_attr () [[]] const; // expected-error {{expected ';'}} }; extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}} [[]] template <typename T> void before_template_attr (); // expected-error {{an attribute list cannot appear here}} @@ -58,6 +64,9 @@ void foo () { [[]] try { } [[]] catch (...) { // expected-error {{an attribute list cannot appear here}} } - + struct S { int arr[2]; } s; + (void)s.arr[ [] { return 0; }() ]; // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} + int n = __builtin_offsetof(S, arr[ [] { return 0; }() ]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} + [[]] return; } diff --git a/clang/test/Parser/objcxx11-attributes.mm b/clang/test/Parser/objcxx11-attributes.mm new file mode 100644 index 00000000000..719cdcc32f4 --- /dev/null +++ b/clang/test/Parser/objcxx11-attributes.mm @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +@interface X {} ++ (X*) alloc; +- (X*) init; +- (int) getSize; +- (void) setSize: (int) size; +- (X*) getSelf; +@end + +void f(X *noreturn) { + // An array size which is computed by a message send is OK. + int a[ [noreturn getSize] ]; + + // ... but is interpreted as an attribute where possible. + int b[ [noreturn] ]; // expected-warning {{'noreturn' only applies to function types}} + + int c[ [noreturn getSize] + 1 ]; + + // An array size which is computed by a lambda is not OK. + int d[ [noreturn] { return 3; } () ]; // expected-error {{expected ']'}} expected-warning {{'noreturn' only applies}} + + // A message send which contains a message send is OK. + [ [ X alloc ] init ]; + [ [ int(), noreturn getSelf ] getSize ]; // expected-warning {{unused}} + + // A message send which contains a lambda is OK. + [ [noreturn] { return noreturn; } () setSize: 4 ]; + [ [bitand] { return noreturn; } () setSize: 5 ]; + [[[[] { return [ X alloc ]; } () init] getSelf] getSize]; + + // An attribute is OK. + [[]]; + [[int(), noreturn]]; + [[class, test(foo 'x' bar),,,]]; +} + +template<typename...Ts> void f(Ts ...x) { + [[test::foo(bar, baz)...]]; + [[used(x)...]]; + [[x...] { return [ X alloc ]; }() init]; +} diff --git a/clang/test/SemaCXX/new-delete-0x.cpp b/clang/test/SemaCXX/new-delete-0x.cpp new file mode 100644 index 00000000000..dcc2e9b8b12 --- /dev/null +++ b/clang/test/SemaCXX/new-delete-0x.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -triple=i686-pc-linux-gnu -std=c++11 + +using size_t = decltype(sizeof(0)); +struct noreturn_t {} constexpr noreturn = {}; + +void *operator new [[noreturn]] (size_t, noreturn_t); +void operator delete [[noreturn]] (void*, noreturn_t); + +void good_news() +{ + auto p = new int[2][[]]; + auto q = new int[[]][2]; + auto r = new int*[[]][2][[]]; + auto s = new (int(*[[]])[2][[]]); +} + +void bad_news(int *ip) +{ + // attribute-specifiers can go almost anywhere in a new-type-id... + auto r = new int[[]{return 1;}()][2]; // expected-error {{expected ']'}} + auto s = new int*[[]{return 1;}()][2]; // expected-error {{expected ']'}} + // ... but not here: + auto t = new (int(*)[[]]); // expected-error {{an attribute list cannot appear here}} + auto u = new (int(*)[[]{return 1;}()][2]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} expected-error {{variably modified type}} +} + +void good_deletes() +{ + delete [&]{ return (int*)0; }(); + // FIXME: This appears to be legal. + delete []{ return (int*)0; }(); // unexpected-error {{expected expression}} +} diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp index 88d85ca792e..e77e3d652f4 100644 --- a/clang/test/SemaCXX/new-delete.cpp +++ b/clang/test/SemaCXX/new-delete.cpp @@ -102,8 +102,7 @@ void good_deletes() void bad_deletes() { delete 0; // expected-error {{cannot delete expression of type 'int'}} - delete [0] (int*)0; // expected-error {{expected ']'}} \ - // expected-note {{to match this '['}} + delete [0] (int*)0; // expected-error {{expected expression}} delete (void*)0; // expected-warning {{cannot delete expression with pointer-to-'void' type 'void *'}} delete (T*)0; // expected-warning {{deleting pointer to incomplete type}} ::S::delete (int*)0; // expected-error {{expected unqualified-id}} |