[cfe-commits] r143462 - in /cfe/trunk: include/clang/Sema/Overload.h lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp test/SemaCXX/cxx0x-initializer-aggregates.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Tue Nov 1 08:53:09 PDT 2011


Author: cornedbee
Date: Tue Nov  1 10:53:09 2011
New Revision: 143462

URL: http://llvm.org/viewvc/llvm-project?rev=143462&view=rev
Log:
Enable function call and some overload resolution with parameters of aggregate class type and initializer list arguments.

Modified:
    cfe/trunk/include/clang/Sema/Overload.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp

Modified: cfe/trunk/include/clang/Sema/Overload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Overload.h?rev=143462&r1=143461&r2=143462&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Overload.h (original)
+++ cfe/trunk/include/clang/Sema/Overload.h Tue Nov  1 10:53:09 2011
@@ -225,9 +225,10 @@
   /// UserDefinedConversionSequence - Represents a user-defined
   /// conversion sequence (C++ 13.3.3.1.2).
   struct UserDefinedConversionSequence {
-    /// Before - Represents the standard conversion that occurs before
-    /// the actual user-defined conversion. (C++ 13.3.3.1.2p1):
+    /// \brief Represents the standard conversion that occurs before
+    /// the actual user-defined conversion.
     ///
+    /// C++11 13.3.3.1.2p1:
     ///   If the user-defined conversion is specified by a constructor
     ///   (12.3.1), the initial standard conversion sequence converts
     ///   the source type to the type required by the argument of the
@@ -255,14 +256,15 @@
     StandardConversionSequence After;
 
     /// ConversionFunction - The function that will perform the
-    /// user-defined conversion.
+    /// user-defined conversion. Null if the conversion is an
+    /// aggregate initialization from an initializer list.
     FunctionDecl* ConversionFunction;
 
     /// \brief The declaration that we found via name lookup, which might be
     /// the same as \c ConversionFunction or it might be a using declaration
     /// that refers to \c ConversionFunction.
     DeclAccessPair FoundConversionFunction;
-    
+
     void DebugPrint() const;
   };
 
@@ -379,7 +381,10 @@
     };
 
     /// ConversionKind - The kind of implicit conversion sequence.
-    unsigned ConversionKind;
+    unsigned ConversionKind : 31;
+
+    /// \brief Whether the argument is an initializer list.
+    bool ListInitializationSequence : 1;
 
     void setKind(Kind K) {
       destruct();
@@ -499,6 +504,16 @@
       Ambiguous.construct();
     }
 
+    /// \brief Whether this sequence was created by the rules of
+    /// list-initialization sequences.
+    bool isListInitializationSequence() const {
+      return ListInitializationSequence;
+    }
+
+    void setListInitializationSequence() {
+      ListInitializationSequence = true;
+    }
+
     // The result of a comparison between implicit conversion
     // sequences. Use Sema::CompareImplicitConversionSequences to
     // actually perform the comparison.

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=143462&r1=143461&r2=143462&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Nov  1 10:53:09 2011
@@ -2129,6 +2129,7 @@
       FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
       CastKind CastKind;
       QualType BeforeToType;
+      assert(FD && "FIXME: aggregate initialization from init list");
       if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
         CastKind = CK_UserDefinedConversion;
 

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=143462&r1=143461&r2=143462&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Nov  1 10:53:09 2011
@@ -305,7 +305,10 @@
     Before.DebugPrint();
     OS << " -> ";
   }
-  OS << '\'' << *ConversionFunction << '\'';
+  if (ConversionFunction)
+    OS << '\'' << *ConversionFunction << '\'';
+  else
+    OS << "aggregate initialization";
   if (After.First || After.Second || After.Third) {
     OS << " -> ";
     After.DebugPrint();
@@ -2701,11 +2704,15 @@
   if (ICS1.getKind() != ICS2.getKind())
     return ImplicitConversionSequence::Indistinguishable;
 
+  ImplicitConversionSequence::CompareKind Result =
+      ImplicitConversionSequence::Indistinguishable;
+
   // Two implicit conversion sequences of the same form are
   // indistinguishable conversion sequences unless one of the
   // following rules apply: (C++ 13.3.3.2p3):
   if (ICS1.isStandard())
-    return CompareStandardConversionSequences(S, ICS1.Standard, ICS2.Standard);
+    Result = CompareStandardConversionSequences(S,
+                                                ICS1.Standard, ICS2.Standard);
   else if (ICS1.isUserDefined()) {
     // User-defined conversion sequence U1 is a better conversion
     // sequence than another user-defined conversion sequence U2 if
@@ -2715,12 +2722,21 @@
     // U2 (C++ 13.3.3.2p3).
     if (ICS1.UserDefined.ConversionFunction ==
           ICS2.UserDefined.ConversionFunction)
-      return CompareStandardConversionSequences(S,
-                                                ICS1.UserDefined.After,
-                                                ICS2.UserDefined.After);
+      Result = CompareStandardConversionSequences(S,
+                                                  ICS1.UserDefined.After,
+                                                  ICS2.UserDefined.After);
   }
 
-  return ImplicitConversionSequence::Indistinguishable;
+  // List-initialization sequence L1 is a better conversion sequence than
+  // list-initialization sequence L2 if L1 converts to std::initializer_list<X>
+  // for some X and L2 does not.
+  if (Result == ImplicitConversionSequence::Indistinguishable &&
+      ICS1.isListInitializationSequence() &&
+      ICS2.isListInitializationSequence()) {
+    // FIXME: Find out if ICS1 converts to initializer_list and ICS2 doesn't.
+  }
+
+  return Result;
 }
 
 static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
@@ -3780,6 +3796,7 @@
 
   ImplicitConversionSequence Result;
   Result.setBad(BadConversionSequence::no_conversion, From, ToType);
+  Result.setListInitializationSequence();
 
   // C++11 [over.ics.list]p2:
   //   If the parameter type is std::initializer_list<X> or "array of X" and
@@ -3805,8 +3822,24 @@
   //   Otherwise, if the parameter has an aggregate type which can be
   //   initialized from the initializer list [...] the implicit conversion
   //   sequence is a user-defined conversion sequence.
-  // FIXME: Implement this.
   if (ToType->isAggregateType()) {
+    // Type is an aggregate, argument is an init list. At this point it comes
+    // down to checking whether the initialization works.
+    // FIXME: Find out whether this parameter is consumed or not.
+    InitializedEntity Entity =
+        InitializedEntity::InitializeParameter(S.Context, ToType,
+                                               /*Consumed=*/false);
+    if (S.CanPerformCopyInitialization(Entity, S.Owned(From))) {
+      Result.setUserDefined();
+      Result.UserDefined.Before.setAsIdentityConversion();
+      // Initializer lists don't have a type.
+      Result.UserDefined.Before.setFromType(QualType());
+      Result.UserDefined.Before.setAllToTypes(QualType());
+
+      Result.UserDefined.After.setAsIdentityConversion();
+      Result.UserDefined.After.setFromType(ToType);
+      Result.UserDefined.After.setAllToTypes(ToType);
+    }
     return Result;
   }
 

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp?rev=143462&r1=143461&r2=143462&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp Tue Nov  1 10:53:09 2011
@@ -1,5 +1,8 @@
 // RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
 
+struct one { char c[1]; };
+struct two { char c[2]; };
+
 namespace aggregate {
   // Direct list initialization does NOT allow braces to be elided!
   struct S {
@@ -16,11 +19,41 @@
     } v;
   };
 
-  void test() {
+  void bracing() {
     S s1 = { 1, 2, 3 ,4, 5, 6, 7, 8 }; // no-error
     S s2{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
     S s3{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
     S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
     S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
   }
+
+  struct String {
+    String(const char*);
+  };
+
+  struct A {
+    int m1;
+    int m2;
+  };
+
+  void function_call() {
+    void takes_A(A);
+    takes_A({1, 2});
+  }
+
+  struct B {
+    int m1;
+    String m2;
+  };
+
+  void overloaded_call() {
+    one overloaded(A);
+    two overloaded(B);
+
+    static_assert(sizeof(overloaded({1, 2})) == sizeof(one), "bad overload");
+    static_assert(sizeof(overloaded({1, "two"})) == sizeof(two),
+      "bad overload");
+    // String is not default-constructible
+    static_assert(sizeof(overloaded({1})) == sizeof(one), "bad overload");
+  }
 }





More information about the cfe-commits mailing list