[cfe-commits] r145769 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaCXX/cxx0x-initializer-references.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Sat Dec 3 06:54:30 PST 2011


Author: cornedbee
Date: Sat Dec  3 08:54:30 2011
New Revision: 145769

URL: http://llvm.org/viewvc/llvm-project?rev=145769&view=rev
Log:
Implement overload resolution for reference-typed parameters supplied with initializer lists.

Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=145769&r1=145768&r2=145769&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Dec  3 08:54:30 2011
@@ -3619,7 +3619,7 @@
 /// \brief Compute an implicit conversion sequence for reference
 /// initialization.
 static ImplicitConversionSequence
-TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
+TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
                  SourceLocation DeclLoc,
                  bool SuppressUserConversions,
                  bool AllowExplicit) {
@@ -3950,9 +3950,71 @@
 
   // C++11 [over.ics.list]p5:
   //   Otherwise, if the parameter is a reference, see 13.3.3.1.4.
-  // FIXME: Implement this.
-  if (ToType->isReferenceType())
+  if (ToType->isReferenceType()) {
+    // The standard is notoriously unclear here, since 13.3.3.1.4 doesn't
+    // mention initializer lists in any way. So we go by what list-
+    // initialization would do and try to extrapolate from that.
+
+    QualType T1 = ToType->getAs<ReferenceType>()->getPointeeType();
+
+    // If the initializer list has a single element that is reference-related
+    // to the parameter type, we initialize the reference from that.
+    if (From->getNumInits() == 1) {
+      Expr *Init = From->getInit(0);
+
+      QualType T2 = Init->getType();
+
+      // If the initializer is the address of an overloaded function, try
+      // to resolve the overloaded function. If all goes well, T2 is the
+      // type of the resulting function.
+      if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+        DeclAccessPair Found;
+        if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(
+                                   Init, ToType, false, Found))
+          T2 = Fn->getType();
+      }
+
+      // Compute some basic properties of the types and the initializer.
+      bool dummy1 = false;
+      bool dummy2 = false;
+      bool dummy3 = false;
+      Sema::ReferenceCompareResult RefRelationship
+        = S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1,
+                                         dummy2, dummy3);
+
+      if (RefRelationship >= Sema::Ref_Related)
+        return TryReferenceInit(S, Init, ToType,
+                                /*FIXME:*/From->getLocStart(),
+                                SuppressUserConversions,
+                                /*AllowExplicit=*/false);
+    }
+
+    // Otherwise, we bind the reference to a temporary created from the
+    // initializer list.
+    Result = TryListConversion(S, From, T1, SuppressUserConversions,
+                               InOverloadResolution,
+                               AllowObjCWritebackConversion);
+    if (Result.isFailure())
+      return Result;
+    assert(!Result.isEllipsis() &&
+           "Sub-initialization cannot result in ellipsis conversion.");
+
+    // Can we even bind to a temporary?
+    if (ToType->isRValueReferenceType() ||
+        (T1.isConstQualified() && !T1.isVolatileQualified())) {
+      StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard :
+                                            Result.UserDefined.After;
+      SCS.ReferenceBinding = true;
+      SCS.IsLvalueReference = ToType->isLValueReferenceType();
+      SCS.BindsToRvalue = true;
+      SCS.BindsToFunctionLvalue = false;
+      SCS.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+      SCS.ObjCLifetimeConversionBinding = false;
+    } else
+      Result.setBad(BadConversionSequence::lvalue_ref_to_rvalue,
+                    From, ToType);
     return Result;
+  }
 
   // C++11 [over.ics.list]p6:
   //   Otherwise, if the parameter type is not a class:

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp?rev=145769&r1=145768&r2=145769&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-references.cpp Sat Dec  3 08:54:30 2011
@@ -1,5 +1,8 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
 
+struct one { char c; };
+struct two { char c[2]; };
+
 namespace reference {
   struct A {
     int i1, i2;
@@ -28,4 +31,44 @@
     static_assert(sizeof(arrayRef) == 3 * sizeof(int), "bad array size");
   }
 
+  struct B {
+    int i1;
+  };
+
+  void call() {
+    void f(const int&);
+    f({1});
+
+    void g(int&); // expected-note {{passing argument}}
+    g({1}); // expected-error {{cannot bind to an initializer list temporary}}
+    int i = 0;
+    g({i});
+
+    void h(const B&);
+    h({1});
+
+    void a(B&); // expected-note {{passing argument}}
+    a({1}); // expected-error {{cannot bind to an initializer list temporary}}
+    B b{1};
+    a({b});
+  }
+
+  void overloading() {
+    one f(const int&);
+    two f(const B&);
+
+    // First is identity conversion, second is user-defined conversion.
+    static_assert(sizeof(f({1})) == sizeof(one), "bad overload resolution");
+
+    one g(int&);
+    two g(const B&);
+
+    static_assert(sizeof(g({1})) == sizeof(two), "bad overload resolution");
+
+    one h(const int&);
+    two h(const A&);
+
+    static_assert(sizeof(h({1, 2})) == sizeof(two), "bad overload resolution");
+  }
+
 }





More information about the cfe-commits mailing list