[cfe-commits] r94660 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaCXX/overload-call-copycon.cpp test/SemaCXX/overload-call.cpp
Douglas Gregor
dgregor at apple.com
Tue Jan 26 19:51:04 PST 2010
Author: dgregor
Date: Tue Jan 26 21:51:04 2010
New Revision: 94660
URL: http://llvm.org/viewvc/llvm-project?rev=94660&view=rev
Log:
Fix a major oversight in the comparison of standard conversion
sequences, where we would occasionally determine (incorrectly) that
one standard conversion sequence was a proper subset of another when,
in fact, they contained completely incomparable conversions.
This change records the types in each step within a standard
conversion sequence, so that we can check the specific comparison
types to determine when one sequence is a proper subset of the
other. Fixes this testcase (thanks, Anders!), which was distilled from
PR6095 (also thanks to Anders).
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaOverload.h
cfe/trunk/test/SemaCXX/overload-call-copycon.cpp
cfe/trunk/test/SemaCXX/overload-call.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=94660&r1=94659&r2=94660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jan 26 21:51:04 2010
@@ -4455,7 +4455,9 @@
ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
ICS->Standard.Third = ICK_Identity;
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
+ ICS->Standard.setToType(0, T2);
+ ICS->Standard.setToType(1, T1);
+ ICS->Standard.setToType(2, T1);
ICS->Standard.ReferenceBinding = true;
ICS->Standard.DirectBinding = true;
ICS->Standard.RRefBinding = false;
@@ -4645,7 +4647,9 @@
ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
ICS->Standard.Third = ICK_Identity;
ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS->Standard.ToTypePtr = T1.getAsOpaquePtr();
+ ICS->Standard.setToType(0, T2);
+ ICS->Standard.setToType(1, T1);
+ ICS->Standard.setToType(2, T1);
ICS->Standard.ReferenceBinding = true;
ICS->Standard.DirectBinding = false;
ICS->Standard.RRefBinding = isRValRef;
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=94660&r1=94659&r2=94660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Jan 26 21:51:04 2010
@@ -1487,9 +1487,9 @@
static QualType TargetType(const ImplicitConversionSequence &ICS) {
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
- return ICS.Standard.getToType();
+ return ICS.Standard.getToType(2);
case ImplicitConversionSequence::UserDefinedConversion:
- return ICS.UserDefined.After.getToType();
+ return ICS.UserDefined.After.getToType(2);
case ImplicitConversionSequence::AmbiguousConversion:
return ICS.Ambiguous.getToType();
case ImplicitConversionSequence::EllipsisConversion:
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=94660&r1=94659&r2=94660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Jan 26 21:51:04 2010
@@ -148,7 +148,7 @@
// array-to-pointer or function-to-pointer implicit conversions, so
// check for their presence as well as checking whether FromType is
// a pointer.
- if (getToType()->isBooleanType() &&
+ if (getToType(1)->isBooleanType() &&
(getFromType()->isPointerType() || getFromType()->isBlockPointerType() ||
First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
return true;
@@ -164,7 +164,7 @@
StandardConversionSequence::
isPointerConversionToVoidPointer(ASTContext& Context) const {
QualType FromType = getFromType();
- QualType ToType = getToType();
+ QualType ToType = getToType(1);
// Note that FromType has not necessarily been transformed by the
// array-to-pointer implicit conversion, so check for its presence
@@ -477,7 +477,7 @@
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(From->getType());
- ICS.Standard.setToType(ToType);
+ ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = Constructor;
if (ToCanon != FromCanon)
ICS.Standard.Second = ICK_Derived_To_Base;
@@ -595,7 +595,7 @@
// conversion (4.4). (C++ 4.2p2)
SCS.Second = ICK_Identity;
SCS.Third = ICK_Qualification;
- SCS.setToType(ToType);
+ SCS.setAllToTypes(FromType);
return true;
}
} else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) {
@@ -634,6 +634,7 @@
// We don't require any conversions for the first step.
SCS.First = ICK_Identity;
}
+ SCS.setToType(0, FromType);
// The second conversion can be an integral promotion, floating
// point promotion, integral conversion, floating point conversion,
@@ -714,6 +715,7 @@
// No second conversion required.
SCS.Second = ICK_Identity;
}
+ SCS.setToType(1, FromType);
QualType CanonFrom;
QualType CanonTo;
@@ -740,13 +742,13 @@
CanonFrom = CanonTo;
}
}
+ SCS.setToType(2, FromType);
// If we have not converted the argument type to the parameter type,
// this is a bad conversion sequence.
if (CanonFrom != CanonTo)
return false;
- SCS.setToType(FromType);
return true;
}
@@ -1605,7 +1607,7 @@
User.After.setAsIdentityConversion();
User.After.setFromType(
ThisType->getAs<PointerType>()->getPointeeType());
- User.After.setToType(ToType);
+ User.After.setAllToTypes(ToType);
return OR_Success;
} else if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
@@ -1722,6 +1724,43 @@
return ImplicitConversionSequence::Indistinguishable;
}
+// Per 13.3.3.2p3, compare the given standard conversion sequences to
+// determine if one is a proper subset of the other.
+static ImplicitConversionSequence::CompareKind
+compareStandardConversionSubsets(ASTContext &Context,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2) {
+ ImplicitConversionSequence::CompareKind Result
+ = ImplicitConversionSequence::Indistinguishable;
+
+ if (SCS1.Second != SCS2.Second) {
+ if (SCS1.Second == ICK_Identity)
+ Result = ImplicitConversionSequence::Better;
+ else if (SCS2.Second == ICK_Identity)
+ Result = ImplicitConversionSequence::Worse;
+ else
+ return ImplicitConversionSequence::Indistinguishable;
+ } else if (!Context.hasSameType(SCS1.getToType(1), SCS2.getToType(1)))
+ return ImplicitConversionSequence::Indistinguishable;
+
+ if (SCS1.Third == SCS2.Third) {
+ return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result
+ : ImplicitConversionSequence::Indistinguishable;
+ }
+
+ if (SCS1.Third == ICK_Identity)
+ return Result == ImplicitConversionSequence::Worse
+ ? ImplicitConversionSequence::Indistinguishable
+ : ImplicitConversionSequence::Better;
+
+ if (SCS2.Third == ICK_Identity)
+ return Result == ImplicitConversionSequence::Better
+ ? ImplicitConversionSequence::Indistinguishable
+ : ImplicitConversionSequence::Worse;
+
+ return ImplicitConversionSequence::Indistinguishable;
+}
+
/// CompareStandardConversionSequences - Compare two standard
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2p3).
@@ -1737,21 +1776,9 @@
// excluding any Lvalue Transformation; the identity conversion
// sequence is considered to be a subsequence of any
// non-identity conversion sequence) or, if not that,
- if (SCS1.Second == SCS2.Second && SCS1.Third == SCS2.Third)
- // Neither is a proper subsequence of the other. Do nothing.
- ;
- else if ((SCS1.Second == ICK_Identity && SCS1.Third == SCS2.Third) ||
- (SCS1.Third == ICK_Identity && SCS1.Second == SCS2.Second) ||
- (SCS1.Second == ICK_Identity &&
- SCS1.Third == ICK_Identity))
- // SCS1 is a proper subsequence of SCS2.
- return ImplicitConversionSequence::Better;
- else if ((SCS2.Second == ICK_Identity && SCS2.Third == SCS1.Third) ||
- (SCS2.Third == ICK_Identity && SCS2.Second == SCS1.Second) ||
- (SCS2.Second == ICK_Identity &&
- SCS2.Third == ICK_Identity))
- // SCS2 is a proper subsequence of SCS1.
- return ImplicitConversionSequence::Worse;
+ if (ImplicitConversionSequence::CompareKind CK
+ = compareStandardConversionSubsets(Context, SCS1, SCS2))
+ return CK;
// -- the rank of S1 is better than the rank of S2 (by the rules
// defined below), or, if not that,
@@ -1856,8 +1883,8 @@
// top-level cv-qualifiers, and the type to which the reference
// initialized by S2 refers is more cv-qualified than the type
// to which the reference initialized by S1 refers.
- QualType T1 = SCS1.getToType();
- QualType T2 = SCS2.getToType();
+ QualType T1 = SCS1.getToType(2);
+ QualType T2 = SCS2.getToType(2);
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
Qualifiers T1Quals, T2Quals;
@@ -1898,8 +1925,8 @@
// FIXME: the example in the standard doesn't use a qualification
// conversion (!)
- QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
- QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+ QualType T1 = SCS1.getToType(2);
+ QualType T2 = SCS2.getToType(2);
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
Qualifiers T1Quals, T2Quals;
@@ -1988,9 +2015,9 @@
Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
QualType FromType1 = SCS1.getFromType();
- QualType ToType1 = SCS1.getToType();
+ QualType ToType1 = SCS1.getToType(1);
QualType FromType2 = SCS2.getFromType();
- QualType ToType2 = SCS2.getToType();
+ QualType ToType2 = SCS2.getToType(1);
// Adjust the types we're converting from via the array-to-pointer
// conversion, if we need to.
@@ -2280,7 +2307,7 @@
// Success. Mark this as a reference binding.
ICS.setStandard();
ICS.Standard.setFromType(FromType);
- ICS.Standard.setToType(ImplicitParamType);
+ ICS.Standard.setAllToTypes(ImplicitParamType);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding = true;
ICS.Standard.RRefBinding = false;
@@ -2767,7 +2794,7 @@
Candidate.IgnoreObjectArgument = false;
Candidate.FinalConversion.setAsIdentityConversion();
Candidate.FinalConversion.setFromType(Conversion->getConversionType());
- Candidate.FinalConversion.setToType(ToType);
+ Candidate.FinalConversion.setAllToTypes(ToType);
// Determine the implicit conversion sequence for the implicit
// object parameter.
Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=94660&r1=94659&r2=94660&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Tue Jan 26 21:51:04 2010
@@ -139,9 +139,10 @@
/// QualType.
void *FromTypePtr;
- /// ToType - The type that this conversion is converting to. This
- /// is an opaque pointer that can be translated into a QualType.
- void *ToTypePtr;
+ /// ToType - The types that this conversion is converting to in
+ /// each step. This is an opaque pointer that can be translated
+ /// into a QualType.
+ void *ToTypePtrs[3];
/// CopyConstructor - The copy constructor that is used to perform
/// this conversion, when the conversion is actually just the
@@ -151,12 +152,22 @@
CXXConstructorDecl *CopyConstructor;
void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
- void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+ void setToType(unsigned Idx, QualType T) {
+ assert(Idx < 3 && "To type index is out of range");
+ ToTypePtrs[Idx] = T.getAsOpaquePtr();
+ }
+ void setAllToTypes(QualType T) {
+ ToTypePtrs[0] = T.getAsOpaquePtr();
+ ToTypePtrs[1] = ToTypePtrs[0];
+ ToTypePtrs[2] = ToTypePtrs[0];
+ }
+
QualType getFromType() const {
return QualType::getFromOpaquePtr(FromTypePtr);
}
- QualType getToType() const {
- return QualType::getFromOpaquePtr(ToTypePtr);
+ QualType getToType(unsigned Idx) const {
+ assert(Idx < 3 && "To type index is out of range");
+ return QualType::getFromOpaquePtr(ToTypePtrs[Idx]);
}
void setAsIdentityConversion();
Modified: cfe/trunk/test/SemaCXX/overload-call-copycon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call-copycon.cpp?rev=94660&r1=94659&r2=94660&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overload-call-copycon.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-call-copycon.cpp Tue Jan 26 21:51:04 2010
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only %s -Wnon-pod-varargs
+// RUN: %clang_cc1 -fsyntax-only -verify %s -Wnon-pod-varargs
class X { };
int& copycon(X x);
@@ -37,7 +37,6 @@
float& f1 = copycon3(bc); // expected-warning {{cannot pass object of non-POD type}}
}
-
class C : public B { };
float& copycon4(A a);
Modified: cfe/trunk/test/SemaCXX/overload-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=94660&r1=94659&r2=94660&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overload-call.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-call.cpp Tue Jan 26 21:51:04 2010
@@ -347,3 +347,15 @@
foo(*P); // expected-error {{no matching function for call to 'foo'}}
}
}
+
+namespace DerivedToBaseVsVoid {
+ struct A { };
+ struct B : A { };
+
+ float &f(void *);
+ int &f(const A*);
+
+ void g(B *b) {
+ int &ir = f(b);
+ }
+}
More information about the cfe-commits
mailing list