[cfe-commits] r135857 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaCXX/explicit.cpp
Douglas Gregor
dgregor at apple.com
Sat Jul 23 11:59:36 PDT 2011
Author: dgregor
Date: Sat Jul 23 13:59:35 2011
New Revision: 135857
URL: http://llvm.org/viewvc/llvm-project?rev=135857&view=rev
Log:
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!
Modified:
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/SemaCXX/explicit.cpp
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=135857&r1=135856&r2=135857&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Jul 23 13:59:35 2011
@@ -9384,8 +9384,8 @@
}
// C++ [over.call.object]p2:
- // In addition, for each conversion function declared in T of the
- // form
+ // In addition, for each (non-explicit in C++0x) conversion function
+ // declared in T of the form
//
// operator conversion-type-id () cv-qualifier;
//
@@ -9415,16 +9415,19 @@
continue;
CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
-
- // Strip the reference type (if any) and then the pointer type (if
- // any) to get down to what might be a function type.
- QualType ConvType = Conv->getConversionType().getNonReferenceType();
- if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
- ConvType = ConvPtrType->getPointeeType();
-
- if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
- AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
- Object.get(), Args, NumArgs, CandidateSet);
+ if (!Conv->isExplicit()) {
+ // Strip the reference type (if any) and then the pointer type (if
+ // any) to get down to what might be a function type.
+ QualType ConvType = Conv->getConversionType().getNonReferenceType();
+ if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+ ConvType = ConvPtrType->getPointeeType();
+
+ if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
+ {
+ AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
+ Object.get(), Args, NumArgs, CandidateSet);
+ }
+ }
}
// Perform overload resolution.
Modified: cfe/trunk/test/SemaCXX/explicit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/explicit.cpp?rev=135857&r1=135856&r2=135857&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/explicit.cpp (original)
+++ cfe/trunk/test/SemaCXX/explicit.cpp Sat Jul 23 13:59:35 2011
@@ -36,4 +36,144 @@
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}}
+ }
}
More information about the cfe-commits
mailing list