diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-07-23 18:59:35 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-07-23 18:59:35 +0000 |
commit | 38b2d3fa3e49a50ba228f00b718f54203eedf08b (patch) | |
tree | f3ded88e524bff8798ba8616f3748f2acfeb6683 /clang/test/SemaCXX/explicit.cpp | |
parent | 57132e88b7c3c8a4b2df063b92607e46c46dc846 (diff) | |
download | bcm5719-llvm-38b2d3fa3e49a50ba228f00b718f54203eedf08b.tar.gz bcm5719-llvm-38b2d3fa3e49a50ba228f00b718f54203eedf08b.zip |
Tests for explicit conversion operators, along with a fix to avoid
considering explicit conversion operators when determining surrogate
functions. Fixes PR10453. Note that there are a few test cases where
Clang is still wrong because it does not implement DR899; see PR10456.
Patch by Jonathan Sauer!
llvm-svn: 135857
Diffstat (limited to 'clang/test/SemaCXX/explicit.cpp')
-rw-r--r-- | clang/test/SemaCXX/explicit.cpp | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/explicit.cpp b/clang/test/SemaCXX/explicit.cpp index 717ed1e3caf..71680d4dde4 100644 --- a/clang/test/SemaCXX/explicit.cpp +++ b/clang/test/SemaCXX/explicit.cpp @@ -36,4 +36,144 @@ namespace Conversion { void f(A a, B b) { b.f(a); } + + void testExplicit() + { + // Taken from 12.3.2p2 + class Y { }; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \ + expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \ + expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \ + expected-note {{andidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} \ + expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \ + expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} \ + expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \ + expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} + struct Z { + explicit operator Y() const; + explicit operator int() const; + }; + + Z z; + // 13.3.1.4p1 & 8.5p16: + Y y2 = z; // expected-error {{no viable conversion from 'Conversion::Z' to 'Conversion::Y'}} + // FIXME: These are well-formed per C++0x 13.3.1.4p1 (see DR899). + Y y3 = (Y)z; // expected-error {{no matching conversion for C-style cast from 'Conversion::Z' to 'Conversion::Y''}} + Y y4 = Y(z); // expected-error {{no matching conversion for functional-style cast from 'Conversion::Z' to 'Conversion::Y'}} + Y y5 = static_cast<Y>(z); // expected-error {{no matching conversion for static_cast from 'Conversion::Z' to 'Conversion::Y'}} + // 13.3.1.5p1 & 8.5p16: + int i1 = (int)z; + int i2 = int(z); + int i3 = static_cast<int>(z); + int i4(z); + // 13.3.1.6p1 & 8.5.3p5: + const Y& y6 = z; // expected-error {{no viable conversion from 'Conversion::Z' to 'const Conversion::Y'}} + const int& y7(z); + } + + void testBool() { + struct Bool { + operator bool(); + }; + + struct NotBool { + explicit operator bool(); // expected-note {{conversion to integral type 'bool'}} + }; + Bool b; + NotBool n; + + (void) (1 + b); + (void) (1 + n); // expected-error {{invalid operands to binary expression ('int' and 'Conversion::NotBool')}} + + // 5.3.1p9: + (void) (!b); + (void) (!n); + + // 5.14p1: + (void) (b && true); + (void) (n && true); + + // 5.15p1: + (void) (b || true); + (void) (n || true); + + // 5.16p1: + (void) (b ? 0 : 1); + (void) (n ? 0: 1); + + // 5.19p5: + // TODO: After constexpr has been implemented + + // 6.4p4: + if (b) {} + if (n) {} + + // 6.4.2p2: + switch (b) {} // expected-warning {{switch condition has boolean value}} + switch (n) {} // expected-error {{switch condition type 'Conversion::NotBool' requires explicit conversion to 'bool'}} \ + expected-warning {{switch condition has boolean value}} + + // 6.5.1: + while (b) {} + while (n) {} + + // 6.5.2p1: + do {} while (b); + do {} while (n); + + // 6.5.3: + for (;b;) {} + for (;n;) {} + } + + void testNew() + { + // 5.3.4p6: + struct Int { + operator int(); + }; + struct NotInt { + explicit operator int(); // expected-note {{conversion to integral type 'int' declared here}} + }; + + Int i; + NotInt ni; + + new int[i]; + new int[ni]; // expected-error {{array size expression of type 'Conversion::NotInt' requires explicit conversion to type 'int'}} + } + + void testDelete() + { + // 5.3.5pp2: + struct Ptr { + operator int*(); + }; + struct NotPtr { + explicit operator int*(); + }; + + Ptr p; + NotPtr np; + + delete p; + delete np; // expected-error {{cannot delete expression of type 'Conversion::NotPtr'}} + } + + void testFunctionPointer() + { + // 13.3.1.1.2p2: + using Func = void(*)(int); + + struct FP { + operator Func(); + }; + struct NotFP { + explicit operator Func(); + }; + + FP fp; + NotFP nfp; + fp(1); + nfp(1); // expected-error {{type 'Conversion::NotFP' does not provide a call operator}} + } } |