hanchenye-llvm-project/clang/test/SemaCXX/convert-to-bool.cpp

68 lines
1.7 KiB
C++
Raw Normal View History

// RUN: %clang_cc1 -fsyntax-only -verify %s
struct ConvToBool {
operator bool() const;
};
struct ConvToInt {
operator int();
};
struct ExplicitConvToBool {
explicit operator bool(); // expected-warning{{explicit conversion functions are a C++0x extension}}
};
void test_conv_to_bool(ConvToBool ctb, ConvToInt cti, ExplicitConvToBool ecb) {
if (ctb) { }
if (cti) { }
if (ecb) { }
for (; ctb; ) { }
for (; cti; ) { }
for (; ecb; ) { }
while (ctb) { };
while (cti) { }
while (ecb) { }
do { } while (ctb);
do { } while (cti);
do { } while (ecb);
if (!ctb) { }
if (!cti) { }
if (!ecb) { }
bool b1 = !ecb;
if (ctb && ecb) { }
bool b2 = ctb && ecb;
if (ctb || ecb) { }
bool b3 = ctb || ecb;
}
void accepts_bool(bool) { } // expected-note{{candidate function}}
struct ExplicitConvToRef {
explicit operator int&(); // expected-warning{{explicit conversion functions are a C++0x extension}}
};
void test_explicit_bool(ExplicitConvToBool ecb) {
bool b1(ecb); // okay
bool b2 = ecb; // expected-error{{no viable conversion from 'ExplicitConvToBool' to 'bool'}}
accepts_bool(ecb); // expected-error{{no matching function for call to}}
}
void test_explicit_conv_to_ref(ExplicitConvToRef ecr) {
int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'ExplicitConvToRef'}}
int& i2(ecr); // okay
}
struct A { };
struct B { };
struct C {
explicit operator A&(); // expected-warning{{explicit conversion functions are a C++0x extension}}
Reimplement reference initialization (C++ [dcl.init.ref]) using the new notion of an "initialization sequence", which encapsulates the computation of the initialization sequence along with diagnostic information and the capability to turn the computed sequence into an expression. At present, I've only switched one CheckReferenceInit callers over to this new mechanism; more will follow. Aside from (hopefully) being much more true to the standard, the diagnostics provided by this reference-initialization code are a bit better than before. Some examples: p5-var.cpp:54:12: error: non-const lvalue reference to type 'struct Derived' cannot bind to a value of unrelated type 'struct Base' Derived &dr2 = b; // expected-error{{non-const lvalue reference to ... ^ ~ p5-var.cpp:55:9: error: binding of reference to type 'struct Base' to a value of type 'struct Base const' drops qualifiers Base &br3 = bc; // expected-error{{drops qualifiers}} ^ ~~ p5-var.cpp:57:15: error: ambiguous conversion from derived class 'struct Diamond' to base class 'struct Base': struct Diamond -> struct Derived -> struct Base struct Diamond -> struct Derived2 -> struct Base Base &br5 = diamond; // expected-error{{ambiguous conversion from ... ^~~~~~~ p5-var.cpp:59:9: error: non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int' long &lr = i; // expected-error{{non-const lvalue reference to type ... ^ ~ p5-var.cpp:74:9: error: non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Base' Base &br1 = Base(); // expected-error{{non-const lvalue reference to ... ^ ~~~~~~ p5-var.cpp:102:9: error: non-const reference cannot bind to bit-field 'i' int & ir1 = (ib.i); // expected-error{{non-const reference cannot ... ^ ~~~~~~ p5-var.cpp:98:7: note: bit-field is declared here int i : 17; // expected-note{{bit-field is declared here}} ^ llvm-svn: 90992
2009-12-10 07:02:17 +08:00
operator B&(); // expected-note{{candidate}}
};
void test_copy_init_conversions(C c) {
A &a = c; // expected-error{{no viable conversion from 'C' to 'A'}}
B &b = b; // okay
}