[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