[cfe-commits] r101680 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaCXX/aggregate-initialization.cpp test/SemaCXX/conditional-expr.cpp test/SemaCXX/conversion-function.cpp test/SemaCXX/copy-initialization.cpp test/SemaCXX/user-defined-conversions.cpp test/SemaTemplate/constructor-template.cpp

Douglas Gregor dgregor at apple.com
Sat Apr 17 15:01:05 PDT 2010


Author: dgregor
Date: Sat Apr 17 17:01:05 2010
New Revision: 101680

URL: http://llvm.org/viewvc/llvm-project?rev=101680&view=rev
Log:
Improve our handling of user-defined conversions as part of overload
resolution. There are two sources of problems involving user-defined
conversions that this change eliminates, along with providing simpler
interfaces for checking implicit conversions:

  - It eliminates a case of infinite recursion found in Boost.

  - It eliminates the search for the constructor needed to copy a temporary
    generated by an implicit conversion from overload
    resolution. Overload resolution assumes that, if it gets a value
    of the parameter's class type (or a derived class thereof), there
    is a way to copy if... even if there isn't. We now model this
    properly.



Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaOverload.h
    cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
    cfe/trunk/test/SemaCXX/conditional-expr.cpp
    cfe/trunk/test/SemaCXX/conversion-function.cpp
    cfe/trunk/test/SemaCXX/copy-initialization.cpp
    cfe/trunk/test/SemaCXX/user-defined-conversions.cpp
    cfe/trunk/test/SemaTemplate/constructor-template.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Apr 17 17:01:05 2010
@@ -692,17 +692,20 @@
   InGroup<DiagGroup<"uninitialized">>;
 
 def err_temp_copy_no_viable : Error<
-  "no viable copy constructor %select{copying variable|copying parameter|"
+  "no viable constructor %select{copying variable|copying parameter|"
   "returning object|throwing object|copying member subobject|copying array "
-  "element}0 of type %1">;
+  "element|allocating object|copying temporary|initializing base subobject|"
+  "initializing vector element}0 of type %1">;
 def err_temp_copy_ambiguous : Error<
-  "ambiguous copy constructor call when %select{copying variable|copying "
+  "ambiguous constructor call when %select{copying variable|copying "
   "parameter|returning object|throwing object|copying member subobject|copying "
-  "array element}0 of type %1">;
+  "array element|allocating object|copying temporary|initializing base subobject|"
+  "initializing vector element}0 of type %1">;
 def err_temp_copy_deleted : Error<
   "%select{copying variable|copying parameter|returning object|throwing "
-  "object|copying member subobject|copying array element}0 of type %1 invokes "
-  "deleted copy constructor">;
+  "object|copying member subobject|copying array element|allocating object|"
+  "copying temporary|initializing base subobject|initializing vector element}0 "
+  "of type %1 invokes deleted constructor">;
   
 // C++0x decltype
 def err_cannot_determine_declared_type_of_overloaded_function : Error<

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Apr 17 17:01:05 2010
@@ -1064,8 +1064,7 @@
   TryImplicitConversion(Expr* From, QualType ToType,
                         bool SuppressUserConversions,
                         bool AllowExplicit,
-                        bool InOverloadResolution,
-                        bool UserCast = false);
+                        bool InOverloadResolution);
   bool IsStandardConversion(Expr *From, QualType ToType,
                             bool InOverloadResolution,
                             StandardConversionSequence& SCS);
@@ -1090,9 +1089,7 @@
   OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType,
                                UserDefinedConversionSequence& User,
                                OverloadCandidateSet& Conversions,
-                               bool AllowConversionFunctions,
-                               bool AllowExplicit, 
-                               bool UserCast);
+                               bool AllowExplicit);
   bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
                                               
 

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Apr 17 17:01:05 2010
@@ -2531,8 +2531,7 @@
   ImplicitConversionSequence ICS
     = S.TryImplicitConversion(Initializer, cv1T1,
                               /*SuppressUserConversions=*/false, AllowExplicit, 
-                              /*FIXME:InOverloadResolution=*/false,
-                              /*UserCast=*/Kind.isExplicitCast());
+                              /*FIXME:InOverloadResolution=*/false);
             
   if (ICS.isBad()) {
     // FIXME: Use the conversion function set stored in ICS to turn
@@ -2867,10 +2866,21 @@
 
   // Add the user-defined conversion step that calls the conversion function.
   QualType ConvType = Function->getResultType().getNonReferenceType();
-  Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType);
+  if (ConvType->getAs<RecordType>()) {
+    // If we're converting to a class type, there may be an copy if
+    // the resulting temporary object (possible to create an object of
+    // a base class type). That copy is not a separate conversion, so
+    // we just make a note of the actual destination type (possibly a
+    // base class of the type returned by the conversion function) and
+    // let the user-defined conversion step handle the conversion.
+    Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType);
+    return;
+  }
 
-  // If the conversion following the call to the conversion function is 
-  // interesting, add it as a separate step.
+  Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType);
+    
+  // If the conversion following the call to the conversion function
+  // is interesting, add it as a separate step.
   if (Best->FinalConversion.First || Best->FinalConversion.Second ||
       Best->FinalConversion.Third) {
     ImplicitConversionSequence ICS;
@@ -2891,8 +2901,7 @@
     = S.TryImplicitConversion(Initializer, Entity.getType(),
                               /*SuppressUserConversions=*/true, 
                               /*AllowExplicit=*/false,
-                              /*FIXME:InOverloadResolution=*/false,
-                              /*UserCast=*/Kind.isExplicitCast());
+                              /*InOverloadResolution=*/false);
   
   if (ICS.isBad()) {
     Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
@@ -3103,10 +3112,11 @@
                                          const InitializedEntity &Entity,
                                          const InitializationKind &Kind,
                                          Sema::OwningExprResult CurInit) {
-  // Determine which class type we're copying.
+  // Determine which class type we're copying to.
   Expr *CurInitExpr = (Expr *)CurInit.get();
   CXXRecordDecl *Class = 0; 
-  if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
+  if (const RecordType *Record
+                = Entity.getType().getNonReferenceType()->getAs<RecordType>())
     Class = cast<CXXRecordDecl>(Record->getDecl());
   if (!Class)
     return move(CurInit);
@@ -3203,16 +3213,26 @@
     return S.ExprError();
   }
 
-  S.CheckConstructorAccess(Loc,
-                           cast<CXXConstructorDecl>(Best->Function),
+  CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
+  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+  CurInit.release(); // Ownership transferred into MultiExprArg, below.
+  
+  // Determine the arguments required to actually perform the
+  // constructor call (we might have derived-to-base conversions).
+  if (S.CompleteConstructorCall(Constructor,
+                                Sema::MultiExprArg(S, 
+                                                   (void **)&CurInitExpr,
+                                                   1),
+                                Loc, ConstructorArgs))
+    return S.ExprError();
+
+  S.CheckConstructorAccess(Loc, Constructor,
                            Best->FoundDecl.getAccess());
 
-  CurInit.release();
   return S.BuildCXXConstructExpr(Loc, Entity.getType().getNonReferenceType(),
-                                 cast<CXXConstructorDecl>(Best->Function),
+                                 Constructor,
                                  Elidable,
-                                 Sema::MultiExprArg(S, 
-                                                    (void**)&CurInitExpr, 1));
+                                 move_arg(ConstructorArgs));
 }
 
 Action::OwningExprResult 

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Apr 17 17:01:05 2010
@@ -436,14 +436,11 @@
 /// not permitted.
 /// If @p AllowExplicit, then explicit user-defined conversions are
 /// permitted.
-/// If @p UserCast, the implicit conversion is being done for a user-specified
-/// cast.
 ImplicitConversionSequence
 Sema::TryImplicitConversion(Expr* From, QualType ToType,
                             bool SuppressUserConversions,
                             bool AllowExplicit, 
-                            bool InOverloadResolution,
-                            bool UserCast) {
+                            bool InOverloadResolution) {
   ImplicitConversionSequence ICS;
   if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) {
     ICS.setStandard();
@@ -455,11 +452,47 @@
     return ICS;
   }
 
+  if (SuppressUserConversions) {
+    // C++ [over.ics.user]p4:
+    //   A conversion of an expression of class type to the same class
+    //   type is given Exact Match rank, and a conversion of an
+    //   expression of class type to a base class of that type is
+    //   given Conversion rank, in spite of the fact that a copy/move
+    //   constructor (i.e., a user-defined conversion function) is
+    //   called for those cases.
+    QualType FromType = From->getType();
+    if (!ToType->getAs<RecordType>() || !FromType->getAs<RecordType>() ||
+        !(Context.hasSameUnqualifiedType(FromType, ToType) ||
+          IsDerivedFrom(FromType, ToType))) {
+      // We're not in the case above, so there is no conversion that
+      // we can perform.
+      ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+      return ICS;
+    }
+
+    ICS.setStandard();
+    ICS.Standard.setAsIdentityConversion();
+    ICS.Standard.setFromType(FromType);
+    ICS.Standard.setAllToTypes(ToType);
+    
+    // We don't actually check at this point whether there is a valid
+    // copy/move constructor, since overloading just assumes that it
+    // exists. When we actually perform initialization, we'll find the
+    // appropriate constructor to copy the returned object, if needed.
+    ICS.Standard.CopyConstructor = 0;
+
+    // Determine whether this is considered a derived-to-base conversion.
+    if (!Context.hasSameUnqualifiedType(FromType, ToType))
+      ICS.Standard.Second = ICK_Derived_To_Base;
+
+    return ICS;
+  }
+
+  // Attempt user-defined conversion.
   OverloadCandidateSet Conversions(From->getExprLoc());
   OverloadingResult UserDefResult
     = IsUserDefinedConversion(From, ToType, ICS.UserDefined, Conversions,
-                              !SuppressUserConversions, AllowExplicit,
-                              UserCast);
+                              AllowExplicit);
 
   if (UserDefResult == OR_Success) {
     ICS.setUserDefined();
@@ -1509,45 +1542,39 @@
 /// and this routine will return true. Otherwise, this routine returns
 /// false and User is unspecified.
 ///
-/// \param AllowConversionFunctions true if the conversion should
-/// consider conversion functions at all. If false, only constructors
-/// will be considered.
-///
 /// \param AllowExplicit  true if the conversion should consider C++0x
 /// "explicit" conversion functions as well as non-explicit conversion
 /// functions (C++0x [class.conv.fct]p2).
-///
-/// \param UserCast true if looking for user defined conversion for a static
-/// cast.
 OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
                                           UserDefinedConversionSequence& User,
-                                            OverloadCandidateSet& CandidateSet,
-                                                bool AllowConversionFunctions,
-                                                bool AllowExplicit, 
-                                                bool UserCast) {
+                                           OverloadCandidateSet& CandidateSet,
+                                                bool AllowExplicit) {
+  // Whether we will only visit constructors.
+  bool ConstructorsOnly = false;
+
+  // If the type we are conversion to is a class type, enumerate its
+  // constructors.
   if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
+    // C++ [over.match.ctor]p1:
+    //   When objects of class type are direct-initialized (8.5), or
+    //   copy-initialized from an expression of the same or a
+    //   derived class type (8.5), overload resolution selects the
+    //   constructor. [...] For copy-initialization, the candidate
+    //   functions are all the converting constructors (12.3.1) of
+    //   that class. The argument list is the expression-list within
+    //   the parentheses of the initializer.
+    if (Context.hasSameUnqualifiedType(ToType, From->getType()) ||
+        (From->getType()->getAs<RecordType>() &&
+         IsDerivedFrom(From->getType(), ToType)))
+      ConstructorsOnly = true;
+
     if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) {
       // We're not going to find any constructors.
     } else if (CXXRecordDecl *ToRecordDecl
                  = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
-      // C++ [over.match.ctor]p1:
-      //   When objects of class type are direct-initialized (8.5), or
-      //   copy-initialized from an expression of the same or a
-      //   derived class type (8.5), overload resolution selects the
-      //   constructor. [...] For copy-initialization, the candidate
-      //   functions are all the converting constructors (12.3.1) of
-      //   that class. The argument list is the expression-list within
-      //   the parentheses of the initializer.
-      bool SuppressUserConversions = !UserCast;
-      if (Context.hasSameUnqualifiedType(ToType, From->getType()) ||
-          IsDerivedFrom(From->getType(), ToType)) {
-        SuppressUserConversions = false;
-        AllowConversionFunctions = false;
-      }
-          
       DeclarationName ConstructorName
         = Context.DeclarationNames.getCXXConstructorName(
-                          Context.getCanonicalType(ToType).getUnqualifiedType());
+                       Context.getCanonicalType(ToType).getUnqualifiedType());
       DeclContext::lookup_iterator Con, ConEnd;
       for (llvm::tie(Con, ConEnd)
              = ToRecordDecl->lookup(ConstructorName);
@@ -1571,26 +1598,25 @@
             AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
                                          /*ExplicitArgs*/ 0,
                                          &From, 1, CandidateSet, 
-                                         SuppressUserConversions);
+                                 /*SuppressUserConversions=*/!ConstructorsOnly);
           else
             // Allow one user-defined conversion when user specifies a
             // From->ToType conversion via an static cast (c-style, etc).
             AddOverloadCandidate(Constructor, FoundDecl,
                                  &From, 1, CandidateSet,
-                                 SuppressUserConversions);
+                                 /*SuppressUserConversions=*/!ConstructorsOnly);
         }
       }
     }
   }
 
-  if (!AllowConversionFunctions) {
-    // Don't allow any conversion functions to enter the overload set.
+  // Enumerate conversion functions, if we're allowed to.
+  if (ConstructorsOnly) {
   } else if (RequireCompleteType(From->getLocStart(), From->getType(),
-                                 PDiag(0)
-                                   << From->getSourceRange())) {
+                          PDiag(0) << From->getSourceRange())) {
     // No conversion functions from incomplete types.
   } else if (const RecordType *FromRecordType
-               = From->getType()->getAs<RecordType>()) {
+                                   = From->getType()->getAs<RecordType>()) {
     if (CXXRecordDecl *FromRecordDecl
          = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
       // Add all of the conversion functions as candidates.
@@ -1696,7 +1722,7 @@
   OverloadCandidateSet CandidateSet(From->getExprLoc());
   OverloadingResult OvResult = 
     IsUserDefinedConversion(From, ToType, ICS.UserDefined,
-                            CandidateSet, true, false, false);
+                            CandidateSet, false);
   if (OvResult == OR_Ambiguous)
     Diag(From->getSourceRange().getBegin(),
          diag::err_typecheck_ambiguous_condition)
@@ -1732,16 +1758,10 @@
   //   described in 13.3.3.2, the ambiguous conversion sequence is
   //   treated as a user-defined sequence that is indistinguishable
   //   from any other user-defined conversion sequence.
-  if (ICS1.getKind() < ICS2.getKind()) {
-    if (!(ICS1.isUserDefined() && ICS2.isAmbiguous()))
-      return ImplicitConversionSequence::Better;
-  } else if (ICS2.getKind() < ICS1.getKind()) {
-    if (!(ICS2.isUserDefined() && ICS1.isAmbiguous()))
-      return ImplicitConversionSequence::Worse;
-  }
-
-  if (ICS1.isAmbiguous() || ICS2.isAmbiguous())
-    return ImplicitConversionSequence::Indistinguishable;
+  if (ICS1.getKindRank() < ICS2.getKindRank())
+    return ImplicitConversionSequence::Better;
+  else if (ICS2.getKindRank() < ICS1.getKindRank())
+    return ImplicitConversionSequence::Worse;
 
   // Two implicit conversion sequences of the same form are
   // indistinguishable conversion sequences unless one of the
@@ -2167,9 +2187,7 @@
     }
   }
   
-  if ((SCS1.ReferenceBinding || SCS1.CopyConstructor) && 
-      (SCS2.ReferenceBinding || SCS2.CopyConstructor) &&
-      SCS1.Second == ICK_Derived_To_Base) {
+  if (SCS1.Second == ICK_Derived_To_Base) {
     //   -- conversion of C to B is better than conversion of C to A,
     //   -- binding of an expression of type C to a reference of type
     //      B& is better than binding an expression of type C to a
@@ -3067,7 +3085,7 @@
                              OverloadCandidateSet& CandidateSet) {
   assert(!Conversion->getDescribedFunctionTemplate() &&
          "Conversion function templates use AddTemplateConversionCandidate");
-
+  QualType ConvType = Conversion->getConversionType().getNonReferenceType();
   if (!CandidateSet.isNewCandidate(Conversion))
     return;
 
@@ -3082,7 +3100,7 @@
   Candidate.IsSurrogate = false;
   Candidate.IgnoreObjectArgument = false;
   Candidate.FinalConversion.setAsIdentityConversion();
-  Candidate.FinalConversion.setFromType(Conversion->getConversionType());
+  Candidate.FinalConversion.setFromType(ConvType);
   Candidate.FinalConversion.setAllToTypes(ToType);
 
   // Determine the implicit conversion sequence for the implicit
@@ -3115,7 +3133,6 @@
     return;
   }
   
-
   // To determine what the conversion from the result of calling the
   // conversion function to the type we're eventually trying to
   // convert to (ToType), we need to synthesize a call to the

Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Sat Apr 17 17:01:05 2010
@@ -381,6 +381,33 @@
       assert(isInitialized() && "querying uninitialized conversion");
       return Kind(ConversionKind);
     }
+    
+    /// \brief Return a ranking of the implicit conversion sequence
+    /// kind, where smaller ranks represent better conversion
+    /// sequences.
+    ///
+    /// In particular, this routine gives user-defined conversion
+    /// sequences and ambiguous conversion sequences the same rank,
+    /// per C++ [over.best.ics]p10.
+    unsigned getKindRank() const {
+      switch (getKind()) {
+      case StandardConversion: 
+        return 0;
+
+      case UserDefinedConversion:
+      case AmbiguousConversion: 
+        return 1;
+
+      case EllipsisConversion:
+        return 2;
+
+      case BadConversion:
+        return 3;
+      }
+
+      return 3;
+    }
+
     bool isBad() const { return getKind() == BadConversion; }
     bool isStandard() const { return getKind() == StandardConversion; }
     bool isEllipsis() const { return getKind() == EllipsisConversion; }

Modified: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp Sat Apr 17 17:01:05 2010
@@ -60,10 +60,10 @@
 
 void f() {
   A as1[1] = { };
-  A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted copy constructor}}
+  A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted constructor}}
 
   B b1 = { };
-  B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted copy constructor}}
+  B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted constructor}}
   
   C c1 = { 1 };
 }

Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Sat Apr 17 17:01:05 2010
@@ -224,7 +224,7 @@
 
   struct Foo3 {
     Foo3();
-    Foo3(Foo3&);
+    Foo3(Foo3&); // expected-note{{would lose const qualifier}}
   };
 
   struct Bar {
@@ -236,7 +236,6 @@
   void f() {
     (void)(true ? Bar() : Foo1()); // okay
     (void)(true ? Bar() : Foo2()); // okay
-    // FIXME: Diagnostic below could be improved
-    (void)(true ? Bar() : Foo3()); // expected-error{{incompatible operand types ('PR6757::Bar' and 'PR6757::Foo3')}}
+    (void)(true ? Bar() : Foo3()); // expected-error{{no viable constructor copying temporary}}
   }
 }

Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/conversion-function.cpp Sat Apr 17 17:01:05 2010
@@ -129,7 +129,7 @@
 };
 
 A1 f() {
-  return "Hello"; // expected-error{{invokes deleted copy constructor}}
+  return "Hello"; // expected-error{{invokes deleted constructor}}
 }
 
 namespace source_locations {
@@ -176,3 +176,29 @@
     *operator int();  // expected-error {{must use a typedef to declare a conversion to 'int *'}}
   };
 }
+
+namespace smart_ptr {
+  class Y { 
+    class YRef { };
+
+    Y(Y&);
+
+  public:
+    Y();
+    Y(YRef);
+
+    operator YRef(); // expected-note{{candidate function}}
+  };
+
+  struct X { // expected-note{{candidate constructor (the implicit copy constructor) not}}
+    explicit X(Y);
+  };
+
+  Y make_Y();
+
+  X f() {
+    X x = make_Y(); // expected-error{{no viable conversion from 'smart_ptr::Y' to 'smart_ptr::X'}}
+    X x2(make_Y());
+    return X(Y());
+  }
+}

Modified: cfe/trunk/test/SemaCXX/copy-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/copy-initialization.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/copy-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/copy-initialization.cpp Sat Apr 17 17:01:05 2010
@@ -25,19 +25,17 @@
 namespace PR6757 {
   struct Foo {
     Foo();
-    Foo(Foo&);
+    Foo(Foo&); // expected-note{{candidate constructor not viable}}
   };
 
   struct Bar {
     operator const Foo&() const;
   };
 
-  void f(Foo); // expected-note{{candidate function not viable: no known conversion from 'PR6757::Bar' to 'PR6757::Foo' for 1st argument}}
+  void f(Foo);
 
-  // FIXME: This isn't really the right reason for the failure. We
-  // should fail after overload resolution.
   void g(Foo foo) {
-    f(Bar()); // expected-error{{no matching function for call to 'f'}}
+    f(Bar()); // expected-error{{no viable constructor copying parameter of type 'PR6757::Foo const'}}
     f(foo);
   }
 }

Modified: cfe/trunk/test/SemaCXX/user-defined-conversions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/user-defined-conversions.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/user-defined-conversions.cpp (original)
+++ cfe/trunk/test/SemaCXX/user-defined-conversions.cpp Sat Apr 17 17:01:05 2010
@@ -67,3 +67,18 @@
   Base b4(ctd);
   Base b5 = ctfd;
 }
+
+struct X1 {
+  X1(X1&); // expected-note{{candidate constructor not viable: no known conversion from 'X1' to 'X1 &' for 1st argument}}
+};
+
+struct X2 {
+  operator X1();
+};
+
+int &f(X1);
+float &f(...);
+
+void g(X2 b) {
+  int &ir = f(b); // expected-error{{no viable constructor copying parameter of type 'X1'}}
+}

Modified: cfe/trunk/test/SemaTemplate/constructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/constructor-template.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/constructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/constructor-template.cpp Sat Apr 17 17:01:05 2010
@@ -94,3 +94,18 @@
 }
 
 template void default_ctor_inst<int>();
+
+template<typename T>
+struct X5 {
+  X5();
+  X5(const T &);
+};
+
+struct X6 {
+  template<typename T> X6(T);
+};
+
+void test_X5_X6() {
+  X5<X6> tf;
+  X5<X6> tf2(tf);
+}





More information about the cfe-commits mailing list