[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