summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r--lib/Sema/SemaOverload.cpp3982
1 files changed, 2535 insertions, 1447 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 11b4bb3..6fb789c 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -23,8 +23,10 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
@@ -32,9 +34,20 @@
namespace clang {
using namespace sema;
+/// A convenience routine for creating a decayed reference to a
+/// function.
+static Expr *
+CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn,
+ SourceLocation Loc = SourceLocation()) {
+ Expr *E = new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc);
+ S.DefaultFunctionArrayConversion(E);
+ return E;
+}
+
static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
bool InOverloadResolution,
- StandardConversionSequence &SCS);
+ StandardConversionSequence &SCS,
+ bool CStyle);
static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
@@ -158,7 +171,10 @@ void StandardConversionSequence::setAsIdentityConversion() {
DeprecatedStringLiteralToCharPtr = false;
ReferenceBinding = false;
DirectBinding = false;
- RRefBinding = false;
+ IsLvalueReference = true;
+ BindsToFunctionLvalue = false;
+ BindsToRvalue = false;
+ BindsImplicitObjectArgumentWithoutRefQualifier = false;
CopyConstructor = 0;
}
@@ -189,6 +205,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const {
(getFromType()->isPointerType() ||
getFromType()->isObjCObjectPointerType() ||
getFromType()->isBlockPointerType() ||
+ getFromType()->isNullPtrType() ||
First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
return true;
@@ -323,7 +340,7 @@ namespace {
TemplateArgument SecondArg;
};
}
-
+
/// \brief Convert from Sema's representation of template deduction information
/// to the form used in overload-candidate information.
OverloadCandidate::DeductionFailureInfo
@@ -339,12 +356,12 @@ static MakeDeductionFailureInfo(ASTContext &Context,
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
break;
-
+
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
Result.Data = Info.Param.getOpaqueValue();
break;
-
+
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified: {
// FIXME: Should allocate from normal heap so that we can free this later.
@@ -355,16 +372,16 @@ static MakeDeductionFailureInfo(ASTContext &Context,
Result.Data = Saved;
break;
}
-
+
case Sema::TDK_SubstitutionFailure:
Result.Data = Info.take();
break;
-
+
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
- break;
+ break;
}
-
+
return Result;
}
@@ -377,7 +394,7 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
break;
-
+
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
// FIXME: Destroy the data?
@@ -388,15 +405,15 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
// FIXME: Destroy the template arugment list?
Data = 0;
break;
-
+
// Unhandled
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
}
}
-
-TemplateParameter
+
+TemplateParameter
OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
@@ -405,24 +422,24 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_TooFewArguments:
case Sema::TDK_SubstitutionFailure:
return TemplateParameter();
-
+
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
- return TemplateParameter::getFromOpaqueValue(Data);
+ return TemplateParameter::getFromOpaqueValue(Data);
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
return static_cast<DFIParamWithArguments*>(Data)->Param;
-
+
// Unhandled
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
}
-
+
return TemplateParameter();
}
-
+
TemplateArgumentList *
OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
@@ -438,7 +455,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
-
+
// Unhandled
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
@@ -461,16 +478,16 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
- return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;
+ return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;
// Unhandled
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
}
-
+
return 0;
-}
+}
const TemplateArgument *
OverloadCandidate::DeductionFailureInfo::getSecondArg() {
@@ -493,7 +510,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
case Sema::TDK_FailedOverloadResolution:
break;
}
-
+
return 0;
}
@@ -501,7 +518,7 @@ void OverloadCandidateSet::clear() {
inherited::clear();
Functions.clear();
}
-
+
// IsOverload - Determine whether the given New declaration is an
// overload of the declarations in Old. This routine returns false if
// New and Old cannot be overloaded, e.g., if New has the same
@@ -582,10 +599,12 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
Match = *I;
return Ovl_Match;
}
- } else if (isa<UsingDecl>(OldD) || isa<TagDecl>(OldD)) {
+ } else if (isa<UsingDecl>(OldD)) {
// We can overload with these, which can show up when doing
// redeclaration checks for UsingDecls.
assert(Old.getLookupKind() == LookupUsingDeclName);
+ } else if (isa<TagDecl>(OldD)) {
+ // We can always overload with tags by hiding them.
} else if (isa<UnresolvedUsingValueDecl>(OldD)) {
// Optimistically assume that an unresolved using decl will
// overload; if it doesn't, we'll have to diagnose during
@@ -632,8 +651,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
isa<FunctionNoProtoType>(NewQType.getTypePtr()))
return false;
- FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
- FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
+ const FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
+ const FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
// The signature of a function includes the types of its
// parameters (C++ 1.3.10), which includes the presence or absence
@@ -664,7 +683,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
return true;
// If the function is a class member, its signature includes the
- // cv-qualifiers (if any) on the function itself.
+ // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself.
//
// As part of this, also check whether one of the member functions
// is static, in which case they are not overloads (C++
@@ -675,9 +694,26 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
if (OldMethod && NewMethod &&
!OldMethod->isStatic() && !NewMethod->isStatic() &&
- OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
+ (OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers() ||
+ OldMethod->getRefQualifier() != NewMethod->getRefQualifier())) {
+ if (!UseUsingDeclRules &&
+ OldMethod->getRefQualifier() != NewMethod->getRefQualifier() &&
+ (OldMethod->getRefQualifier() == RQ_None ||
+ NewMethod->getRefQualifier() == RQ_None)) {
+ // C++0x [over.load]p2:
+ // - Member function declarations with the same name and the same
+ // parameter-type-list as well as member function template
+ // declarations with the same name, the same parameter-type-list, and
+ // the same template parameter lists cannot be overloaded if any of
+ // them, but not all, have a ref-qualifier (8.3.5).
+ Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
+ << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
+ Diag(OldMethod->getLocation(), diag::note_previous_declaration);
+ }
+
return true;
-
+ }
+
// The signatures match; this is not an overload.
return false;
}
@@ -708,11 +744,12 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
static ImplicitConversionSequence
TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
- bool AllowExplicit,
- bool InOverloadResolution) {
+ bool AllowExplicit,
+ bool InOverloadResolution,
+ bool CStyle) {
ImplicitConversionSequence ICS;
if (IsStandardConversion(S, From, ToType, InOverloadResolution,
- ICS.Standard)) {
+ ICS.Standard, CStyle)) {
ICS.setStandard();
return ICS;
}
@@ -737,20 +774,20 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
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 (!S.Context.hasSameUnqualifiedType(FromType, ToType))
ICS.Standard.Second = ICK_Derived_To_Base;
-
+
return ICS;
}
-
+
if (SuppressUserConversions) {
// We're not in the case above, so there is no conversion that
// we can perform.
@@ -823,12 +860,14 @@ bool Sema::TryImplicitConversion(InitializationSequence &Sequence,
Expr *Initializer,
bool SuppressUserConversions,
bool AllowExplicitConversions,
- bool InOverloadResolution) {
+ bool InOverloadResolution,
+ bool CStyle) {
ImplicitConversionSequence ICS
= clang::TryImplicitConversion(*this, Initializer, Entity.getType(),
SuppressUserConversions,
- AllowExplicitConversions,
- InOverloadResolution);
+ AllowExplicitConversions,
+ InOverloadResolution,
+ CStyle);
if (ICS.isBad()) return true;
// Perform the actual conversion.
@@ -856,34 +895,66 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
ICS = clang::TryImplicitConversion(*this, From, ToType,
/*SuppressUserConversions=*/false,
AllowExplicit,
- /*InOverloadResolution=*/false);
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false);
return PerformImplicitConversion(From, ToType, ICS, Action);
}
-
-/// \brief Determine whether the conversion from FromType to ToType is a valid
+
+/// \brief Determine whether the conversion from FromType to ToType is a valid
/// conversion that strips "noreturn" off the nested function type.
-static bool IsNoReturnConversion(ASTContext &Context, QualType FromType,
+static bool IsNoReturnConversion(ASTContext &Context, QualType FromType,
QualType ToType, QualType &ResultTy) {
if (Context.hasSameUnqualifiedType(FromType, ToType))
return false;
-
- // Strip the noreturn off the type we're converting from; noreturn can
- // safely be removed.
- FromType = Context.getNoReturnType(FromType, false);
- if (!Context.hasSameUnqualifiedType(FromType, ToType))
- return false;
- ResultTy = FromType;
+ // Permit the conversion F(t __attribute__((noreturn))) -> F(t)
+ // where F adds one of the following at most once:
+ // - a pointer
+ // - a member pointer
+ // - a block pointer
+ CanQualType CanTo = Context.getCanonicalType(ToType);
+ CanQualType CanFrom = Context.getCanonicalType(FromType);
+ Type::TypeClass TyClass = CanTo->getTypeClass();
+ if (TyClass != CanFrom->getTypeClass()) return false;
+ if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) {
+ if (TyClass == Type::Pointer) {
+ CanTo = CanTo.getAs<PointerType>()->getPointeeType();
+ CanFrom = CanFrom.getAs<PointerType>()->getPointeeType();
+ } else if (TyClass == Type::BlockPointer) {
+ CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType();
+ CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType();
+ } else if (TyClass == Type::MemberPointer) {
+ CanTo = CanTo.getAs<MemberPointerType>()->getPointeeType();
+ CanFrom = CanFrom.getAs<MemberPointerType>()->getPointeeType();
+ } else {
+ return false;
+ }
+
+ TyClass = CanTo->getTypeClass();
+ if (TyClass != CanFrom->getTypeClass()) return false;
+ if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto)
+ return false;
+ }
+
+ const FunctionType *FromFn = cast<FunctionType>(CanFrom);
+ FunctionType::ExtInfo EInfo = FromFn->getExtInfo();
+ if (!EInfo.getNoReturn()) return false;
+
+ FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false));
+ assert(QualType(FromFn, 0).isCanonical());
+ if (QualType(FromFn, 0) != CanTo) return false;
+
+ ResultTy = ToType;
return true;
}
-
+
/// \brief Determine whether the conversion from FromType to ToType is a valid
/// vector conversion.
///
/// \param ICK Will be set to the vector conversion kind, if this is a vector
/// conversion.
-static bool IsVectorConversion(ASTContext &Context, QualType FromType,
- QualType ToType, ImplicitConversionKind &ICK) {
+static bool IsVectorConversion(ASTContext &Context, QualType FromType,
+ QualType ToType, ImplicitConversionKind &ICK) {
// We need at least one of these types to be a vector type to have a vector
// conversion.
if (!ToType->isVectorType() && !FromType->isVectorType())
@@ -899,7 +970,7 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType,
// identity conversion.
if (FromType->isExtVectorType())
return false;
-
+
// Vector splat from any arithmetic type to a vector.
if (FromType->isArithmeticType()) {
ICK = ICK_Vector_Splat;
@@ -922,7 +993,7 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType,
return false;
}
-
+
/// IsStandardConversion - Determines whether there is a standard
/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the
/// expression From to the type ToType. Standard conversion sequences
@@ -933,9 +1004,10 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType,
/// routine will return false and the value of SCS is unspecified.
static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
bool InOverloadResolution,
- StandardConversionSequence &SCS) {
+ StandardConversionSequence &SCS,
+ bool CStyle) {
QualType FromType = From->getType();
-
+
// Standard conversions (C++ [conv])
SCS.setAsIdentityConversion();
SCS.DeprecatedStringLiteralToCharPtr = false;
@@ -959,38 +1031,53 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
if (FromType == S.Context.OverloadTy) {
DeclAccessPair AccessPair;
if (FunctionDecl *Fn
- = S.ResolveAddressOfOverloadedFunction(From, ToType, false,
+ = S.ResolveAddressOfOverloadedFunction(From, ToType, false,
AccessPair)) {
// We were able to resolve the address of the overloaded function,
// so we can convert to the type of that function.
FromType = Fn->getType();
+
+ // we can sometimes resolve &foo<int> regardless of ToType, so check
+ // if the type matches (identity) or we are converting to bool
+ if (!S.Context.hasSameUnqualifiedType(
+ S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
+ QualType resultTy;
+ // if the function type matches except for [[noreturn]], it's ok
+ if (!IsNoReturnConversion(S.Context, FromType,
+ S.ExtractUnqualifiedFunctionType(ToType), resultTy))
+ // otherwise, only a boolean conversion is standard
+ if (!ToType->isBooleanType())
+ return false;
+
+ }
+
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
if (!Method->isStatic()) {
- Type *ClassType
+ const Type *ClassType
= S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
FromType = S.Context.getMemberPointerType(FromType, ClassType);
}
}
-
+
// If the "from" expression takes the address of the overloaded
// function, update the type of the resulting expression accordingly.
if (FromType->getAs<FunctionType>())
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(From->IgnoreParens()))
if (UnOp->getOpcode() == UO_AddrOf)
FromType = S.Context.getPointerType(FromType);
-
+
// Check that we've computed the proper type after overload resolution.
assert(S.Context.hasSameType(FromType,
S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
} else {
return false;
}
- }
+ }
// Lvalue-to-rvalue conversion (C++ 4.1):
// An lvalue (3.10) of a non-function, non-array type T can be
// converted to an rvalue.
- Expr::isLvalueResult argIsLvalue = From->isLvalue(S.Context);
- if (argIsLvalue == Expr::LV_Valid &&
+ bool argIsLValue = From->isLValue();
+ if (argIsLValue &&
!FromType->isFunctionType() && !FromType->isArrayType() &&
S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) {
SCS.First = ICK_Lvalue_To_Rvalue;
@@ -1022,7 +1109,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
SCS.setAllToTypes(FromType);
return true;
}
- } else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) {
+ } else if (FromType->isFunctionType() && argIsLValue) {
// Function-to-pointer conversion (C++ 4.3).
SCS.First = ICK_Function_To_Pointer;
@@ -1060,17 +1147,26 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Complex promotion (Clang extension)
SCS.Second = ICK_Complex_Promotion;
FromType = ToType.getUnqualifiedType();
- } else if (FromType->isIntegralOrEnumerationType() &&
+ } else if (ToType->isBooleanType() &&
+ (FromType->isArithmeticType() ||
+ FromType->isAnyPointerType() ||
+ FromType->isBlockPointerType() ||
+ FromType->isMemberPointerType() ||
+ FromType->isNullPtrType())) {
+ // Boolean conversions (C++ 4.12).
+ SCS.Second = ICK_Boolean_Conversion;
+ FromType = S.Context.BoolTy;
+ } else if (FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isIntegralType(S.Context)) {
// Integral conversions (C++ 4.7).
SCS.Second = ICK_Integral_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if (FromType->isComplexType() && ToType->isComplexType()) {
+ } else if (FromType->isAnyComplexType() && ToType->isComplexType()) {
// Complex conversions (C99 6.3.1.6)
SCS.Second = ICK_Complex_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if ((FromType->isComplexType() && ToType->isArithmeticType()) ||
- (ToType->isComplexType() && FromType->isArithmeticType())) {
+ } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) ||
+ (ToType->isAnyComplexType() && FromType->isArithmeticType())) {
// Complex-real conversions (C99 6.3.1.7)
SCS.Second = ICK_Complex_Real;
FromType = ToType.getUnqualifiedType();
@@ -1078,32 +1174,24 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Floating point conversions (C++ 4.8).
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if ((FromType->isRealFloatingType() &&
- ToType->isIntegralType(S.Context) && !ToType->isBooleanType()) ||
- (FromType->isIntegralOrEnumerationType() &&
+ } else if ((FromType->isRealFloatingType() &&
+ ToType->isIntegralType(S.Context)) ||
+ (FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isRealFloatingType())) {
// Floating-integral conversions (C++ 4.9).
SCS.Second = ICK_Floating_Integral;
FromType = ToType.getUnqualifiedType();
+ } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) {
+ SCS.Second = ICK_Block_Pointer_Conversion;
} else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution,
FromType, IncompatibleObjC)) {
// Pointer conversions (C++ 4.10).
SCS.Second = ICK_Pointer_Conversion;
SCS.IncompatibleObjC = IncompatibleObjC;
- } else if (S.IsMemberPointerConversion(From, FromType, ToType,
+ } else if (S.IsMemberPointerConversion(From, FromType, ToType,
InOverloadResolution, FromType)) {
// Pointer to member conversions (4.11).
SCS.Second = ICK_Pointer_Member;
- } else if (ToType->isBooleanType() &&
- (FromType->isArithmeticType() ||
- FromType->isEnumeralType() ||
- FromType->isAnyPointerType() ||
- FromType->isBlockPointerType() ||
- FromType->isMemberPointerType() ||
- FromType->isNullPtrType())) {
- // Boolean conversions (C++ 4.12).
- SCS.Second = ICK_Boolean_Conversion;
- FromType = S.Context.BoolTy;
} else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) {
SCS.Second = SecondICK;
FromType = ToType.getUnqualifiedType();
@@ -1124,7 +1212,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
QualType CanonFrom;
QualType CanonTo;
// The third conversion can be a qualification conversion (C++ 4p1).
- if (S.IsQualificationConversion(FromType, ToType)) {
+ if (S.IsQualificationConversion(FromType, ToType, CStyle)) {
SCS.Third = ICK_Qualification;
FromType = ToType;
CanonFrom = S.Context.getCanonicalType(FromType);
@@ -1139,7 +1227,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// a conversion. [...]
CanonFrom = S.Context.getCanonicalType(FromType);
CanonTo = S.Context.getCanonicalType(ToType);
- if (CanonFrom.getLocalUnqualifiedType()
+ if (CanonFrom.getLocalUnqualifiedType()
== CanonTo.getLocalUnqualifiedType() &&
(CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()
|| CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr())) {
@@ -1187,23 +1275,47 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
return To->getKind() == BuiltinType::UInt;
}
- // An rvalue of type wchar_t (3.9.1) or an enumeration type (7.2)
- // can be converted to an rvalue of the first of the following types
- // that can represent all the values of its underlying type: int,
- // unsigned int, long, or unsigned long (C++ 4.5p2).
+ // C++0x [conv.prom]p3:
+ // A prvalue of an unscoped enumeration type whose underlying type is not
+ // fixed (7.2) can be converted to an rvalue a prvalue of the first of the
+ // following types that can represent all the values of the enumeration
+ // (i.e., the values in the range bmin to bmax as described in 7.2): int,
+ // unsigned int, long int, unsigned long int, long long int, or unsigned
+ // long long int. If none of the types in that list can represent all the
+ // values of the enumeration, an rvalue a prvalue of an unscoped enumeration
+ // type can be converted to an rvalue a prvalue of the extended integer type
+ // with lowest integer conversion rank (4.13) greater than the rank of long
+ // long in which all the values of the enumeration can be represented. If
+ // there are two such extended types, the signed one is chosen.
+ if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) {
+ // C++0x 7.2p9: Note that this implicit enum to int conversion is not
+ // provided for a scoped enumeration.
+ if (FromEnumType->getDecl()->isScoped())
+ return false;
- // We pre-calculate the promotion type for enum types.
- if (const EnumType *FromEnumType = FromType->getAs<EnumType>())
- if (ToType->isIntegerType())
+ // We have already pre-calculated the promotion type, so this is trivial.
+ if (ToType->isIntegerType() &&
+ !RequireCompleteType(From->getLocStart(), FromType, PDiag()))
return Context.hasSameUnqualifiedType(ToType,
FromEnumType->getDecl()->getPromotionType());
+ }
- if (FromType->isWideCharType() && ToType->isIntegerType()) {
+ // C++0x [conv.prom]p2:
+ // A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) can be converted
+ // to an rvalue a prvalue of the first of the following types that can
+ // represent all the values of its underlying type: int, unsigned int,
+ // long int, unsigned long int, long long int, or unsigned long long int.
+ // If none of the types in that list can represent all the values of its
+ // underlying type, an rvalue a prvalue of type char16_t, char32_t,
+ // or wchar_t can be converted to an rvalue a prvalue of its underlying
+ // type.
+ if (FromType->isAnyCharacterType() && !FromType->isCharType() &&
+ ToType->isIntegerType()) {
// Determine whether the type we're converting from is signed or
// unsigned.
bool FromIsSigned;
uint64_t FromSize = Context.getTypeSize(FromType);
-
+
// FIXME: Is wchar_t signed or unsigned? We assume it's signed for now.
FromIsSigned = true;
@@ -1321,10 +1433,19 @@ bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) {
/// if non-empty, will be a pointer to ToType that may or may not have
/// the right set of qualifiers on its pointee.
static QualType
-BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
+BuildSimilarlyQualifiedPointerType(const Type *FromPtr,
QualType ToPointee, QualType ToType,
ASTContext &Context) {
- QualType CanonFromPointee = Context.getCanonicalType(FromPtr->getPointeeType());
+ assert((FromPtr->getTypeClass() == Type::Pointer ||
+ FromPtr->getTypeClass() == Type::ObjCObjectPointer) &&
+ "Invalid similarly-qualified pointer type");
+
+ /// \brief Conversions to 'id' subsume cv-qualifier conversions.
+ if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType())
+ return ToType.getUnqualifiedType();
+
+ QualType CanonFromPointee
+ = Context.getCanonicalType(FromPtr->getPointeeType());
QualType CanonToPointee = Context.getCanonicalType(ToPointee);
Qualifiers Quals = CanonFromPointee.getQualifiers();
@@ -1336,34 +1457,20 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
// Build a pointer to ToPointee. It has the right qualifiers
// already.
+ if (isa<ObjCObjectPointerType>(ToType))
+ return Context.getObjCObjectPointerType(ToPointee);
return Context.getPointerType(ToPointee);
}
// Just build a canonical type that has the right qualifiers.
- return Context.getPointerType(
- Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(),
- Quals));
-}
+ QualType QualifiedCanonToPointee
+ = Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals);
-/// BuildSimilarlyQualifiedObjCObjectPointerType - In a pointer conversion from
-/// the FromType, which is an objective-c pointer, to ToType, which may or may
-/// not have the right set of qualifiers.
-static QualType
-BuildSimilarlyQualifiedObjCObjectPointerType(QualType FromType,
- QualType ToType,
- ASTContext &Context) {
- QualType CanonFromType = Context.getCanonicalType(FromType);
- QualType CanonToType = Context.getCanonicalType(ToType);
- Qualifiers Quals = CanonFromType.getQualifiers();
-
- // Exact qualifier match -> return the pointer type we're converting to.
- if (CanonToType.getLocalQualifiers() == Quals)
- return ToType;
-
- // Just build a canonical type that has the right qualifiers.
- return Context.getQualifiedType(CanonToType.getLocalUnqualifiedType(), Quals);
+ if (isa<ObjCObjectPointerType>(ToType))
+ return Context.getObjCObjectPointerType(QualifiedCanonToPointee);
+ return Context.getPointerType(QualifiedCanonToPointee);
}
-
+
static bool isNullPointerConstantForConversion(Expr *Expr,
bool InOverloadResolution,
ASTContext &Context) {
@@ -1399,7 +1506,8 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
QualType& ConvertedType,
bool &IncompatibleObjC) {
IncompatibleObjC = false;
- if (isObjCPointerConversion(FromType, ToType, ConvertedType, IncompatibleObjC))
+ if (isObjCPointerConversion(FromType, ToType, ConvertedType,
+ IncompatibleObjC))
return true;
// Conversion from a null pointer constant to any Objective-C pointer type.
@@ -1441,14 +1549,15 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
return true;
}
- // Beyond this point, both types need to be pointers
+ // Beyond this point, both types need to be pointers
// , including objective-c pointers.
QualType ToPointeeType = ToTypePtr->getPointeeType();
if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) {
- ConvertedType = BuildSimilarlyQualifiedObjCObjectPointerType(FromType,
+ ConvertedType = BuildSimilarlyQualifiedPointerType(
+ FromType->getAs<ObjCObjectPointerType>(),
+ ToPointeeType,
ToType, Context);
return true;
-
}
const PointerType *FromTypePtr = FromType->getAs<PointerType>();
if (!FromTypePtr)
@@ -1456,7 +1565,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
QualType FromPointeeType = FromTypePtr->getPointeeType();
- // If the unqualified pointee types are the same, this can't be a
+ // If the unqualified pointee types are the same, this can't be a
// pointer conversion, so don't do all of the work below.
if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType))
return false;
@@ -1517,13 +1626,20 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
bool &IncompatibleObjC) {
if (!getLangOptions().ObjC1)
return false;
-
+
// First, we handle all conversions on ObjC object pointer types.
- const ObjCObjectPointerType* ToObjCPtr = ToType->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType* ToObjCPtr =
+ ToType->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *FromObjCPtr =
FromType->getAs<ObjCObjectPointerType>();
if (ToObjCPtr && FromObjCPtr) {
+ // If the pointee types are the same (ignoring qualifications),
+ // then this is not a pointer conversion.
+ if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(),
+ FromObjCPtr->getPointeeType()))
+ return false;
+
// Objective C++: We're able to convert between "id" or "Class" and a
// pointer to any interface (in both directions).
if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
@@ -1547,7 +1663,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
!ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs(
FromObjCPtr->getPointeeType()))
return false;
- ConvertedType = ToType;
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
+ ToObjCPtr->getPointeeType(),
+ ToType, Context);
return true;
}
@@ -1556,7 +1674,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
// interfaces, which is permitted. However, we're going to
// complain about it.
IncompatibleObjC = true;
- ConvertedType = FromType;
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
+ ToObjCPtr->getPointeeType(),
+ ToType, Context);
return true;
}
}
@@ -1564,7 +1684,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
QualType ToPointeeType;
if (const PointerType *ToCPtr = ToType->getAs<PointerType>())
ToPointeeType = ToCPtr->getPointeeType();
- else if (const BlockPointerType *ToBlockPtr =
+ else if (const BlockPointerType *ToBlockPtr =
ToType->getAs<BlockPointerType>()) {
// Objective C++: We're able to convert from a pointer to any object
// to a block pointer type.
@@ -1574,9 +1694,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
}
ToPointeeType = ToBlockPtr->getPointeeType();
}
- else if (FromType->getAs<BlockPointerType>() &&
+ else if (FromType->getAs<BlockPointerType>() &&
ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) {
- // Objective C++: We're able to convert from a block pointer type to a
+ // Objective C++: We're able to convert from a block pointer type to a
// pointer to any object.
ConvertedType = ToType;
return true;
@@ -1587,7 +1707,8 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
QualType FromPointeeType;
if (const PointerType *FromCPtr = FromType->getAs<PointerType>())
FromPointeeType = FromCPtr->getPointeeType();
- else if (const BlockPointerType *FromBlockPtr = FromType->getAs<BlockPointerType>())
+ else if (const BlockPointerType *FromBlockPtr =
+ FromType->getAs<BlockPointerType>())
FromPointeeType = FromBlockPtr->getPointeeType();
else
return false;
@@ -1599,7 +1720,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
IncompatibleObjC)) {
// We always complain about this conversion.
IncompatibleObjC = true;
- ConvertedType = ToType;
+ ConvertedType = Context.getPointerType(ConvertedType);
return true;
}
// Allow conversion of pointee being objective-c pointer to another one;
@@ -1608,10 +1729,10 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
ToPointeeType->getAs<ObjCObjectPointerType>() &&
isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
IncompatibleObjC)) {
- ConvertedType = ToType;
+ ConvertedType = Context.getPointerType(ConvertedType);
return true;
}
-
+
// If we have pointers to functions or blocks, check whether the only
// differences in the argument and result types are in Objective-C
// pointer conversions. If so, we permit the conversion (but
@@ -1677,17 +1798,102 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
return false;
}
-
+
+bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
+ QualType& ConvertedType) {
+ QualType ToPointeeType;
+ if (const BlockPointerType *ToBlockPtr =
+ ToType->getAs<BlockPointerType>())
+ ToPointeeType = ToBlockPtr->getPointeeType();
+ else
+ return false;
+
+ QualType FromPointeeType;
+ if (const BlockPointerType *FromBlockPtr =
+ FromType->getAs<BlockPointerType>())
+ FromPointeeType = FromBlockPtr->getPointeeType();
+ else
+ return false;
+ // We have pointer to blocks, check whether the only
+ // differences in the argument and result types are in Objective-C
+ // pointer conversions. If so, we permit the conversion.
+
+ const FunctionProtoType *FromFunctionType
+ = FromPointeeType->getAs<FunctionProtoType>();
+ const FunctionProtoType *ToFunctionType
+ = ToPointeeType->getAs<FunctionProtoType>();
+
+ if (!FromFunctionType || !ToFunctionType)
+ return false;
+
+ if (Context.hasSameType(FromPointeeType, ToPointeeType))
+ return true;
+
+ // Perform the quick checks that will tell us whether these
+ // function types are obviously different.
+ if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() ||
+ FromFunctionType->isVariadic() != ToFunctionType->isVariadic())
+ return false;
+
+ FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo();
+ FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo();
+ if (FromEInfo != ToEInfo)
+ return false;
+
+ bool IncompatibleObjC = false;
+ if (Context.hasSameType(FromFunctionType->getResultType(),
+ ToFunctionType->getResultType())) {
+ // Okay, the types match exactly. Nothing to do.
+ } else {
+ QualType RHS = FromFunctionType->getResultType();
+ QualType LHS = ToFunctionType->getResultType();
+ if ((!getLangOptions().CPlusPlus || !RHS->isRecordType()) &&
+ !RHS.hasQualifiers() && LHS.hasQualifiers())
+ LHS = LHS.getUnqualifiedType();
+
+ if (Context.hasSameType(RHS,LHS)) {
+ // OK exact match.
+ } else if (isObjCPointerConversion(RHS, LHS,
+ ConvertedType, IncompatibleObjC)) {
+ if (IncompatibleObjC)
+ return false;
+ // Okay, we have an Objective-C pointer conversion.
+ }
+ else
+ return false;
+ }
+
+ // Check argument types.
+ for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
+ ArgIdx != NumArgs; ++ArgIdx) {
+ IncompatibleObjC = false;
+ QualType FromArgType = FromFunctionType->getArgType(ArgIdx);
+ QualType ToArgType = ToFunctionType->getArgType(ArgIdx);
+ if (Context.hasSameType(FromArgType, ToArgType)) {
+ // Okay, the types match exactly. Nothing to do.
+ } else if (isObjCPointerConversion(ToArgType, FromArgType,
+ ConvertedType, IncompatibleObjC)) {
+ if (IncompatibleObjC)
+ return false;
+ // Okay, we have an Objective-C pointer conversion.
+ } else
+ // Argument types are too different. Abort.
+ return false;
+ }
+ ConvertedType = ToType;
+ return true;
+}
+
/// FunctionArgTypesAreEqual - This routine checks two function proto types
/// for equlity of their argument types. Caller has already checked that
/// they have same number of arguments. This routine assumes that Objective-C
/// pointer types which only differ in their protocol qualifiers are equal.
-bool Sema::FunctionArgTypesAreEqual(FunctionProtoType* OldType,
- FunctionProtoType* NewType){
+bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType) {
if (!getLangOptions().ObjC1)
return std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
NewType->arg_type_begin());
-
+
for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
N = NewType->arg_type_begin(),
E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
@@ -1704,12 +1910,12 @@ bool Sema::FunctionArgTypesAreEqual(FunctionProtoType* OldType,
}
else if (const ObjCObjectPointerType *PTTo =
ToType->getAs<ObjCObjectPointerType>()) {
- if (const ObjCObjectPointerType *PTFr =
+ if (const ObjCObjectPointerType *PTFr =
FromType->getAs<ObjCObjectPointerType>())
if (PTTo->getInterfaceDecl() == PTFr->getInterfaceDecl())
continue;
}
- return false;
+ return false;
}
}
return true;
@@ -1726,10 +1932,13 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
CXXCastPath& BasePath,
bool IgnoreBaseAccess) {
QualType FromType = From->getType();
+ bool IsCStyleOrFunctionalCast = IgnoreBaseAccess;
+
+ Kind = CK_BitCast;
if (CXXBoolLiteralExpr* LitBool
= dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens()))
- if (LitBool->getValue() == false)
+ if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false)
Diag(LitBool->getExprLoc(), diag::warn_init_pointer_from_false)
<< ToType;
@@ -1747,13 +1956,13 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
From->getSourceRange(), &BasePath,
IgnoreBaseAccess))
return true;
-
+
// The conversion was successful.
Kind = CK_DerivedToBase;
}
}
if (const ObjCObjectPointerType *FromPtrType =
- FromType->getAs<ObjCObjectPointerType>())
+ FromType->getAs<ObjCObjectPointerType>()) {
if (const ObjCObjectPointerType *ToPtrType =
ToType->getAs<ObjCObjectPointerType>()) {
// Objective-C++ conversions are always okay.
@@ -1761,8 +1970,14 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
// Objective-C++ implicit conversions.
if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
return false;
-
+ }
}
+
+ // We shouldn't fall into this case unless it's valid for other
+ // reasons.
+ if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+ Kind = CK_NullToPointer;
+
return false;
}
@@ -1772,7 +1987,7 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
/// If so, returns true and places the converted type (that might differ from
/// ToType in its cv-qualifiers at some level) into ConvertedType.
bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
- QualType ToType,
+ QualType ToType,
bool InOverloadResolution,
QualType &ConvertedType) {
const MemberPointerType *ToTypePtr = ToType->getAs<MemberPointerType>();
@@ -1796,9 +2011,10 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
// where D is derived from B (C++ 4.11p2).
QualType FromClass(FromTypePtr->getClass(), 0);
QualType ToClass(ToTypePtr->getClass(), 0);
- // FIXME: What happens when these are dependent? Is this function even called?
- if (IsDerivedFrom(ToClass, FromClass)) {
+ if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
+ !RequireCompleteType(From->getLocStart(), ToClass, PDiag()) &&
+ IsDerivedFrom(ToClass, FromClass)) {
ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
ToClass.getTypePtr());
return true;
@@ -1806,7 +2022,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
return false;
}
-
+
/// CheckMemberPointerConversion - Check the member pointer conversion from the
/// expression From to the type ToType. This routine checks for ambiguous or
/// virtual or inaccessible base-to-derived member pointer conversions
@@ -1821,7 +2037,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
if (!FromPtrType) {
// This must be a null pointer to member pointer conversion
- assert(From->isNullPointerConstant(Context,
+ assert(From->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull) &&
"Expr must be null pointer constant!");
Kind = CK_NullToMemberPointer;
@@ -1876,7 +2092,8 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
/// an rvalue of type FromType to ToType is a qualification conversion
/// (C++ 4.4).
bool
-Sema::IsQualificationConversion(QualType FromType, QualType ToType) {
+Sema::IsQualificationConversion(QualType FromType, QualType ToType,
+ bool CStyle) {
FromType = Context.getCanonicalType(FromType);
ToType = Context.getCanonicalType(ToType);
@@ -1901,12 +2118,12 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) {
// -- for every j > 0, if const is in cv 1,j then const is in cv
// 2,j, and similarly for volatile.
- if (!ToType.isAtLeastAsQualifiedAs(FromType))
+ if (!CStyle && !ToType.isAtLeastAsQualifiedAs(FromType))
return false;
// -- if the cv 1,j and cv 2,j are different, then const is in
// every cv for 0 < k < j.
- if (FromType.getCVRQualifiers() != ToType.getCVRQualifiers()
+ if (!CStyle && FromType.getCVRQualifiers() != ToType.getCVRQualifiers()
&& !PreviousToQualsIncludeConst)
return false;
@@ -1977,13 +2194,13 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
-
+
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
- &From, 1, CandidateSet,
+ &From, 1, CandidateSet,
/*SuppressUserConversions=*/
!ConstructorsOnly);
else
@@ -2039,7 +2256,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
}
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best)) {
+ switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
case OR_Success:
// Record the standard conversion we used and the conversion function.
if (CXXConstructorDecl *Constructor
@@ -2058,6 +2275,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
User.EllipsisConversion = false;
}
User.ConversionFunction = Constructor;
+ User.FoundConversionFunction = Best->FoundDecl.getDecl();
User.After.setAsIdentityConversion();
User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
User.After.setAllToTypes(ToType);
@@ -2072,6 +2290,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// implicit object parameter of the conversion function.
User.Before = Best->Conversions[0].Standard;
User.ConversionFunction = Conversion;
+ User.FoundConversionFunction = Best->FoundDecl.getDecl();
User.EllipsisConversion = false;
// C++ [over.ics.user]p2:
@@ -2095,19 +2314,19 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
case OR_Deleted:
// No conversion here! We're done.
return OR_Deleted;
-
+
case OR_Ambiguous:
return OR_Ambiguous;
}
return OR_No_Viable_Function;
}
-
+
bool
Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
OverloadCandidateSet CandidateSet(From->getExprLoc());
- OverloadingResult OvResult =
+ OverloadingResult OvResult =
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
CandidateSet, false);
if (OvResult == OR_Ambiguous)
@@ -2121,7 +2340,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
else
return false;
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &From, 1);
- return true;
+ return true;
}
/// CompareImplicitConversionSequences - Compare two implicit
@@ -2182,12 +2401,12 @@ static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
Qualifiers Quals;
T1 = Context.getUnqualifiedArrayType(T1, Quals);
- T2 = Context.getUnqualifiedArrayType(T2, Quals);
+ T2 = Context.getUnqualifiedArrayType(T2, Quals);
}
-
+
return Context.hasSameUnqualifiedType(T1, T2);
}
-
+
// 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
@@ -2197,7 +2416,7 @@ compareStandardConversionSubsets(ASTContext &Context,
ImplicitConversionSequence::CompareKind Result
= ImplicitConversionSequence::Indistinguishable;
- // the identity conversion sequence is considered to be a subsequence of
+ // the identity conversion sequence is considered to be a subsequence of
// any non-identity conversion sequence
if (SCS1.ReferenceBinding == SCS2.ReferenceBinding) {
if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion())
@@ -2205,7 +2424,7 @@ compareStandardConversionSubsets(ASTContext &Context,
else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion())
return ImplicitConversionSequence::Worse;
}
-
+
if (SCS1.Second != SCS2.Second) {
if (SCS1.Second == ICK_Identity)
Result = ImplicitConversionSequence::Better;
@@ -2230,10 +2449,37 @@ compareStandardConversionSubsets(ASTContext &Context,
return Result == ImplicitConversionSequence::Better
? ImplicitConversionSequence::Indistinguishable
: ImplicitConversionSequence::Worse;
-
+
return ImplicitConversionSequence::Indistinguishable;
}
+/// \brief Determine whether one of the given reference bindings is better
+/// than the other based on what kind of bindings they are.
+static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
+ const StandardConversionSequence &SCS2) {
+ // C++0x [over.ics.rank]p3b4:
+ // -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
+ // implicit object parameter of a non-static member function declared
+ // without a ref-qualifier, and *either* S1 binds an rvalue reference
+ // to an rvalue and S2 binds an lvalue reference *or S1 binds an
+ // lvalue reference to a function lvalue and S2 binds an rvalue
+ // reference*.
+ //
+ // FIXME: Rvalue references. We're going rogue with the above edits,
+ // because the semantics in the current C++0x working paper (N3225 at the
+ // time of this writing) break the standard definition of std::forward
+ // and std::reference_wrapper when dealing with references to functions.
+ // Proposed wording changes submitted to CWG for consideration.
+ if (SCS1.BindsImplicitObjectArgumentWithoutRefQualifier ||
+ SCS2.BindsImplicitObjectArgumentWithoutRefQualifier)
+ return false;
+
+ return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue &&
+ SCS2.IsLvalueReference) ||
+ (SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue &&
+ !SCS2.IsLvalueReference);
+}
+
/// 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).
@@ -2339,17 +2585,11 @@ CompareStandardConversionSequences(Sema &S,
return QualCK;
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
- // C++0x [over.ics.rank]p3b4:
- // -- S1 and S2 are reference bindings (8.5.3) and neither refers to an
- // implicit object parameter of a non-static member function declared
- // without a ref-qualifier, and S1 binds an rvalue reference to an
- // rvalue and S2 binds an lvalue reference.
- // FIXME: We don't know if we're dealing with the implicit object parameter,
- // or if the member function in this case has a ref qualifier.
- // (Of course, we don't have ref qualifiers yet.)
- if (SCS1.RRefBinding != SCS2.RRefBinding)
- return SCS1.RRefBinding ? ImplicitConversionSequence::Better
- : ImplicitConversionSequence::Worse;
+ // Check for a better reference binding based on the kind of bindings.
+ if (isBetterReferenceBindingKind(SCS1, SCS2))
+ return ImplicitConversionSequence::Better;
+ else if (isBetterReferenceBindingKind(SCS2, SCS1))
+ return ImplicitConversionSequence::Worse;
// C++ [over.ics.rank]p3b4:
// -- S1 and S2 are reference bindings (8.5.3), and the types to
@@ -2365,8 +2605,8 @@ CompareStandardConversionSequences(Sema &S,
QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
if (UnqualT1 == UnqualT2) {
- // If the type is an array type, promote the element qualifiers to the type
- // for comparison.
+ // If the type is an array type, promote the element qualifiers to the
+ // type for comparison.
if (isa<ArrayType>(T1) && T1Quals)
T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
if (isa<ArrayType>(T2) && T2Quals)
@@ -2513,9 +2753,6 @@ CompareDerivedToBaseConversions(Sema &S,
// If class B is derived directly or indirectly from class A and
// class C is derived directly or indirectly from B,
//
- // For Objective-C, we let A, B, and C also be Objective-C
- // interfaces.
-
// Compare based on pointer conversions.
if (SCS1.Second == ICK_Pointer_Conversion &&
SCS2.Second == ICK_Pointer_Conversion &&
@@ -2531,24 +2768,12 @@ CompareDerivedToBaseConversions(Sema &S,
QualType ToPointee2
= ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
- const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>();
- const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>();
- const ObjCObjectType* ToIface1 = ToPointee1->getAs<ObjCObjectType>();
- const ObjCObjectType* ToIface2 = ToPointee2->getAs<ObjCObjectType>();
-
// -- conversion of C* to B* is better than conversion of C* to A*,
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
if (S.IsDerivedFrom(ToPointee1, ToPointee2))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
return ImplicitConversionSequence::Worse;
-
- if (ToIface1 && ToIface2) {
- if (S.Context.canAssignObjCInterfaces(ToIface2, ToIface1))
- return ImplicitConversionSequence::Better;
- else if (S.Context.canAssignObjCInterfaces(ToIface1, ToIface2))
- return ImplicitConversionSequence::Worse;
- }
}
// -- conversion of B* to A* is better than conversion of C* to A*,
@@ -2557,27 +2782,90 @@ CompareDerivedToBaseConversions(Sema &S,
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
+ }
+ } else if (SCS1.Second == ICK_Pointer_Conversion &&
+ SCS2.Second == ICK_Pointer_Conversion) {
+ const ObjCObjectPointerType *FromPtr1
+ = FromType1->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *FromPtr2
+ = FromType2->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *ToPtr1
+ = ToType1->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *ToPtr2
+ = ToType2->getAs<ObjCObjectPointerType>();
+
+ if (FromPtr1 && FromPtr2 && ToPtr1 && ToPtr2) {
+ // Apply the same conversion ranking rules for Objective-C pointer types
+ // that we do for C++ pointers to class types. However, we employ the
+ // Objective-C pseudo-subtyping relationship used for assignment of
+ // Objective-C pointer types.
+ bool FromAssignLeft
+ = S.Context.canAssignObjCInterfaces(FromPtr1, FromPtr2);
+ bool FromAssignRight
+ = S.Context.canAssignObjCInterfaces(FromPtr2, FromPtr1);
+ bool ToAssignLeft
+ = S.Context.canAssignObjCInterfaces(ToPtr1, ToPtr2);
+ bool ToAssignRight
+ = S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1);
+
+ // A conversion to an a non-id object pointer type or qualified 'id'
+ // type is better than a conversion to 'id'.
+ if (ToPtr1->isObjCIdType() &&
+ (ToPtr2->isObjCQualifiedIdType() || ToPtr2->getInterfaceDecl()))
+ return ImplicitConversionSequence::Worse;
+ if (ToPtr2->isObjCIdType() &&
+ (ToPtr1->isObjCQualifiedIdType() || ToPtr1->getInterfaceDecl()))
+ return ImplicitConversionSequence::Better;
+
+ // A conversion to a non-id object pointer type is better than a
+ // conversion to a qualified 'id' type
+ if (ToPtr1->isObjCQualifiedIdType() && ToPtr2->getInterfaceDecl())
+ return ImplicitConversionSequence::Worse;
+ if (ToPtr2->isObjCQualifiedIdType() && ToPtr1->getInterfaceDecl())
+ return ImplicitConversionSequence::Better;
+
+ // A conversion to an a non-Class object pointer type or qualified 'Class'
+ // type is better than a conversion to 'Class'.
+ if (ToPtr1->isObjCClassType() &&
+ (ToPtr2->isObjCQualifiedClassType() || ToPtr2->getInterfaceDecl()))
+ return ImplicitConversionSequence::Worse;
+ if (ToPtr2->isObjCClassType() &&
+ (ToPtr1->isObjCQualifiedClassType() || ToPtr1->getInterfaceDecl()))
+ return ImplicitConversionSequence::Better;
+
+ // A conversion to a non-Class object pointer type is better than a
+ // conversion to a qualified 'Class' type.
+ if (ToPtr1->isObjCQualifiedClassType() && ToPtr2->getInterfaceDecl())
+ return ImplicitConversionSequence::Worse;
+ if (ToPtr2->isObjCQualifiedClassType() && ToPtr1->getInterfaceDecl())
+ return ImplicitConversionSequence::Better;
- if (FromIface1 && FromIface2) {
- if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2))
- return ImplicitConversionSequence::Better;
- else if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1))
- return ImplicitConversionSequence::Worse;
- }
+ // -- "conversion of C* to B* is better than conversion of C* to A*,"
+ if (S.Context.hasSameType(FromType1, FromType2) &&
+ !FromPtr1->isObjCIdType() && !FromPtr1->isObjCClassType() &&
+ (ToAssignLeft != ToAssignRight))
+ return ToAssignLeft? ImplicitConversionSequence::Worse
+ : ImplicitConversionSequence::Better;
+
+ // -- "conversion of B* to A* is better than conversion of C* to A*,"
+ if (S.Context.hasSameUnqualifiedType(ToType1, ToType2) &&
+ (FromAssignLeft != FromAssignRight))
+ return FromAssignLeft? ImplicitConversionSequence::Better
+ : ImplicitConversionSequence::Worse;
}
}
-
+
// Ranking of member-pointer types.
if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member &&
FromType1->isMemberPointerType() && FromType2->isMemberPointerType() &&
ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) {
- const MemberPointerType * FromMemPointer1 =
+ const MemberPointerType * FromMemPointer1 =
FromType1->getAs<MemberPointerType>();
- const MemberPointerType * ToMemPointer1 =
+ const MemberPointerType * ToMemPointer1 =
ToType1->getAs<MemberPointerType>();
- const MemberPointerType * FromMemPointer2 =
+ const MemberPointerType * FromMemPointer2 =
FromType2->getAs<MemberPointerType>();
- const MemberPointerType * ToMemPointer2 =
+ const MemberPointerType * ToMemPointer2 =
ToType2->getAs<MemberPointerType>();
const Type *FromPointeeType1 = FromMemPointer1->getClass();
const Type *ToPointeeType1 = ToMemPointer1->getClass();
@@ -2602,7 +2890,7 @@ CompareDerivedToBaseConversions(Sema &S,
return ImplicitConversionSequence::Worse;
}
}
-
+
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
@@ -2708,10 +2996,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
- QualType ToType
- = AllowRvalues? DeclType->getAs<ReferenceType>()->getPointeeType()
- : DeclType;
-
OverloadCandidateSet CandidateSet(DeclLoc);
const UnresolvedSetImpl *Conversions
= T2RecordDecl->getVisibleConversionFunctions();
@@ -2730,20 +3014,22 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
else
Conv = cast<CXXConversionDecl>(D);
- // If this is an explicit conversion, and we're not allowed to consider
+ // If this is an explicit conversion, and we're not allowed to consider
// explicit conversions, skip it.
if (!AllowExplicit && Conv->isExplicit())
continue;
-
+
if (AllowRvalues) {
bool DerivedToBase = false;
bool ObjCConversion = false;
if (!ConvTemplate &&
- S.CompareReferenceRelationship(DeclLoc,
- Conv->getConversionType().getNonReferenceType().getUnqualifiedType(),
- DeclType.getNonReferenceType().getUnqualifiedType(),
- DerivedToBase, ObjCConversion)
- == Sema::Ref_Incompatible)
+ S.CompareReferenceRelationship(
+ DeclLoc,
+ Conv->getConversionType().getNonReferenceType()
+ .getUnqualifiedType(),
+ DeclType.getNonReferenceType().getUnqualifiedType(),
+ DerivedToBase, ObjCConversion) ==
+ Sema::Ref_Incompatible)
continue;
} else {
// If the conversion function doesn't return a reference type,
@@ -2757,17 +3043,17 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
!RefType->getPointeeType()->isFunctionType()))
continue;
}
-
+
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
- Init, ToType, CandidateSet);
+ Init, DeclType, CandidateSet);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
- ToType, CandidateSet);
+ DeclType, CandidateSet);
}
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
+ switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
case OR_Success:
// C++ [over.ics.ref]p1:
//
@@ -2786,6 +3072,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
ICS.UserDefined.Before = Best->Conversions[0].Standard;
ICS.UserDefined.After = Best->FinalConversion;
ICS.UserDefined.ConversionFunction = Best->Function;
+ ICS.UserDefined.FoundConversionFunction = Best->FoundDecl.getDecl();
ICS.UserDefined.EllipsisConversion = false;
assert(ICS.UserDefined.After.ReferenceBinding &&
ICS.UserDefined.After.DirectBinding &&
@@ -2806,7 +3093,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
// conversion; continue with other checks.
return false;
}
-
+
return false;
}
@@ -2851,9 +3138,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// of type "cv2 T2" as follows:
// -- If reference is an lvalue reference and the initializer expression
- // The next bullet point (T1 is a function) is pretty much equivalent to this
- // one, so it's handled here.
- if (!isRValRef || T1->isFunctionType()) {
+ if (!isRValRef) {
// -- is an lvalue (but is not a bit-field), and "cv1 T1" is
// reference-compatible with "cv2 T2," or
//
@@ -2879,7 +3164,10 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
ICS.Standard.setToType(2, T1);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding = true;
- ICS.Standard.RRefBinding = isRValRef;
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = false;
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.CopyConstructor = 0;
// Nothing more to do: the inaccessibility/ambiguity check for
@@ -2897,7 +3185,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// conversion functions (13.3.1.6) and choosing the best
// one through overload resolution (13.3)),
if (!SuppressUserConversions && T2->isRecordType() &&
- !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ !S.RequireCompleteType(DeclLoc, T2, 0) &&
RefRelationship == Sema::Ref_Incompatible) {
if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
Init, T2, /*AllowRvalues=*/false,
@@ -2908,9 +3196,8 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// -- Otherwise, the reference shall be an lvalue reference to a
// non-volatile const type (i.e., cv1 shall be const), or the reference
- // shall be an rvalue reference and the initializer expression shall be
- // an rvalue or have a function type.
- //
+ // shall be an rvalue reference.
+ //
// We actually handle one oddity of C++ [over.ics.ref] at this
// point, which is that, due to p2 (which short-circuits reference
// binding by only attempting a simple conversion for non-direct
@@ -2920,70 +3207,70 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// qualifier.
// This is also the point where rvalue references and lvalue inits no longer
// go together.
- if ((!isRValRef && !T1.isConstQualified()) ||
- (isRValRef && InitCategory.isLValue()))
+ if (!isRValRef && !T1.isConstQualified())
return ICS;
- // -- If T1 is a function type, then
- // -- if T2 is the same type as T1, the reference is bound to the
- // initializer expression lvalue;
- // -- if T2 is a class type and the initializer expression can be
- // implicitly converted to an lvalue of type T1 [...], the
- // reference is bound to the function lvalue that is the result
- // of the conversion;
- // This is the same as for the lvalue case above, so it was handled there.
- // -- otherwise, the program is ill-formed.
- // This is the one difference to the lvalue case.
- if (T1->isFunctionType())
+ // -- If the initializer expression
+ //
+ // -- is an xvalue, class prvalue, array prvalue or function
+ // lvalue and "cv1T1" is reference-compatible with "cv2 T2", or
+ if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification &&
+ (InitCategory.isXValue() ||
+ (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) ||
+ (InitCategory.isLValue() && T2->isFunctionType()))) {
+ ICS.setStandard();
+ ICS.Standard.First = ICK_Identity;
+ ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
+ : ObjCConversion? ICK_Compatible_Conversion
+ : ICK_Identity;
+ ICS.Standard.Third = ICK_Identity;
+ ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+ ICS.Standard.setToType(0, T2);
+ ICS.Standard.setToType(1, T1);
+ ICS.Standard.setToType(2, T1);
+ ICS.Standard.ReferenceBinding = true;
+ // In C++0x, this is always a direct binding. In C++98/03, it's a direct
+ // binding unless we're binding to a class prvalue.
+ // Note: Although xvalues wouldn't normally show up in C++98/03 code, we
+ // allow the use of rvalue references in C++98/03 for the benefit of
+ // standard library implementors; therefore, we need the xvalue check here.
+ ICS.Standard.DirectBinding =
+ S.getLangOptions().CPlusPlus0x ||
+ (InitCategory.isPRValue() && !T2->isRecordType());
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = InitCategory.isRValue();
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
+ ICS.Standard.CopyConstructor = 0;
return ICS;
+ }
- // -- Otherwise, if T2 is a class type and
- // -- the initializer expression is an rvalue and "cv1 T1"
- // is reference-compatible with "cv2 T2," or
- //
- // -- T1 is not reference-related to T2 and the initializer
- // expression can be implicitly converted to an rvalue
- // of type "cv3 T3" (this conversion is selected by
- // enumerating the applicable conversion functions
- // (13.3.1.6) and choosing the best one through overload
- // resolution (13.3)),
+ // -- has a class type (i.e., T2 is a class type), where T1 is not
+ // reference-related to T2, and can be implicitly converted to
+ // an xvalue, class prvalue, or function lvalue of type
+ // "cv3 T3", where "cv1 T1" is reference-compatible with
+ // "cv3 T3",
//
- // then the reference is bound to the initializer
- // expression rvalue in the first case and to the object
- // that is the result of the conversion in the second case
- // (or, in either case, to the appropriate base class
- // subobject of the object).
- if (T2->isRecordType()) {
- // First case: "cv1 T1" is reference-compatible with "cv2 T2". This is a
- // direct binding in C++0x but not in C++03.
- if (InitCategory.isRValue() &&
- RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
- ICS.setStandard();
- ICS.Standard.First = ICK_Identity;
- ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
- : ObjCConversion? ICK_Compatible_Conversion
- : ICK_Identity;
- ICS.Standard.Third = ICK_Identity;
- ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS.Standard.setToType(0, T2);
- ICS.Standard.setToType(1, T1);
- ICS.Standard.setToType(2, T1);
- ICS.Standard.ReferenceBinding = true;
- ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x;
- ICS.Standard.RRefBinding = isRValRef;
- ICS.Standard.CopyConstructor = 0;
- return ICS;
- }
-
- // Second case: not reference-related.
- if (RefRelationship == Sema::Ref_Incompatible &&
- !S.RequireCompleteType(DeclLoc, T2, 0) &&
- FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
- Init, T2, /*AllowRvalues=*/true,
- AllowExplicit))
- return ICS;
+ // then the reference is bound to the value of the initializer
+ // expression in the first case and to the result of the conversion
+ // in the second case (or, in either case, to an appropriate base
+ // class subobject).
+ if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
+ T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
+ Init, T2, /*AllowRvalues=*/true,
+ AllowExplicit)) {
+ // In the second case, if the reference is an rvalue reference
+ // and the second standard conversion sequence of the
+ // user-defined conversion sequence includes an lvalue-to-rvalue
+ // conversion, the program is ill-formed.
+ if (ICS.isUserDefined() && isRValRef &&
+ ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue)
+ ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
+
+ return ICS;
}
-
+
// -- Otherwise, a temporary of type "cv1 T1" is created and
// initialized from the initializer expression using the
// rules for a non-reference copy initialization (8.5). The
@@ -3008,6 +3295,12 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
(T1->isRecordType() || T2->isRecordType()))
return ICS;
+ // If T1 is reference-related to T2 and the reference is an rvalue
+ // reference, the initializer expression shall not be an lvalue.
+ if (RefRelationship >= Sema::Ref_Related &&
+ isRValRef && Init->Classify(S.Context).isLValue())
+ return ICS;
+
// C++ [over.ics.ref]p2:
// When a parameter of reference type is not bound directly to
// an argument expression, the conversion sequence is the one
@@ -3020,16 +3313,24 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// and does not constitute a conversion.
ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions,
/*AllowExplicit=*/false,
- /*InOverloadResolution=*/false);
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false);
// Of course, that's still a reference binding.
if (ICS.isStandard()) {
ICS.Standard.ReferenceBinding = true;
- ICS.Standard.RRefBinding = isRValRef;
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = true;
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
} else if (ICS.isUserDefined()) {
ICS.UserDefined.After.ReferenceBinding = true;
- ICS.UserDefined.After.RRefBinding = isRValRef;
+ ICS.Standard.IsLvalueReference = !isRValRef;
+ ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
+ ICS.Standard.BindsToRvalue = true;
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
}
+
return ICS;
}
@@ -3041,7 +3342,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
/// do not permit any user-defined conversion sequences.
static ImplicitConversionSequence
TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
- bool SuppressUserConversions,
+ bool SuppressUserConversions,
bool InOverloadResolution) {
if (ToType->isReferenceType())
return TryReferenceInit(S, From, ToType,
@@ -3052,7 +3353,8 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
return TryImplicitConversion(S, From, ToType,
SuppressUserConversions,
/*AllowExplicit=*/false,
- InOverloadResolution);
+ InOverloadResolution,
+ /*CStyle=*/false);
}
/// TryObjectArgumentInitialization - Try to initialize the object
@@ -3060,6 +3362,7 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
/// expression @p From.
static ImplicitConversionSequence
TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
+ Expr::Classification FromClassification,
CXXMethodDecl *Method,
CXXRecordDecl *ActingContext) {
QualType ClassType = S.Context.getTypeDeclType(ActingContext);
@@ -3075,24 +3378,37 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
// We need to have an object of class type.
QualType FromType = OrigFromType;
- if (const PointerType *PT = FromType->getAs<PointerType>())
+ if (const PointerType *PT = FromType->getAs<PointerType>()) {
FromType = PT->getPointeeType();
+ // When we had a pointer, it's implicitly dereferenced, so we
+ // better have an lvalue.
+ assert(FromClassification.isLValue());
+ }
+
assert(FromType->isRecordType());
- // The implicit object parameter is has the type "reference to cv X",
- // where X is the class of which the function is a member
- // (C++ [over.match.funcs]p4). However, when finding an implicit
- // conversion sequence for the argument, we are not allowed to
- // create temporaries or perform user-defined conversions
+ // C++0x [over.match.funcs]p4:
+ // For non-static member functions, the type of the implicit object
+ // parameter is
+ //
+ // - "lvalue reference to cv X" for functions declared without a
+ // ref-qualifier or with the & ref-qualifier
+ // - "rvalue reference to cv X" for functions declared with the &&
+ // ref-qualifier
+ //
+ // where X is the class of which the function is a member and cv is the
+ // cv-qualification on the member function declaration.
+ //
+ // However, when finding an implicit conversion sequence for the argument, we
+ // are not allowed to create temporaries or perform user-defined conversions
// (C++ [over.match.funcs]p5). We perform a simplified version of
// reference binding here, that allows class rvalues to bind to
// non-constant references.
- // First check the qualifiers. We don't care about lvalue-vs-rvalue
- // with the implicit object parameter (C++ [over.match.funcs]p5).
+ // First check the qualifiers.
QualType FromTypeCanon = S.Context.getCanonicalType(FromType);
- if (ImplicitParamType.getCVRQualifiers()
+ if (ImplicitParamType.getCVRQualifiers()
!= FromTypeCanon.getLocalCVRQualifiers() &&
!ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
ICS.setBad(BadConversionSequence::bad_qualifiers,
@@ -3114,6 +3430,31 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
return ICS;
}
+ // Check the ref-qualifier.
+ switch (Method->getRefQualifier()) {
+ case RQ_None:
+ // Do nothing; we don't care about lvalueness or rvalueness.
+ break;
+
+ case RQ_LValue:
+ if (!FromClassification.isLValue() && Quals != Qualifiers::Const) {
+ // non-const lvalue reference cannot bind to an rvalue
+ ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType,
+ ImplicitParamType);
+ return ICS;
+ }
+ break;
+
+ case RQ_RValue:
+ if (!FromClassification.isRValue()) {
+ // rvalue reference cannot bind to an lvalue
+ ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, FromType,
+ ImplicitParamType);
+ return ICS;
+ }
+ break;
+ }
+
// Success. Mark this as a reference binding.
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
@@ -3122,7 +3463,11 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
ICS.Standard.setAllToTypes(ImplicitParamType);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding = true;
- ICS.Standard.RRefBinding = false;
+ ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue;
+ ICS.Standard.BindsToFunctionLvalue = false;
+ ICS.Standard.BindsToRvalue = FromClassification.isRValue();
+ ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier
+ = (Method->getRefQualifier() == RQ_None);
return ICS;
}
@@ -3130,31 +3475,50 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
/// the implicit object parameter for the given Method with the given
/// expression.
bool
-Sema::PerformObjectArgumentInitialization(Expr *&From,
- NestedNameSpecifier *Qualifier,
+Sema::PerformObjectArgumentInitialization(Expr *&From,
+ NestedNameSpecifier *Qualifier,
NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
QualType FromRecordType, DestType;
QualType ImplicitParamRecordType =
Method->getThisType(Context)->getAs<PointerType>()->getPointeeType();
+ Expr::Classification FromClassification;
if (const PointerType *PT = From->getType()->getAs<PointerType>()) {
FromRecordType = PT->getPointeeType();
DestType = Method->getThisType(Context);
+ FromClassification = Expr::Classification::makeSimpleLValue();
} else {
FromRecordType = From->getType();
DestType = ImplicitParamRecordType;
+ FromClassification = From->Classify(Context);
}
// Note that we always use the true parent context when performing
// the actual argument initialization.
ImplicitConversionSequence ICS
- = TryObjectArgumentInitialization(*this, From->getType(), Method,
- Method->getParent());
- if (ICS.isBad())
+ = TryObjectArgumentInitialization(*this, From->getType(), FromClassification,
+ Method, Method->getParent());
+ if (ICS.isBad()) {
+ if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
+ Qualifiers FromQs = FromRecordType.getQualifiers();
+ Qualifiers ToQs = DestType.getQualifiers();
+ unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
+ if (CVR) {
+ Diag(From->getSourceRange().getBegin(),
+ diag::err_member_function_call_bad_cvr)
+ << Method->getDeclName() << FromRecordType << (CVR - 1)
+ << From->getSourceRange();
+ Diag(Method->getLocation(), diag::note_previous_decl)
+ << Method->getDeclName();
+ return true;
+ }
+ }
+
return Diag(From->getSourceRange().getBegin(),
diag::err_implicit_object_parameter_init)
<< ImplicitParamRecordType << FromRecordType << From->getSourceRange();
+ }
if (ICS.Standard.Second == ICK_Derived_To_Base)
return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
@@ -3174,7 +3538,8 @@ TryContextuallyConvertToBool(Sema &S, Expr *From) {
// FIXME: Are these flags correct?
/*SuppressUserConversions=*/false,
/*AllowExplicit=*/true,
- /*InOverloadResolution=*/false);
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false);
}
/// PerformContextuallyConvertToBool - Perform a contextual conversion
@@ -3183,14 +3548,14 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From);
if (!ICS.isBad())
return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
-
+
if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_bool_condition)
<< From->getType() << From->getSourceRange();
return true;
}
-
+
/// TryContextuallyConvertToObjCId - Attempt to contextually convert the
/// expression From to 'id'.
static ImplicitConversionSequence
@@ -3200,7 +3565,8 @@ TryContextuallyConvertToObjCId(Sema &S, Expr *From) {
// FIXME: Are these flags correct?
/*SuppressUserConversions=*/false,
/*AllowExplicit=*/true,
- /*InOverloadResolution=*/false);
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false);
}
/// PerformContextuallyConvertToObjCId - Perform a contextual conversion
@@ -3213,7 +3579,7 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
return true;
}
-/// \brief Attempt to convert the given expression to an integral or
+/// \brief Attempt to convert the given expression to an integral or
/// enumeration type.
///
/// This routine will attempt to convert an expression of class type to an
@@ -3241,7 +3607,7 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
/// \param AmbigDiag The diagnostic to be emitted if there is more than one
/// conversion function that could convert to integral or enumeration type.
///
-/// \param AmbigNote The note to be emitted with \p AmbigDiag for each
+/// \param AmbigNote The note to be emitted with \p AmbigDiag for each
/// usable conversion function.
///
/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion
@@ -3249,7 +3615,7 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
///
/// \returns The expression, converted to an integral or enumeration type if
/// successful.
-ExprResult
+ExprResult
Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
const PartialDiagnostic &NotIntDiag,
const PartialDiagnostic &IncompleteDiag,
@@ -3261,7 +3627,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
// We can't perform any more checking for type-dependent expressions.
if (From->isTypeDependent())
return Owned(From);
-
+
// If the expression already has integral or enumeration type, we're golden.
QualType T = From->getType();
if (T->isIntegralOrEnumerationType())
@@ -3269,7 +3635,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
// FIXME: Check for missing '()' if T is a function type?
- // If we don't have a class type in C++, there's no way we can get an
+ // If we don't have a class type in C++, there's no way we can get an
// expression of integral or enumeration type.
const RecordType *RecordTy = T->getAs<RecordType>();
if (!RecordTy || !getLangOptions().CPlusPlus) {
@@ -3277,20 +3643,20 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
<< T << From->getSourceRange();
return Owned(From);
}
-
+
// We must have a complete class type.
if (RequireCompleteType(Loc, T, IncompleteDiag))
return Owned(From);
-
+
// Look for a conversion to an integral or enumeration type.
UnresolvedSet<4> ViableConversions;
UnresolvedSet<4> ExplicitConversions;
const UnresolvedSetImpl *Conversions
= cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
-
+
for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end();
- I != E;
+ E = Conversions->end();
+ I != E;
++I) {
if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl()))
@@ -3302,21 +3668,21 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
ViableConversions.addDecl(I.getDecl(), I.getAccess());
}
}
-
+
switch (ViableConversions.size()) {
case 0:
if (ExplicitConversions.size() == 1) {
DeclAccessPair Found = ExplicitConversions[0];
CXXConversionDecl *Conversion
= cast<CXXConversionDecl>(Found->getUnderlyingDecl());
-
+
// The user probably meant to invoke the given explicit
// conversion; use it.
QualType ConvTy
= Conversion->getConversionType().getNonReferenceType();
std::string TypeStr;
ConvTy.getAsStringInternal(TypeStr, Context.PrintingPolicy);
-
+
Diag(Loc, ExplicitConvDiag)
<< T << ConvTy
<< FixItHint::CreateInsertion(From->getLocStart(),
@@ -3325,41 +3691,49 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
")");
Diag(Conversion->getLocation(), ExplicitConvNote)
<< ConvTy->isEnumeralType() << ConvTy;
-
- // If we aren't in a SFINAE context, build a call to the
+
+ // If we aren't in a SFINAE context, build a call to the
// explicit conversion function.
if (isSFINAEContext())
return ExprError();
-
+
CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
- From = BuildCXXMemberCallExpr(From, Found, Conversion);
+ ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion);
+ if (Result.isInvalid())
+ return ExprError();
+
+ From = Result.get();
}
-
+
// We'll complain below about a non-integral condition type.
break;
-
+
case 1: {
// Apply this conversion.
DeclAccessPair Found = ViableConversions[0];
CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
-
+
CXXConversionDecl *Conversion
= cast<CXXConversionDecl>(Found->getUnderlyingDecl());
QualType ConvTy
- = Conversion->getConversionType().getNonReferenceType();
+ = Conversion->getConversionType().getNonReferenceType();
if (ConvDiag.getDiagID()) {
if (isSFINAEContext())
return ExprError();
-
+
Diag(Loc, ConvDiag)
<< T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange();
}
-
- From = BuildCXXMemberCallExpr(From, Found,
+
+ ExprResult Result = BuildCXXMemberCallExpr(From, Found,
cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
+ if (Result.isInvalid())
+ return ExprError();
+
+ From = Result.get();
break;
}
-
+
default:
Diag(Loc, AmbigDiag)
<< T << From->getSourceRange();
@@ -3372,7 +3746,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
}
return Owned(From);
}
-
+
if (!From->getType()->isIntegralOrEnumerationType())
Diag(Loc, NotIntDiag)
<< From->getType() << From->getSourceRange();
@@ -3411,7 +3785,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// object argument (C++ [over.call.func]p3), and the acting context
// is irrelevant.
AddMethodCandidate(Method, FoundDecl, Method->getParent(),
- QualType(), Args, NumArgs, CandidateSet,
+ QualType(), Expr::Classification::makeSimpleLValue(),
+ Args, NumArgs, CandidateSet,
SuppressUserConversions);
return;
}
@@ -3430,13 +3805,13 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// A member function template is never instantiated to perform the copy
// of a class object to an object of its class type.
QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
- if (NumArgs == 1 &&
- Constructor->isCopyConstructorLikeSpecialization() &&
+ if (NumArgs == 1 &&
+ Constructor->isSpecializationCopyingObject() &&
(Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
IsDerivedFrom(Args[0]->getType(), ClassType)))
return;
}
-
+
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
@@ -3445,13 +3820,14 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.Viable = true;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
+ Candidate.ExplicitCallArguments = NumArgs;
unsigned NumArgsInProto = Proto->getNumArgs();
// (C++ 13.3.2p2): A candidate function having fewer than m
// parameters is viable only if it has an ellipsis in its parameter
// list (8.3.5).
- if ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto &&
+ if ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto &&
!Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
@@ -3483,7 +3859,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
QualType ParamType = Proto->getArgType(ArgIdx);
Candidate.Conversions[ArgIdx]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
- SuppressUserConversions,
+ SuppressUserConversions,
/*InOverloadResolution=*/true);
if (Candidate.Conversions[ArgIdx].isBad()) {
Candidate.Viable = false;
@@ -3511,7 +3887,8 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
cast<CXXMethodDecl>(FD)->getParent(),
- Args[0]->getType(), Args + 1, NumArgs - 1,
+ Args[0]->getType(), Args[0]->Classify(Context),
+ Args + 1, NumArgs - 1,
CandidateSet, SuppressUserConversions);
else
AddOverloadCandidate(FD, F.getPair(), Args, NumArgs, CandidateSet,
@@ -3523,7 +3900,9 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
AddMethodTemplateCandidate(FunTmpl, F.getPair(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
/*FIXME: explicit args */ 0,
- Args[0]->getType(), Args + 1, NumArgs - 1,
+ Args[0]->getType(),
+ Args[0]->Classify(Context),
+ Args + 1, NumArgs - 1,
CandidateSet,
SuppressUserConversions);
else
@@ -3539,6 +3918,7 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
/// method) as a method candidate to the given overload set.
void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
+ Expr::Classification ObjectClassification,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
@@ -3547,18 +3927,18 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
if (isa<UsingShadowDecl>(Decl))
Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl();
-
+
if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
/*ExplicitArgs*/ 0,
- ObjectType, Args, NumArgs,
+ ObjectType, ObjectClassification, Args, NumArgs,
CandidateSet,
SuppressUserConversions);
} else {
AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
- ObjectType, Args, NumArgs,
+ ObjectType, ObjectClassification, Args, NumArgs,
CandidateSet, SuppressUserConversions);
}
}
@@ -3573,6 +3953,7 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
void
Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
@@ -3595,6 +3976,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Candidate.Function = Method;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
+ Candidate.ExplicitCallArguments = NumArgs;
unsigned NumArgsInProto = Proto->getNumArgs();
@@ -3630,8 +4012,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
// Determine the implicit conversion sequence for the object
// parameter.
Candidate.Conversions[0]
- = TryObjectArgumentInitialization(*this, ObjectType, Method,
- ActingContext);
+ = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification,
+ Method, ActingContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -3650,7 +4032,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
QualType ParamType = Proto->getArgType(ArgIdx);
Candidate.Conversions[ArgIdx + 1]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
- SuppressUserConversions,
+ SuppressUserConversions,
/*InOverloadResolution=*/true);
if (Candidate.Conversions[ArgIdx + 1].isBad()) {
Candidate.Viable = false;
@@ -3665,7 +4047,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
}
}
}
-
+
/// \brief Add a C++ member function template as a candidate to the candidate
/// set, using template argument deduction to produce an appropriate member
/// function template specialization.
@@ -3675,6 +4057,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
CXXRecordDecl *ActingContext,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
+ Expr::Classification ObjectClassification,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
@@ -3703,7 +4086,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
- Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Candidate.ExplicitCallArguments = NumArgs;
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
Info);
return;
}
@@ -3714,8 +4098,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
assert(isa<CXXMethodDecl>(Specialization) &&
"Specialization is not a member function?");
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
- ActingContext, ObjectType, Args, NumArgs,
- CandidateSet, SuppressUserConversions);
+ ActingContext, ObjectType, ObjectClassification,
+ Args, NumArgs, CandidateSet, SuppressUserConversions);
}
/// \brief Add a C++ function template specialization as a candidate
@@ -3753,7 +4137,8 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
- Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Candidate.ExplicitCallArguments = NumArgs;
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
Info);
return;
}
@@ -3798,10 +4183,11 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.FinalConversion.setAllToTypes(ToType);
Candidate.Viable = true;
Candidate.Conversions.resize(1);
+ Candidate.ExplicitCallArguments = 1;
// C++ [over.match.funcs]p4:
- // For conversion functions, the function is considered to be a member of
- // the class of the implicit implied object argument for the purpose of
+ // For conversion functions, the function is considered to be a member of
+ // the class of the implicit implied object argument for the purpose of
// defining the type of the implicit object parameter.
//
// Determine the implicit conversion sequence for the implicit
@@ -3811,18 +4197,19 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
ImplicitParamType = FromPtrType->getPointeeType();
CXXRecordDecl *ConversionContext
= cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
-
+
Candidate.Conversions[0]
- = TryObjectArgumentInitialization(*this, From->getType(), Conversion,
- ConversionContext);
-
+ = TryObjectArgumentInitialization(*this, From->getType(),
+ From->Classify(Context),
+ Conversion, ConversionContext);
+
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
- // We won't go through a user-define type conversion function to convert a
+ // We won't go through a user-define type conversion function to convert a
// derived to base as such conversions are given Conversion Rank. They only
// go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
QualType FromCanon
@@ -3833,7 +4220,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.FailureKind = ovl_fail_trivial_conversion;
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
@@ -3843,17 +4230,26 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// call on the stack and we don't need its arguments to be
// well-formed.
DeclRefExpr ConversionRef(Conversion, Conversion->getType(),
- From->getLocStart());
+ VK_LValue, From->getLocStart());
ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
Context.getPointerType(Conversion->getType()),
CK_FunctionToPointerDecay,
&ConversionRef, VK_RValue);
+ QualType CallResultType
+ = Conversion->getConversionType().getNonLValueExprType(Context);
+ if (RequireCompleteType(From->getLocStart(), CallResultType, 0)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_final_conversion;
+ return;
+ }
+
+ ExprValueKind VK = Expr::getValueKindForType(Conversion->getConversionType());
+
// Note that it is safe to allocate CallExpr on the stack here because
// there are 0 arguments (i.e., nothing is allocated using ASTContext's
// allocator).
- CallExpr Call(Context, &ConversionFn, 0, 0,
- Conversion->getConversionType().getNonLValueExprType(Context),
+ CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, VK,
From->getLocStart());
ImplicitConversionSequence ICS =
TryCopyInitialization(*this, &Call, ToType,
@@ -3863,17 +4259,27 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
Candidate.FinalConversion = ICS.Standard;
-
+
// C++ [over.ics.user]p3:
// If the user-defined conversion is specified by a specialization of a
- // conversion function template, the second standard conversion sequence
+ // conversion function template, the second standard conversion sequence
// shall have exact match rank.
if (Conversion->getPrimaryTemplate() &&
GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_final_conversion_not_exact;
}
-
+
+ // C++0x [dcl.init.ref]p5:
+ // In the second case, if the reference is an rvalue reference and
+ // the second standard conversion sequence of the user-defined
+ // conversion sequence includes an lvalue-to-rvalue conversion, the
+ // program is ill-formed.
+ if (ToType->isRValueReferenceType() &&
+ ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_final_conversion;
+ }
break;
case ImplicitConversionSequence::BadConversion:
@@ -3917,7 +4323,8 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
- Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
+ Candidate.ExplicitCallArguments = 1;
+ Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
Info);
return;
}
@@ -3938,7 +4345,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
- QualType ObjectType,
+ Expr *Object,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet) {
if (!CandidateSet.isNewCandidate(Conversion))
@@ -3956,12 +4363,14 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
Candidate.IsSurrogate = true;
Candidate.IgnoreObjectArgument = false;
Candidate.Conversions.resize(NumArgs + 1);
+ Candidate.ExplicitCallArguments = NumArgs;
// Determine the implicit conversion sequence for the implicit
// object parameter.
ImplicitConversionSequence ObjectInit
- = TryObjectArgumentInitialization(*this, ObjectType, Conversion,
- ActingContext);
+ = TryObjectArgumentInitialization(*this, Object->getType(),
+ Object->Classify(Context),
+ Conversion, ActingContext);
if (ObjectInit.isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -3976,6 +4385,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard;
Candidate.Conversions[0].UserDefined.EllipsisConversion = false;
Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion;
+ Candidate.Conversions[0].UserDefined.FoundConversionFunction
+ = FoundDecl.getDecl();
Candidate.Conversions[0].UserDefined.After
= Candidate.Conversions[0].UserDefined.Before;
Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion();
@@ -4071,7 +4482,8 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
Oper != OperEnd;
++Oper)
AddMethodCandidate(Oper.getPair(), Args[0]->getType(),
- Args + 1, NumArgs - 1, CandidateSet,
+ Args[0]->Classify(Context), Args + 1, NumArgs - 1,
+ CandidateSet,
/* SuppressUserConversions = */ false);
}
}
@@ -4107,6 +4519,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
// arguments.
Candidate.Viable = true;
Candidate.Conversions.resize(NumArgs);
+ Candidate.ExplicitCallArguments = NumArgs;
for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
// C++ [over.match.oper]p4:
// For the built-in assignment operators, conversions of the
@@ -4159,10 +4572,17 @@ class BuiltinCandidateTypeSet {
/// used in the built-in candidates.
TypeSet EnumerationTypes;
- /// \brief The set of vector types that will be used in the built-in
+ /// \brief The set of vector types that will be used in the built-in
/// candidates.
TypeSet VectorTypes;
-
+
+ /// \brief A flag indicating non-record types are viable candidates
+ bool HasNonRecordTypes;
+
+ /// \brief A flag indicating whether either arithmetic or enumeration types
+ /// were present in the candidate set.
+ bool HasArithmeticOrEnumeralTypes;
+
/// Sema - The semantic analysis instance where we are building the
/// candidate type set.
Sema &SemaRef;
@@ -4179,9 +4599,12 @@ public:
typedef TypeSet::iterator iterator;
BuiltinCandidateTypeSet(Sema &SemaRef)
- : SemaRef(SemaRef), Context(SemaRef.Context) { }
+ : HasNonRecordTypes(false),
+ HasArithmeticOrEnumeralTypes(false),
+ SemaRef(SemaRef),
+ Context(SemaRef.Context) { }
- void AddTypesConvertedFrom(QualType Ty,
+ void AddTypesConvertedFrom(QualType Ty,
SourceLocation Loc,
bool AllowUserConversions,
bool AllowExplicitConversions,
@@ -4204,9 +4627,12 @@ public:
/// enumeration_end - Past the last enumeration type found;
iterator enumeration_end() { return EnumerationTypes.end(); }
-
+
iterator vector_begin() { return VectorTypes.begin(); }
iterator vector_end() { return VectorTypes.end(); }
+
+ bool hasNonRecordTypes() { return HasNonRecordTypes; }
+ bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; }
};
/// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to
@@ -4225,7 +4651,7 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
// Insert this type.
if (!PointerTypes.insert(Ty))
return false;
-
+
QualType PointeeTy;
const PointerType *PointerTy = Ty->getAs<PointerType>();
bool buildObjCPtr = false;
@@ -4239,7 +4665,7 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
}
else
PointeeTy = PointerTy->getPointeeType();
-
+
// Don't add qualified variants of arrays. For one, they're not allowed
// (the qualifier would sink to the element type), and for another, the
// only overload situation where it matters is subscript or pointer +- int,
@@ -4251,7 +4677,7 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
BaseCVR = Array->getElementType().getCVRQualifiers();
bool hasVolatile = VisibleQuals.hasVolatile();
bool hasRestrict = VisibleQuals.hasRestrict();
-
+
// Iterate through all strict supersets of BaseCVR.
for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
if ((CVR | BaseCVR) != CVR) continue;
@@ -4302,9 +4728,10 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
unsigned BaseCVR = PointeeTy.getCVRQualifiers();
for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
if ((CVR | BaseCVR) != CVR) continue;
-
+
QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
- MemberPointerTypes.insert(Context.getMemberPointerType(QPointeeTy, ClassTy));
+ MemberPointerTypes.insert(
+ Context.getMemberPointerType(QPointeeTy, ClassTy));
}
return true;
@@ -4332,12 +4759,21 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
if (const ReferenceType *RefTy = Ty->getAs<ReferenceType>())
Ty = RefTy->getPointeeType();
- // We don't care about qualifiers on the type.
- Ty = Ty.getLocalUnqualifiedType();
-
// If we're dealing with an array type, decay to the pointer.
if (Ty->isArrayType())
Ty = SemaRef.Context.getArrayDecayedType(Ty);
+
+ // Otherwise, we don't care about qualifiers on the type.
+ Ty = Ty.getLocalUnqualifiedType();
+
+ // Flag if we ever add a non-record type.
+ const RecordType *TyRec = Ty->getAs<RecordType>();
+ HasNonRecordTypes = HasNonRecordTypes || !TyRec;
+
+ // Flag if we encounter an arithmetic type.
+ HasArithmeticOrEnumeralTypes =
+ HasArithmeticOrEnumeralTypes || Ty->isArithmeticType();
+
if (Ty->isObjCIdType() || Ty->isObjCClassType())
PointerTypes.insert(Ty);
else if (Ty->getAs<PointerType>() || Ty->getAs<ObjCObjectPointerType>()) {
@@ -4350,35 +4786,36 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty))
return;
} else if (Ty->isEnumeralType()) {
+ HasArithmeticOrEnumeralTypes = true;
EnumerationTypes.insert(Ty);
} else if (Ty->isVectorType()) {
+ // We treat vector types as arithmetic types in many contexts as an
+ // extension.
+ HasArithmeticOrEnumeralTypes = true;
VectorTypes.insert(Ty);
- } else if (AllowUserConversions) {
- if (const RecordType *TyRec = Ty->getAs<RecordType>()) {
- if (SemaRef.RequireCompleteType(Loc, Ty, 0)) {
- // No conversion functions in incomplete types.
- return;
- }
+ } else if (AllowUserConversions && TyRec) {
+ // No conversion functions in incomplete types.
+ if (SemaRef.RequireCompleteType(Loc, Ty, 0))
+ return;
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
- const UnresolvedSetImpl *Conversions
- = ClassDecl->getVisibleConversionFunctions();
- for (UnresolvedSetImpl::iterator I = Conversions->begin(),
- E = Conversions->end(); I != E; ++I) {
- NamedDecl *D = I.getDecl();
- if (isa<UsingShadowDecl>(D))
- D = cast<UsingShadowDecl>(D)->getTargetDecl();
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
+ const UnresolvedSetImpl *Conversions
+ = ClassDecl->getVisibleConversionFunctions();
+ for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+ E = Conversions->end(); I != E; ++I) {
+ NamedDecl *D = I.getDecl();
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
- // Skip conversion function templates; they don't tell us anything
- // about which builtin types we can convert to.
- if (isa<FunctionTemplateDecl>(D))
- continue;
+ // Skip conversion function templates; they don't tell us anything
+ // about which builtin types we can convert to.
+ if (isa<FunctionTemplateDecl>(D))
+ continue;
- CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
- if (AllowExplicitConversions || !Conv->isExplicit()) {
- AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,
- VisibleQuals);
- }
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
+ if (AllowExplicitConversions || !Conv->isExplicit()) {
+ AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,
+ VisibleQuals);
}
}
}
@@ -4426,14 +4863,14 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
VRQuals.addRestrict();
return VRQuals;
}
-
+
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
if (!ClassDecl->hasDefinition())
return VRQuals;
const UnresolvedSetImpl *Conversions =
ClassDecl->getVisibleConversionFunctions();
-
+
for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
NamedDecl *D = I.getDecl();
@@ -4449,7 +4886,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
while (!done) {
if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>())
CanTy = ResTypePtr->getPointeeType();
- else if (const MemberPointerType *ResTypeMPtr =
+ else if (const MemberPointerType *ResTypeMPtr =
CanTy->getAs<MemberPointerType>())
CanTy = ResTypeMPtr->getPointeeType();
else
@@ -4465,765 +4902,1174 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
}
return VRQuals;
}
-
-/// AddBuiltinOperatorCandidates - Add the appropriate built-in
-/// operator overloads to the candidate set (C++ [over.built]), based
-/// on the operator @p Op and the arguments given. For example, if the
-/// operator is a binary '+', this routine might add "int
-/// operator+(int, int)" to cover integer addition.
-void
-Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
- SourceLocation OpLoc,
- Expr **Args, unsigned NumArgs,
- OverloadCandidateSet& CandidateSet) {
- // The set of "promoted arithmetic types", which are the arithmetic
- // types are that preserved by promotion (C++ [over.built]p2). Note
- // that the first few of these types are the promoted integral
- // types; these types need to be first.
- // FIXME: What about complex?
- const unsigned FirstIntegralType = 0;
- const unsigned LastIntegralType = 13;
- const unsigned FirstPromotedIntegralType = 7,
- LastPromotedIntegralType = 13;
- const unsigned FirstPromotedArithmeticType = 7,
- LastPromotedArithmeticType = 16;
- const unsigned NumArithmeticTypes = 16;
- QualType ArithmeticTypes[NumArithmeticTypes] = {
- Context.BoolTy, Context.CharTy, Context.WCharTy,
-// FIXME: Context.Char16Ty, Context.Char32Ty,
- Context.SignedCharTy, Context.ShortTy,
- Context.UnsignedCharTy, Context.UnsignedShortTy,
- Context.IntTy, Context.LongTy, Context.LongLongTy,
- Context.UnsignedIntTy, Context.UnsignedLongTy, Context.UnsignedLongLongTy,
- Context.FloatTy, Context.DoubleTy, Context.LongDoubleTy
- };
- assert(ArithmeticTypes[FirstPromotedIntegralType] == Context.IntTy &&
- "Invalid first promoted integral type");
- assert(ArithmeticTypes[LastPromotedIntegralType - 1]
- == Context.UnsignedLongLongTy &&
- "Invalid last promoted integral type");
- assert(ArithmeticTypes[FirstPromotedArithmeticType] == Context.IntTy &&
- "Invalid first promoted arithmetic type");
- assert(ArithmeticTypes[LastPromotedArithmeticType - 1]
- == Context.LongDoubleTy &&
- "Invalid last promoted arithmetic type");
-
- // Find all of the types that the arguments can convert to, but only
- // if the operator we're looking at has built-in operator candidates
- // that make use of these types.
- Qualifiers VisibleTypeConversionsQuals;
- VisibleTypeConversionsQuals.addConst();
- for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
- VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
-
- BuiltinCandidateTypeSet CandidateTypes(*this);
- for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
- CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(),
- OpLoc,
- true,
- (Op == OO_Exclaim ||
- Op == OO_AmpAmp ||
- Op == OO_PipePipe),
- VisibleTypeConversionsQuals);
-
- bool isComparison = false;
- switch (Op) {
- case OO_None:
- case NUM_OVERLOADED_OPERATORS:
- assert(false && "Expected an overloaded operator");
- break;
- case OO_Star: // '*' is either unary or binary
- if (NumArgs == 1)
- goto UnaryStar;
- else
- goto BinaryStar;
- break;
+namespace {
- case OO_Plus: // '+' is either unary or binary
- if (NumArgs == 1)
- goto UnaryPlus;
- else
- goto BinaryPlus;
- break;
+/// \brief Helper class to manage the addition of builtin operator overload
+/// candidates. It provides shared state and utility methods used throughout
+/// the process, as well as a helper method to add each group of builtin
+/// operator overloads from the standard to a candidate set.
+class BuiltinOperatorOverloadBuilder {
+ // Common instance state available to all overload candidate addition methods.
+ Sema &S;
+ Expr **Args;
+ unsigned NumArgs;
+ Qualifiers VisibleTypeConversionsQuals;
+ bool HasArithmeticOrEnumeralCandidateType;
+ llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
+ OverloadCandidateSet &CandidateSet;
+
+ // Define some constants used to index and iterate over the arithemetic types
+ // provided via the getArithmeticType() method below.
+ // The "promoted arithmetic types" are the arithmetic
+ // types are that preserved by promotion (C++ [over.built]p2).
+ static const unsigned FirstIntegralType = 3;
+ static const unsigned LastIntegralType = 18;
+ static const unsigned FirstPromotedIntegralType = 3,
+ LastPromotedIntegralType = 9;
+ static const unsigned FirstPromotedArithmeticType = 0,
+ LastPromotedArithmeticType = 9;
+ static const unsigned NumArithmeticTypes = 18;
+
+ /// \brief Get the canonical type for a given arithmetic type index.
+ CanQualType getArithmeticType(unsigned index) {
+ assert(index < NumArithmeticTypes);
+ static CanQualType ASTContext::* const
+ ArithmeticTypes[NumArithmeticTypes] = {
+ // Start of promoted types.
+ &ASTContext::FloatTy,
+ &ASTContext::DoubleTy,
+ &ASTContext::LongDoubleTy,
+
+ // Start of integral types.
+ &ASTContext::IntTy,
+ &ASTContext::LongTy,
+ &ASTContext::LongLongTy,
+ &ASTContext::UnsignedIntTy,
+ &ASTContext::UnsignedLongTy,
+ &ASTContext::UnsignedLongLongTy,
+ // End of promoted types.
+
+ &ASTContext::BoolTy,
+ &ASTContext::CharTy,
+ &ASTContext::WCharTy,
+ &ASTContext::Char16Ty,
+ &ASTContext::Char32Ty,
+ &ASTContext::SignedCharTy,
+ &ASTContext::ShortTy,
+ &ASTContext::UnsignedCharTy,
+ &ASTContext::UnsignedShortTy,
+ // End of integral types.
+ // FIXME: What about complex?
+ };
+ return S.Context.*ArithmeticTypes[index];
+ }
+
+ /// \brief Gets the canonical type resulting from the usual arithemetic
+ /// converions for the given arithmetic types.
+ CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) {
+ // Accelerator table for performing the usual arithmetic conversions.
+ // The rules are basically:
+ // - if either is floating-point, use the wider floating-point
+ // - if same signedness, use the higher rank
+ // - if same size, use unsigned of the higher rank
+ // - use the larger type
+ // These rules, together with the axiom that higher ranks are
+ // never smaller, are sufficient to precompute all of these results
+ // *except* when dealing with signed types of higher rank.
+ // (we could precompute SLL x UI for all known platforms, but it's
+ // better not to make any assumptions).
+ enum PromotedType {
+ Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL, Dep=-1
+ };
+ static PromotedType ConversionsTable[LastPromotedArithmeticType]
+ [LastPromotedArithmeticType] = {
+ /* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt },
+ /* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl },
+ /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl },
+ /* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL },
+ /* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, Dep, UL, ULL },
+ /* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, Dep, Dep, ULL },
+ /* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, UI, UL, ULL },
+ /* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, UL, UL, ULL },
+ /* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, ULL, ULL, ULL },
+ };
- case OO_Minus: // '-' is either unary or binary
- if (NumArgs == 1)
- goto UnaryMinus;
- else
- goto BinaryMinus;
- break;
+ assert(L < LastPromotedArithmeticType);
+ assert(R < LastPromotedArithmeticType);
+ int Idx = ConversionsTable[L][R];
+
+ // Fast path: the table gives us a concrete answer.
+ if (Idx != Dep) return getArithmeticType(Idx);
+
+ // Slow path: we need to compare widths.
+ // An invariant is that the signed type has higher rank.
+ CanQualType LT = getArithmeticType(L),
+ RT = getArithmeticType(R);
+ unsigned LW = S.Context.getIntWidth(LT),
+ RW = S.Context.getIntWidth(RT);
+
+ // If they're different widths, use the signed type.
+ if (LW > RW) return LT;
+ else if (LW < RW) return RT;
+
+ // Otherwise, use the unsigned type of the signed type's rank.
+ if (L == SL || R == SL) return S.Context.UnsignedLongTy;
+ assert(L == SLL || R == SLL);
+ return S.Context.UnsignedLongLongTy;
+ }
+
+ /// \brief Helper method to factor out the common pattern of adding overloads
+ /// for '++' and '--' builtin operators.
+ void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
+ bool HasVolatile) {
+ QualType ParamTypes[2] = {
+ S.Context.getLValueReferenceType(CandidateTy),
+ S.Context.IntTy
+ };
- case OO_Amp: // '&' is either unary or binary
+ // Non-volatile version.
if (NumArgs == 1)
- goto UnaryAmp;
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
else
- goto BinaryAmp;
+ S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet);
+
+ // Use a heuristic to reduce number of builtin candidates in the set:
+ // add volatile version only if there are conversions to a volatile type.
+ if (HasVolatile) {
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(
+ S.Context.getVolatileType(CandidateTy));
+ if (NumArgs == 1)
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
+ else
+ S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet);
+ }
+ }
+
+public:
+ BuiltinOperatorOverloadBuilder(
+ Sema &S, Expr **Args, unsigned NumArgs,
+ Qualifiers VisibleTypeConversionsQuals,
+ bool HasArithmeticOrEnumeralCandidateType,
+ llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes,
+ OverloadCandidateSet &CandidateSet)
+ : S(S), Args(Args), NumArgs(NumArgs),
+ VisibleTypeConversionsQuals(VisibleTypeConversionsQuals),
+ HasArithmeticOrEnumeralCandidateType(
+ HasArithmeticOrEnumeralCandidateType),
+ CandidateTypes(CandidateTypes),
+ CandidateSet(CandidateSet) {
+ // Validate some of our static helper constants in debug builds.
+ assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy &&
+ "Invalid first promoted integral type");
+ assert(getArithmeticType(LastPromotedIntegralType - 1)
+ == S.Context.UnsignedLongLongTy &&
+ "Invalid last promoted integral type");
+ assert(getArithmeticType(FirstPromotedArithmeticType)
+ == S.Context.FloatTy &&
+ "Invalid first promoted arithmetic type");
+ assert(getArithmeticType(LastPromotedArithmeticType - 1)
+ == S.Context.UnsignedLongLongTy &&
+ "Invalid last promoted arithmetic type");
+ }
+
+ // C++ [over.built]p3:
+ //
+ // For every pair (T, VQ), where T is an arithmetic type, and VQ
+ // is either volatile or empty, there exist candidate operator
+ // functions of the form
+ //
+ // VQ T& operator++(VQ T&);
+ // T operator++(VQ T&, int);
+ //
+ // C++ [over.built]p4:
+ //
+ // For every pair (T, VQ), where T is an arithmetic type other
+ // than bool, and VQ is either volatile or empty, there exist
+ // candidate operator functions of the form
+ //
+ // VQ T& operator--(VQ T&);
+ // T operator--(VQ T&, int);
+ void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
- case OO_PlusPlus:
- case OO_MinusMinus:
- // C++ [over.built]p3:
- //
- // For every pair (T, VQ), where T is an arithmetic type, and VQ
- // is either volatile or empty, there exist candidate operator
- // functions of the form
- //
- // VQ T& operator++(VQ T&);
- // T operator++(VQ T&, int);
- //
- // C++ [over.built]p4:
- //
- // For every pair (T, VQ), where T is an arithmetic type other
- // than bool, and VQ is either volatile or empty, there exist
- // candidate operator functions of the form
- //
- // VQ T& operator--(VQ T&);
- // T operator--(VQ T&, int);
for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
Arith < NumArithmeticTypes; ++Arith) {
- QualType ArithTy = ArithmeticTypes[Arith];
- QualType ParamTypes[2]
- = { Context.getLValueReferenceType(ArithTy), Context.IntTy };
-
- // Non-volatile version.
- if (NumArgs == 1)
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
- else
- AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
- // heuristic to reduce number of builtin candidates in the set.
- // Add volatile version only if there are conversions to a volatile type.
- if (VisibleTypeConversionsQuals.hasVolatile()) {
- // Volatile version
- ParamTypes[0]
- = Context.getLValueReferenceType(Context.getVolatileType(ArithTy));
- if (NumArgs == 1)
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
- else
- AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
- }
+ addPlusPlusMinusMinusStyleOverloads(
+ getArithmeticType(Arith),
+ VisibleTypeConversionsQuals.hasVolatile());
}
+ }
- // C++ [over.built]p5:
- //
- // For every pair (T, VQ), where T is a cv-qualified or
- // cv-unqualified object type, and VQ is either volatile or
- // empty, there exist candidate operator functions of the form
- //
- // T*VQ& operator++(T*VQ&);
- // T*VQ& operator--(T*VQ&);
- // T* operator++(T*VQ&, int);
- // T* operator--(T*VQ&, int);
- for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
- Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+ // C++ [over.built]p5:
+ //
+ // For every pair (T, VQ), where T is a cv-qualified or
+ // cv-unqualified object type, and VQ is either volatile or
+ // empty, there exist candidate operator functions of the form
+ //
+ // T*VQ& operator++(T*VQ&);
+ // T*VQ& operator--(T*VQ&);
+ // T* operator++(T*VQ&, int);
+ // T* operator--(T*VQ&, int);
+ void addPlusPlusMinusMinusPointerOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
// Skip pointer types that aren't pointers to object types.
- if (!(*Ptr)->getPointeeType()->isIncompleteOrObjectType())
+ if (!(*Ptr)->getPointeeType()->isObjectType())
continue;
- QualType ParamTypes[2] = {
- Context.getLValueReferenceType(*Ptr), Context.IntTy
- };
-
- // Without volatile
- if (NumArgs == 1)
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
- else
- AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
-
- if (!Context.getCanonicalType(*Ptr).isVolatileQualified() &&
- VisibleTypeConversionsQuals.hasVolatile()) {
- // With volatile
- ParamTypes[0]
- = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
- if (NumArgs == 1)
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
- else
- AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
- }
+ addPlusPlusMinusMinusStyleOverloads(*Ptr,
+ (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile()));
}
- break;
+ }
- UnaryStar:
- // C++ [over.built]p6:
- // For every cv-qualified or cv-unqualified object type T, there
- // exist candidate operator functions of the form
- //
- // T& operator*(T*);
- //
- // C++ [over.built]p7:
- // For every function type T, there exist candidate operator
- // functions of the form
- // T& operator*(T*);
- for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
- Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+ // C++ [over.built]p6:
+ // For every cv-qualified or cv-unqualified object type T, there
+ // exist candidate operator functions of the form
+ //
+ // T& operator*(T*);
+ //
+ // C++ [over.built]p7:
+ // For every function type T that does not have cv-qualifiers or a
+ // ref-qualifier, there exist candidate operator functions of the form
+ // T& operator*(T*);
+ void addUnaryStarPointerOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
QualType ParamTy = *Ptr;
QualType PointeeTy = ParamTy->getPointeeType();
- AddBuiltinCandidate(Context.getLValueReferenceType(PointeeTy),
- &ParamTy, Args, 1, CandidateSet);
- }
- break;
+ if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType())
+ continue;
- UnaryPlus:
- // C++ [over.built]p8:
- // For every type T, there exist candidate operator functions of
- // the form
- //
- // T* operator+(T*);
- for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
- Ptr != CandidateTypes.pointer_end(); ++Ptr) {
- QualType ParamTy = *Ptr;
- AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet);
+ if (const FunctionProtoType *Proto =PointeeTy->getAs<FunctionProtoType>())
+ if (Proto->getTypeQuals() || Proto->getRefQualifier())
+ continue;
+
+ S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy),
+ &ParamTy, Args, 1, CandidateSet);
}
+ }
- // Fall through
+ // C++ [over.built]p9:
+ // For every promoted arithmetic type T, there exist candidate
+ // operator functions of the form
+ //
+ // T operator+(T);
+ // T operator-(T);
+ void addUnaryPlusOrMinusArithmeticOverloads() {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
- UnaryMinus:
- // C++ [over.built]p9:
- // For every promoted arithmetic type T, there exist candidate
- // operator functions of the form
- //
- // T operator+(T);
- // T operator-(T);
for (unsigned Arith = FirstPromotedArithmeticType;
Arith < LastPromotedArithmeticType; ++Arith) {
- QualType ArithTy = ArithmeticTypes[Arith];
- AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet);
+ QualType ArithTy = getArithmeticType(Arith);
+ S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet);
}
-
+
// Extension: We also add these operators for vector types.
- for (BuiltinCandidateTypeSet::iterator Vec = CandidateTypes.vector_begin(),
- VecEnd = CandidateTypes.vector_end();
+ for (BuiltinCandidateTypeSet::iterator
+ Vec = CandidateTypes[0].vector_begin(),
+ VecEnd = CandidateTypes[0].vector_end();
Vec != VecEnd; ++Vec) {
QualType VecTy = *Vec;
- AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
+ S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
}
- break;
+ }
+
+ // C++ [over.built]p8:
+ // For every type T, there exist candidate operator functions of
+ // the form
+ //
+ // T* operator+(T*);
+ void addUnaryPlusPointerOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType ParamTy = *Ptr;
+ S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet);
+ }
+ }
+
+ // C++ [over.built]p10:
+ // For every promoted integral type T, there exist candidate
+ // operator functions of the form
+ //
+ // T operator~(T);
+ void addUnaryTildePromotedIntegralOverloads() {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
- case OO_Tilde:
- // C++ [over.built]p10:
- // For every promoted integral type T, there exist candidate
- // operator functions of the form
- //
- // T operator~(T);
for (unsigned Int = FirstPromotedIntegralType;
Int < LastPromotedIntegralType; ++Int) {
- QualType IntTy = ArithmeticTypes[Int];
- AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet);
+ QualType IntTy = getArithmeticType(Int);
+ S.AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet);
}
-
+
// Extension: We also add this operator for vector types.
- for (BuiltinCandidateTypeSet::iterator Vec = CandidateTypes.vector_begin(),
- VecEnd = CandidateTypes.vector_end();
+ for (BuiltinCandidateTypeSet::iterator
+ Vec = CandidateTypes[0].vector_begin(),
+ VecEnd = CandidateTypes[0].vector_end();
Vec != VecEnd; ++Vec) {
QualType VecTy = *Vec;
- AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
- }
- break;
+ S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
+ }
+ }
- case OO_New:
- case OO_Delete:
- case OO_Array_New:
- case OO_Array_Delete:
- case OO_Call:
- assert(false && "Special operators don't use AddBuiltinOperatorCandidates");
- break;
+ // C++ [over.match.oper]p16:
+ // For every pointer to member type T, there exist candidate operator
+ // functions of the form
+ //
+ // bool operator==(T,T);
+ // bool operator!=(T,T);
+ void addEqualEqualOrNotEqualMemberPointerOverloads() {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+ MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+ MemPtr != MemPtrEnd;
+ ++MemPtr) {
+ // Don't add the same builtin candidate twice.
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+ continue;
- case OO_Comma:
- UnaryAmp:
- case OO_Arrow:
- // C++ [over.match.oper]p3:
- // -- For the operator ',', the unary operator '&', or the
- // operator '->', the built-in candidates set is empty.
- break;
+ QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+ CandidateSet);
+ }
+ }
+ }
- case OO_EqualEqual:
- case OO_ExclaimEqual:
- // C++ [over.match.oper]p16:
- // For every pointer to member type T, there exist candidate operator
- // functions of the form
+ // C++ [over.built]p15:
+ //
+ // For every pointer or enumeration type T, there exist
+ // candidate operator functions of the form
+ //
+ // bool operator<(T, T);
+ // bool operator>(T, T);
+ // bool operator<=(T, T);
+ // bool operator>=(T, T);
+ // bool operator==(T, T);
+ // bool operator!=(T, T);
+ void addRelationalPointerOrEnumeralOverloads() {
+ // C++ [over.built]p1:
+ // If there is a user-written candidate with the same name and parameter
+ // types as a built-in candidate operator function, the built-in operator
+ // function is hidden and is not included in the set of candidate
+ // functions.
//
- // bool operator==(T,T);
- // bool operator!=(T,T);
- for (BuiltinCandidateTypeSet::iterator
- MemPtr = CandidateTypes.member_pointer_begin(),
- MemPtrEnd = CandidateTypes.member_pointer_end();
- MemPtr != MemPtrEnd;
- ++MemPtr) {
- QualType ParamTypes[2] = { *MemPtr, *MemPtr };
- AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
- }
+ // The text is actually in a note, but if we don't implement it then we end
+ // up with ambiguities when the user provides an overloaded operator for
+ // an enumeration type. Note that only enumeration types have this problem,
+ // so we track which enumeration types we've seen operators for. Also, the
+ // only other overloaded operator with enumeration argumenst, operator=,
+ // cannot be overloaded for enumeration types, so this is the only place
+ // where we must suppress candidates like this.
+ llvm::DenseSet<std::pair<CanQualType, CanQualType> >
+ UserDefinedBinaryOperators;
+
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ if (CandidateTypes[ArgIdx].enumeration_begin() !=
+ CandidateTypes[ArgIdx].enumeration_end()) {
+ for (OverloadCandidateSet::iterator C = CandidateSet.begin(),
+ CEnd = CandidateSet.end();
+ C != CEnd; ++C) {
+ if (!C->Viable || !C->Function || C->Function->getNumParams() != 2)
+ continue;
- // Fall through
+ QualType FirstParamType =
+ C->Function->getParamDecl(0)->getType().getUnqualifiedType();
+ QualType SecondParamType =
+ C->Function->getParamDecl(1)->getType().getUnqualifiedType();
- case OO_Less:
- case OO_Greater:
- case OO_LessEqual:
- case OO_GreaterEqual:
- // C++ [over.built]p15:
- //
- // For every pointer or enumeration type T, there exist
- // candidate operator functions of the form
- //
- // bool operator<(T, T);
- // bool operator>(T, T);
- // bool operator<=(T, T);
- // bool operator>=(T, T);
- // bool operator==(T, T);
- // bool operator!=(T, T);
- for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
- Ptr != CandidateTypes.pointer_end(); ++Ptr) {
- QualType ParamTypes[2] = { *Ptr, *Ptr };
- AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
- }
- for (BuiltinCandidateTypeSet::iterator Enum
- = CandidateTypes.enumeration_begin();
- Enum != CandidateTypes.enumeration_end(); ++Enum) {
- QualType ParamTypes[2] = { *Enum, *Enum };
- AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
+ // Skip if either parameter isn't of enumeral type.
+ if (!FirstParamType->isEnumeralType() ||
+ !SecondParamType->isEnumeralType())
+ continue;
+
+ // Add this operator to the set of known user-defined operators.
+ UserDefinedBinaryOperators.insert(
+ std::make_pair(S.Context.getCanonicalType(FirstParamType),
+ S.Context.getCanonicalType(SecondParamType)));
+ }
+ }
}
- // Fall through.
- isComparison = true;
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
- BinaryPlus:
- BinaryMinus:
- if (!isComparison) {
- // We didn't fall through, so we must have OO_Plus or OO_Minus.
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[ArgIdx].pointer_begin(),
+ PtrEnd = CandidateTypes[ArgIdx].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ // Don't add the same builtin candidate twice.
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ continue;
- // C++ [over.built]p13:
- //
- // For every cv-qualified or cv-unqualified object type T
- // there exist candidate operator functions of the form
- //
- // T* operator+(T*, ptrdiff_t);
- // T& operator[](T*, ptrdiff_t); [BELOW]
- // T* operator-(T*, ptrdiff_t);
- // T* operator+(ptrdiff_t, T*);
- // T& operator[](ptrdiff_t, T*); [BELOW]
- //
- // C++ [over.built]p14:
- //
- // For every T, where T is a pointer to object type, there
- // exist candidate operator functions of the form
- //
- // ptrdiff_t operator-(T, T);
- for (BuiltinCandidateTypeSet::iterator Ptr
- = CandidateTypes.pointer_begin();
- Ptr != CandidateTypes.pointer_end(); ++Ptr) {
- QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
+ QualType ParamTypes[2] = { *Ptr, *Ptr };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+ CandidateSet);
+ }
+ for (BuiltinCandidateTypeSet::iterator
+ Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+ EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+ Enum != EnumEnd; ++Enum) {
+ CanQualType CanonType = S.Context.getCanonicalType(*Enum);
+
+ // Don't add the same builtin candidate twice, or if a user defined
+ // candidate exists.
+ if (!AddedTypes.insert(CanonType) ||
+ UserDefinedBinaryOperators.count(std::make_pair(CanonType,
+ CanonType)))
+ continue;
- // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
- AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+ QualType ParamTypes[2] = { *Enum, *Enum };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2,
+ CandidateSet);
+ }
+ }
+ }
- if (Op == OO_Plus) {
+ // C++ [over.built]p13:
+ //
+ // For every cv-qualified or cv-unqualified object type T
+ // there exist candidate operator functions of the form
+ //
+ // T* operator+(T*, ptrdiff_t);
+ // T& operator[](T*, ptrdiff_t); [BELOW]
+ // T* operator-(T*, ptrdiff_t);
+ // T* operator+(ptrdiff_t, T*);
+ // T& operator[](ptrdiff_t, T*); [BELOW]
+ //
+ // C++ [over.built]p14:
+ //
+ // For every T, where T is a pointer to object type, there
+ // exist candidate operator functions of the form
+ //
+ // ptrdiff_t operator-(T, T);
+ void addBinaryPlusOrMinusPointerOverloads(OverloadedOperatorKind Op) {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (int Arg = 0; Arg < 2; ++Arg) {
+ QualType AsymetricParamTypes[2] = {
+ S.Context.getPointerDiffType(),
+ S.Context.getPointerDiffType(),
+ };
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[Arg].pointer_begin(),
+ PtrEnd = CandidateTypes[Arg].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType PointeeTy = (*Ptr)->getPointeeType();
+ if (!PointeeTy->isObjectType())
+ continue;
+
+ AsymetricParamTypes[Arg] = *Ptr;
+ if (Arg == 0 || Op == OO_Plus) {
+ // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
// T* operator+(ptrdiff_t, T*);
- ParamTypes[0] = ParamTypes[1];
- ParamTypes[1] = *Ptr;
- AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
- } else {
+ S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, 2,
+ CandidateSet);
+ }
+ if (Op == OO_Minus) {
// ptrdiff_t operator-(T, T);
- ParamTypes[1] = *Ptr;
- AddBuiltinCandidate(Context.getPointerDiffType(), ParamTypes,
- Args, 2, CandidateSet);
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ continue;
+
+ QualType ParamTypes[2] = { *Ptr, *Ptr };
+ S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes,
+ Args, 2, CandidateSet);
}
}
}
- // Fall through
+ }
+
+ // C++ [over.built]p12:
+ //
+ // For every pair of promoted arithmetic types L and R, there
+ // exist candidate operator functions of the form
+ //
+ // LR operator*(L, R);
+ // LR operator/(L, R);
+ // LR operator+(L, R);
+ // LR operator-(L, R);
+ // bool operator<(L, R);
+ // bool operator>(L, R);
+ // bool operator<=(L, R);
+ // bool operator>=(L, R);
+ // bool operator==(L, R);
+ // bool operator!=(L, R);
+ //
+ // where LR is the result of the usual arithmetic conversions
+ // between types L and R.
+ //
+ // C++ [over.built]p24:
+ //
+ // For every pair of promoted arithmetic types L and R, there exist
+ // candidate operator functions of the form
+ //
+ // LR operator?(bool, L, R);
+ //
+ // where LR is the result of the usual arithmetic conversions
+ // between types L and R.
+ // Our candidates ignore the first parameter.
+ void addGenericBinaryArithmeticOverloads(bool isComparison) {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
- case OO_Slash:
- BinaryStar:
- Conditional:
- // C++ [over.built]p12:
- //
- // For every pair of promoted arithmetic types L and R, there
- // exist candidate operator functions of the form
- //
- // LR operator*(L, R);
- // LR operator/(L, R);
- // LR operator+(L, R);
- // LR operator-(L, R);
- // bool operator<(L, R);
- // bool operator>(L, R);
- // bool operator<=(L, R);
- // bool operator>=(L, R);
- // bool operator==(L, R);
- // bool operator!=(L, R);
- //
- // where LR is the result of the usual arithmetic conversions
- // between types L and R.
- //
- // C++ [over.built]p24:
- //
- // For every pair of promoted arithmetic types L and R, there exist
- // candidate operator functions of the form
- //
- // LR operator?(bool, L, R);
- //
- // where LR is the result of the usual arithmetic conversions
- // between types L and R.
- // Our candidates ignore the first parameter.
for (unsigned Left = FirstPromotedArithmeticType;
Left < LastPromotedArithmeticType; ++Left) {
for (unsigned Right = FirstPromotedArithmeticType;
Right < LastPromotedArithmeticType; ++Right) {
- QualType LandR[2] = { ArithmeticTypes[Left], ArithmeticTypes[Right] };
- QualType Result
- = isComparison
- ? Context.BoolTy
- : Context.UsualArithmeticConversionsType(LandR[0], LandR[1]);
- AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+ QualType LandR[2] = { getArithmeticType(Left),
+ getArithmeticType(Right) };
+ QualType Result =
+ isComparison ? S.Context.BoolTy
+ : getUsualArithmeticConversions(Left, Right);
+ S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
}
}
// Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the
// conditional operator for vector types.
- for (BuiltinCandidateTypeSet::iterator Vec1 = CandidateTypes.vector_begin(),
- Vec1End = CandidateTypes.vector_end();
- Vec1 != Vec1End; ++Vec1)
- for (BuiltinCandidateTypeSet::iterator
- Vec2 = CandidateTypes.vector_begin(),
- Vec2End = CandidateTypes.vector_end();
+ for (BuiltinCandidateTypeSet::iterator
+ Vec1 = CandidateTypes[0].vector_begin(),
+ Vec1End = CandidateTypes[0].vector_end();
+ Vec1 != Vec1End; ++Vec1) {
+ for (BuiltinCandidateTypeSet::iterator
+ Vec2 = CandidateTypes[1].vector_begin(),
+ Vec2End = CandidateTypes[1].vector_end();
Vec2 != Vec2End; ++Vec2) {
QualType LandR[2] = { *Vec1, *Vec2 };
- QualType Result;
- if (isComparison)
- Result = Context.BoolTy;
- else {
+ QualType Result = S.Context.BoolTy;
+ if (!isComparison) {
if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType())
Result = *Vec1;
else
Result = *Vec2;
}
-
- AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+
+ S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
}
-
- break;
+ }
+ }
+
+ // C++ [over.built]p17:
+ //
+ // For every pair of promoted integral types L and R, there
+ // exist candidate operator functions of the form
+ //
+ // LR operator%(L, R);
+ // LR operator&(L, R);
+ // LR operator^(L, R);
+ // LR operator|(L, R);
+ // L operator<<(L, R);
+ // L operator>>(L, R);
+ //
+ // where LR is the result of the usual arithmetic conversions
+ // between types L and R.
+ void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
- case OO_Percent:
- BinaryAmp:
- case OO_Caret:
- case OO_Pipe:
- case OO_LessLess:
- case OO_GreaterGreater:
- // C++ [over.built]p17:
- //
- // For every pair of promoted integral types L and R, there
- // exist candidate operator functions of the form
- //
- // LR operator%(L, R);
- // LR operator&(L, R);
- // LR operator^(L, R);
- // LR operator|(L, R);
- // L operator<<(L, R);
- // L operator>>(L, R);
- //
- // where LR is the result of the usual arithmetic conversions
- // between types L and R.
for (unsigned Left = FirstPromotedIntegralType;
Left < LastPromotedIntegralType; ++Left) {
for (unsigned Right = FirstPromotedIntegralType;
Right < LastPromotedIntegralType; ++Right) {
- QualType LandR[2] = { ArithmeticTypes[Left], ArithmeticTypes[Right] };
+ QualType LandR[2] = { getArithmeticType(Left),
+ getArithmeticType(Right) };
QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater)
? LandR[0]
- : Context.UsualArithmeticConversionsType(LandR[0], LandR[1]);
- AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
+ : getUsualArithmeticConversions(Left, Right);
+ S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet);
}
}
- break;
+ }
- case OO_Equal:
- // C++ [over.built]p20:
- //
- // For every pair (T, VQ), where T is an enumeration or
- // pointer to member type and VQ is either volatile or
- // empty, there exist candidate operator functions of the form
- //
- // VQ T& operator=(VQ T&, T);
- for (BuiltinCandidateTypeSet::iterator
- Enum = CandidateTypes.enumeration_begin(),
- EnumEnd = CandidateTypes.enumeration_end();
- Enum != EnumEnd; ++Enum)
- AddBuiltinAssignmentOperatorCandidates(*this, *Enum, Args, 2,
- CandidateSet);
- for (BuiltinCandidateTypeSet::iterator
- MemPtr = CandidateTypes.member_pointer_begin(),
- MemPtrEnd = CandidateTypes.member_pointer_end();
- MemPtr != MemPtrEnd; ++MemPtr)
- AddBuiltinAssignmentOperatorCandidates(*this, *MemPtr, Args, 2,
- CandidateSet);
-
- // Fall through.
+ // C++ [over.built]p20:
+ //
+ // For every pair (T, VQ), where T is an enumeration or
+ // pointer to member type and VQ is either volatile or
+ // empty, there exist candidate operator functions of the form
+ //
+ // VQ T& operator=(VQ T&, T);
+ void addAssignmentMemberPointerOrEnumeralOverloads() {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
+ for (BuiltinCandidateTypeSet::iterator
+ Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+ EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+ Enum != EnumEnd; ++Enum) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
+ continue;
- case OO_PlusEqual:
- case OO_MinusEqual:
- // C++ [over.built]p19:
- //
- // For every pair (T, VQ), where T is any type and VQ is either
- // volatile or empty, there exist candidate operator functions
- // of the form
- //
- // T*VQ& operator=(T*VQ&, T*);
- //
- // C++ [over.built]p21:
- //
- // For every pair (T, VQ), where T is a cv-qualified or
- // cv-unqualified object type and VQ is either volatile or
- // empty, there exist candidate operator functions of the form
- //
- // T*VQ& operator+=(T*VQ&, ptrdiff_t);
- // T*VQ& operator-=(T*VQ&, ptrdiff_t);
- for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
- Ptr != CandidateTypes.pointer_end(); ++Ptr) {
- QualType ParamTypes[2];
- ParamTypes[1] = (Op == OO_Equal)? *Ptr : Context.getPointerDiffType();
+ AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, 2,
+ CandidateSet);
+ }
+
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+ MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+ MemPtr != MemPtrEnd; ++MemPtr) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
+ continue;
+
+ AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, 2,
+ CandidateSet);
+ }
+ }
+ }
+
+ // C++ [over.built]p19:
+ //
+ // For every pair (T, VQ), where T is any type and VQ is either
+ // volatile or empty, there exist candidate operator functions
+ // of the form
+ //
+ // T*VQ& operator=(T*VQ&, T*);
+ //
+ // C++ [over.built]p21:
+ //
+ // For every pair (T, VQ), where T is a cv-qualified or
+ // cv-unqualified object type and VQ is either volatile or
+ // empty, there exist candidate operator functions of the form
+ //
+ // T*VQ& operator+=(T*VQ&, ptrdiff_t);
+ // T*VQ& operator-=(T*VQ&, ptrdiff_t);
+ void addAssignmentPointerOverloads(bool isEqualOp) {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ // If this is operator=, keep track of the builtin candidates we added.
+ if (isEqualOp)
+ AddedTypes.insert(S.Context.getCanonicalType(*Ptr));
+ else if (!(*Ptr)->getPointeeType()->isObjectType())
+ continue;
// non-volatile version
- ParamTypes[0] = Context.getLValueReferenceType(*Ptr);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
- /*IsAssigmentOperator=*/Op == OO_Equal);
+ QualType ParamTypes[2] = {
+ S.Context.getLValueReferenceType(*Ptr),
+ isEqualOp ? *Ptr : S.Context.getPointerDiffType(),
+ };
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/ isEqualOp);
- if (!Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+ if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
VisibleTypeConversionsQuals.hasVolatile()) {
// volatile version
- ParamTypes[0]
- = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
- /*IsAssigmentOperator=*/Op == OO_Equal);
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
}
}
- // Fall through.
- case OO_StarEqual:
- case OO_SlashEqual:
- // C++ [over.built]p18:
- //
- // For every triple (L, VQ, R), where L is an arithmetic type,
- // VQ is either volatile or empty, and R is a promoted
- // arithmetic type, there exist candidate operator functions of
- // the form
- //
- // VQ L& operator=(VQ L&, R);
- // VQ L& operator*=(VQ L&, R);
- // VQ L& operator/=(VQ L&, R);
- // VQ L& operator+=(VQ L&, R);
- // VQ L& operator-=(VQ L&, R);
+ if (isEqualOp) {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[1].pointer_begin(),
+ PtrEnd = CandidateTypes[1].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ // Make sure we don't add the same candidate twice.
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
+ continue;
+
+ QualType ParamTypes[2] = {
+ S.Context.getLValueReferenceType(*Ptr),
+ *Ptr,
+ };
+
+ // non-volatile version
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/true);
+
+ if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+ VisibleTypeConversionsQuals.hasVolatile()) {
+ // volatile version
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+ CandidateSet, /*IsAssigmentOperator=*/true);
+ }
+ }
+ }
+ }
+
+ // C++ [over.built]p18:
+ //
+ // For every triple (L, VQ, R), where L is an arithmetic type,
+ // VQ is either volatile or empty, and R is a promoted
+ // arithmetic type, there exist candidate operator functions of
+ // the form
+ //
+ // VQ L& operator=(VQ L&, R);
+ // VQ L& operator*=(VQ L&, R);
+ // VQ L& operator/=(VQ L&, R);
+ // VQ L& operator+=(VQ L&, R);
+ // VQ L& operator-=(VQ L&, R);
+ void addAssignmentArithmeticOverloads(bool isEqualOp) {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) {
for (unsigned Right = FirstPromotedArithmeticType;
Right < LastPromotedArithmeticType; ++Right) {
QualType ParamTypes[2];
- ParamTypes[1] = ArithmeticTypes[Right];
+ ParamTypes[1] = getArithmeticType(Right);
// Add this built-in operator as a candidate (VQ is empty).
- ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
- /*IsAssigmentOperator=*/Op == OO_Equal);
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(getArithmeticType(Left));
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
// Add this built-in operator as a candidate (VQ is 'volatile').
if (VisibleTypeConversionsQuals.hasVolatile()) {
- ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]);
- ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
- /*IsAssigmentOperator=*/Op == OO_Equal);
+ ParamTypes[0] =
+ S.Context.getVolatileType(getArithmeticType(Left));
+ ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+ CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
}
}
}
-
+
// Extension: Add the binary operators =, +=, -=, *=, /= for vector types.
- for (BuiltinCandidateTypeSet::iterator Vec1 = CandidateTypes.vector_begin(),
- Vec1End = CandidateTypes.vector_end();
- Vec1 != Vec1End; ++Vec1)
- for (BuiltinCandidateTypeSet::iterator
- Vec2 = CandidateTypes.vector_begin(),
- Vec2End = CandidateTypes.vector_end();
+ for (BuiltinCandidateTypeSet::iterator
+ Vec1 = CandidateTypes[0].vector_begin(),
+ Vec1End = CandidateTypes[0].vector_end();
+ Vec1 != Vec1End; ++Vec1) {
+ for (BuiltinCandidateTypeSet::iterator
+ Vec2 = CandidateTypes[1].vector_begin(),
+ Vec2End = CandidateTypes[1].vector_end();
Vec2 != Vec2End; ++Vec2) {
QualType ParamTypes[2];
ParamTypes[1] = *Vec2;
// Add this built-in operator as a candidate (VQ is empty).
- ParamTypes[0] = Context.getLValueReferenceType(*Vec1);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
- /*IsAssigmentOperator=*/Op == OO_Equal);
-
+ ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1);
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
+
// Add this built-in operator as a candidate (VQ is 'volatile').
if (VisibleTypeConversionsQuals.hasVolatile()) {
- ParamTypes[0] = Context.getVolatileType(*Vec1);
- ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
- /*IsAssigmentOperator=*/Op == OO_Equal);
+ ParamTypes[0] = S.Context.getVolatileType(*Vec1);
+ ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+ CandidateSet,
+ /*IsAssigmentOperator=*/isEqualOp);
}
}
- break;
+ }
+ }
+
+ // C++ [over.built]p22:
+ //
+ // For every triple (L, VQ, R), where L is an integral type, VQ
+ // is either volatile or empty, and R is a promoted integral
+ // type, there exist candidate operator functions of the form
+ //
+ // VQ L& operator%=(VQ L&, R);
+ // VQ L& operator<<=(VQ L&, R);
+ // VQ L& operator>>=(VQ L&, R);
+ // VQ L& operator&=(VQ L&, R);
+ // VQ L& operator^=(VQ L&, R);
+ // VQ L& operator|=(VQ L&, R);
+ void addAssignmentIntegralOverloads() {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
- case OO_PercentEqual:
- case OO_LessLessEqual:
- case OO_GreaterGreaterEqual:
- case OO_AmpEqual:
- case OO_CaretEqual:
- case OO_PipeEqual:
- // C++ [over.built]p22:
- //
- // For every triple (L, VQ, R), where L is an integral type, VQ
- // is either volatile or empty, and R is a promoted integral
- // type, there exist candidate operator functions of the form
- //
- // VQ L& operator%=(VQ L&, R);
- // VQ L& operator<<=(VQ L&, R);
- // VQ L& operator>>=(VQ L&, R);
- // VQ L& operator&=(VQ L&, R);
- // VQ L& operator^=(VQ L&, R);
- // VQ L& operator|=(VQ L&, R);
for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) {
for (unsigned Right = FirstPromotedIntegralType;
Right < LastPromotedIntegralType; ++Right) {
QualType ParamTypes[2];
- ParamTypes[1] = ArithmeticTypes[Right];
+ ParamTypes[1] = getArithmeticType(Right);
// Add this built-in operator as a candidate (VQ is empty).
- ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
+ ParamTypes[0] =
+ S.Context.getLValueReferenceType(getArithmeticType(Left));
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
if (VisibleTypeConversionsQuals.hasVolatile()) {
// Add this built-in operator as a candidate (VQ is 'volatile').
- ParamTypes[0] = ArithmeticTypes[Left];
- ParamTypes[0] = Context.getVolatileType(ParamTypes[0]);
- ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
- AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
+ ParamTypes[0] = getArithmeticType(Left);
+ ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]);
+ ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
+ S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2,
+ CandidateSet);
}
}
}
- break;
-
- case OO_Exclaim: {
- // C++ [over.operator]p23:
- //
- // There also exist candidate operator functions of the form
- //
- // bool operator!(bool);
- // bool operator&&(bool, bool); [BELOW]
- // bool operator||(bool, bool); [BELOW]
- QualType ParamTy = Context.BoolTy;
- AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet,
- /*IsAssignmentOperator=*/false,
- /*NumContextualBoolArguments=*/1);
- break;
- }
-
- case OO_AmpAmp:
- case OO_PipePipe: {
- // C++ [over.operator]p23:
- //
- // There also exist candidate operator functions of the form
- //
- // bool operator!(bool); [ABOVE]
- // bool operator&&(bool, bool);
- // bool operator||(bool, bool);
- QualType ParamTypes[2] = { Context.BoolTy, Context.BoolTy };
- AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet,
- /*IsAssignmentOperator=*/false,
- /*NumContextualBoolArguments=*/2);
- break;
}
- case OO_Subscript:
- // C++ [over.built]p13:
- //
- // For every cv-qualified or cv-unqualified object type T there
- // exist candidate operator functions of the form
- //
- // T* operator+(T*, ptrdiff_t); [ABOVE]
- // T& operator[](T*, ptrdiff_t);
- // T* operator-(T*, ptrdiff_t); [ABOVE]
- // T* operator+(ptrdiff_t, T*); [ABOVE]
- // T& operator[](ptrdiff_t, T*);
- for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
- Ptr != CandidateTypes.pointer_end(); ++Ptr) {
- QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
+ // C++ [over.operator]p23:
+ //
+ // There also exist candidate operator functions of the form
+ //
+ // bool operator!(bool);
+ // bool operator&&(bool, bool);
+ // bool operator||(bool, bool);
+ void addExclaimOverload() {
+ QualType ParamTy = S.Context.BoolTy;
+ S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet,
+ /*IsAssignmentOperator=*/false,
+ /*NumContextualBoolArguments=*/1);
+ }
+ void addAmpAmpOrPipePipeOverload() {
+ QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, CandidateSet,
+ /*IsAssignmentOperator=*/false,
+ /*NumContextualBoolArguments=*/2);
+ }
+
+ // C++ [over.built]p13:
+ //
+ // For every cv-qualified or cv-unqualified object type T there
+ // exist candidate operator functions of the form
+ //
+ // T* operator+(T*, ptrdiff_t); [ABOVE]
+ // T& operator[](T*, ptrdiff_t);
+ // T* operator-(T*, ptrdiff_t); [ABOVE]
+ // T* operator+(ptrdiff_t, T*); [ABOVE]
+ // T& operator[](ptrdiff_t, T*);
+ void addSubscriptOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() };
QualType PointeeType = (*Ptr)->getPointeeType();
- QualType ResultTy = Context.getLValueReferenceType(PointeeType);
+ if (!PointeeType->isObjectType())
+ continue;
+
+ QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
// T& operator[](T*, ptrdiff_t)
- AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+ S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+ }
- // T& operator[](ptrdiff_t, T*);
- ParamTypes[0] = ParamTypes[1];
- ParamTypes[1] = *Ptr;
- AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
- }
- break;
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[1].pointer_begin(),
+ PtrEnd = CandidateTypes[1].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr };
+ QualType PointeeType = (*Ptr)->getPointeeType();
+ if (!PointeeType->isObjectType())
+ continue;
- case OO_ArrowStar:
- // C++ [over.built]p11:
- // For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type,
- // C1 is the same type as C2 or is a derived class of C2, T is an object
- // type or a function type, and CV1 and CV2 are cv-qualifier-seqs,
- // there exist candidate operator functions of the form
- // CV12 T& operator->*(CV1 C1*, CV2 T C2::*);
- // where CV12 is the union of CV1 and CV2.
- {
- for (BuiltinCandidateTypeSet::iterator Ptr =
- CandidateTypes.pointer_begin();
- Ptr != CandidateTypes.pointer_end(); ++Ptr) {
- QualType C1Ty = (*Ptr);
- QualType C1;
- QualifierCollector Q1;
- C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0);
- if (!isa<RecordType>(C1))
+ QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
+
+ // T& operator[](ptrdiff_t, T*)
+ S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+ }
+ }
+
+ // C++ [over.built]p11:
+ // For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type,
+ // C1 is the same type as C2 or is a derived class of C2, T is an object
+ // type or a function type, and CV1 and CV2 are cv-qualifier-seqs,
+ // there exist candidate operator functions of the form
+ //
+ // CV12 T& operator->*(CV1 C1*, CV2 T C2::*);
+ //
+ // where CV12 is the union of CV1 and CV2.
+ void addArrowStarOverloads() {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[0].pointer_begin(),
+ PtrEnd = CandidateTypes[0].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ QualType C1Ty = (*Ptr);
+ QualType C1;
+ QualifierCollector Q1;
+ C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0);
+ if (!isa<RecordType>(C1))
+ continue;
+ // heuristic to reduce number of builtin candidates in the set.
+ // Add volatile/restrict version only if there are conversions to a
+ // volatile/restrict type.
+ if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
+ continue;
+ if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
+ continue;
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes[1].member_pointer_begin(),
+ MemPtrEnd = CandidateTypes[1].member_pointer_end();
+ MemPtr != MemPtrEnd; ++MemPtr) {
+ const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
+ QualType C2 = QualType(mptr->getClass(), 0);
+ C2 = C2.getUnqualifiedType();
+ if (C1 != C2 && !S.IsDerivedFrom(C1, C2))
+ break;
+ QualType ParamTypes[2] = { *Ptr, *MemPtr };
+ // build CV12 T&
+ QualType T = mptr->getPointeeType();
+ if (!VisibleTypeConversionsQuals.hasVolatile() &&
+ T.isVolatileQualified())
+ continue;
+ if (!VisibleTypeConversionsQuals.hasRestrict() &&
+ T.isRestrictQualified())
continue;
- // heuristic to reduce number of builtin candidates in the set.
- // Add volatile/restrict version only if there are conversions to a
- // volatile/restrict type.
- if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
+ T = Q1.apply(S.Context, T);
+ QualType ResultTy = S.Context.getLValueReferenceType(T);
+ S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+ }
+ }
+ }
+
+ // Note that we don't consider the first argument, since it has been
+ // contextually converted to bool long ago. The candidates below are
+ // therefore added as binary.
+ //
+ // C++ [over.built]p25:
+ // For every type T, where T is a pointer, pointer-to-member, or scoped
+ // enumeration type, there exist candidate operator functions of the form
+ //
+ // T operator?(bool, T, T);
+ //
+ void addConditionalOperatorOverloads() {
+ /// Set of (canonical) types that we've already handled.
+ llvm::SmallPtrSet<QualType, 8> AddedTypes;
+
+ for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
+ for (BuiltinCandidateTypeSet::iterator
+ Ptr = CandidateTypes[ArgIdx].pointer_begin(),
+ PtrEnd = CandidateTypes[ArgIdx].pointer_end();
+ Ptr != PtrEnd; ++Ptr) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
continue;
- if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
+
+ QualType ParamTypes[2] = { *Ptr, *Ptr };
+ S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+ }
+
+ for (BuiltinCandidateTypeSet::iterator
+ MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+ MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+ MemPtr != MemPtrEnd; ++MemPtr) {
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
continue;
+
+ QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+ S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet);
+ }
+
+ if (S.getLangOptions().CPlusPlus0x) {
for (BuiltinCandidateTypeSet::iterator
- MemPtr = CandidateTypes.member_pointer_begin(),
- MemPtrEnd = CandidateTypes.member_pointer_end();
- MemPtr != MemPtrEnd; ++MemPtr) {
- const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
- QualType C2 = QualType(mptr->getClass(), 0);
- C2 = C2.getUnqualifiedType();
- if (C1 != C2 && !IsDerivedFrom(C1, C2))
- break;
- QualType ParamTypes[2] = { *Ptr, *MemPtr };
- // build CV12 T&
- QualType T = mptr->getPointeeType();
- if (!VisibleTypeConversionsQuals.hasVolatile() &&
- T.isVolatileQualified())
+ Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+ EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+ Enum != EnumEnd; ++Enum) {
+ if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped())
continue;
- if (!VisibleTypeConversionsQuals.hasRestrict() &&
- T.isRestrictQualified())
+
+ if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
continue;
- T = Q1.apply(T);
- QualType ResultTy = Context.getLValueReferenceType(T);
- AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
+
+ QualType ParamTypes[2] = { *Enum, *Enum };
+ S.AddBuiltinCandidate(*Enum, ParamTypes, Args, 2, CandidateSet);
}
}
}
+ }
+};
+
+} // end anonymous namespace
+
+/// AddBuiltinOperatorCandidates - Add the appropriate built-in
+/// operator overloads to the candidate set (C++ [over.built]), based
+/// on the operator @p Op and the arguments given. For example, if the
+/// operator is a binary '+', this routine might add "int
+/// operator+(int, int)" to cover integer addition.
+void
+Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet) {
+ // Find all of the types that the arguments can convert to, but only
+ // if the operator we're looking at has built-in operator candidates
+ // that make use of these types. Also record whether we encounter non-record
+ // candidate types or either arithmetic or enumeral candidate types.
+ Qualifiers VisibleTypeConversionsQuals;
+ VisibleTypeConversionsQuals.addConst();
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
+ VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
+
+ bool HasNonRecordCandidateType = false;
+ bool HasArithmeticOrEnumeralCandidateType = false;
+ llvm::SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes;
+ for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+ CandidateTypes.push_back(BuiltinCandidateTypeSet(*this));
+ CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(),
+ OpLoc,
+ true,
+ (Op == OO_Exclaim ||
+ Op == OO_AmpAmp ||
+ Op == OO_PipePipe),
+ VisibleTypeConversionsQuals);
+ HasNonRecordCandidateType = HasNonRecordCandidateType ||
+ CandidateTypes[ArgIdx].hasNonRecordTypes();
+ HasArithmeticOrEnumeralCandidateType =
+ HasArithmeticOrEnumeralCandidateType ||
+ CandidateTypes[ArgIdx].hasArithmeticOrEnumeralTypes();
+ }
+
+ // Exit early when no non-record types have been added to the candidate set
+ // for any of the arguments to the operator.
+ if (!HasNonRecordCandidateType)
+ return;
+
+ // Setup an object to manage the common state for building overloads.
+ BuiltinOperatorOverloadBuilder OpBuilder(*this, Args, NumArgs,
+ VisibleTypeConversionsQuals,
+ HasArithmeticOrEnumeralCandidateType,
+ CandidateTypes, CandidateSet);
+
+ // Dispatch over the operation to add in only those overloads which apply.
+ switch (Op) {
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ assert(false && "Expected an overloaded operator");
break;
- case OO_Conditional:
- // Note that we don't consider the first argument, since it has been
- // contextually converted to bool long ago. The candidates below are
- // therefore added as binary.
- //
- // C++ [over.built]p24:
- // For every type T, where T is a pointer or pointer-to-member type,
- // there exist candidate operator functions of the form
- //
- // T operator?(bool, T, T);
- //
- for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(),
- E = CandidateTypes.pointer_end(); Ptr != E; ++Ptr) {
- QualType ParamTypes[2] = { *Ptr, *Ptr };
- AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
- }
- for (BuiltinCandidateTypeSet::iterator Ptr =
- CandidateTypes.member_pointer_begin(),
- E = CandidateTypes.member_pointer_end(); Ptr != E; ++Ptr) {
- QualType ParamTypes[2] = { *Ptr, *Ptr };
- AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+ case OO_New:
+ case OO_Delete:
+ case OO_Array_New:
+ case OO_Array_Delete:
+ case OO_Call:
+ assert(false && "Special operators don't use AddBuiltinOperatorCandidates");
+ break;
+
+ case OO_Comma:
+ case OO_Arrow:
+ // C++ [over.match.oper]p3:
+ // -- For the operator ',', the unary operator '&', or the
+ // operator '->', the built-in candidates set is empty.
+ break;
+
+ case OO_Plus: // '+' is either unary or binary
+ if (NumArgs == 1)
+ OpBuilder.addUnaryPlusPointerOverloads();
+ // Fall through.
+
+ case OO_Minus: // '-' is either unary or binary
+ if (NumArgs == 1) {
+ OpBuilder.addUnaryPlusOrMinusArithmeticOverloads();
+ } else {
+ OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op);
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
}
- goto Conditional;
+ break;
+
+ case OO_Star: // '*' is either unary or binary
+ if (NumArgs == 1)
+ OpBuilder.addUnaryStarPointerOverloads();
+ else
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+ break;
+
+ case OO_Slash:
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+ break;
+
+ case OO_PlusPlus:
+ case OO_MinusMinus:
+ OpBuilder.addPlusPlusMinusMinusArithmeticOverloads(Op);
+ OpBuilder.addPlusPlusMinusMinusPointerOverloads();
+ break;
+
+ case OO_EqualEqual:
+ case OO_ExclaimEqual:
+ OpBuilder.addEqualEqualOrNotEqualMemberPointerOverloads();
+ // Fall through.
+
+ case OO_Less:
+ case OO_Greater:
+ case OO_LessEqual:
+ case OO_GreaterEqual:
+ OpBuilder.addRelationalPointerOrEnumeralOverloads();
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true);
+ break;
+
+ case OO_Percent:
+ case OO_Caret:
+ case OO_Pipe:
+ case OO_LessLess:
+ case OO_GreaterGreater:
+ OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+ break;
+
+ case OO_Amp: // '&' is either unary or binary
+ if (NumArgs == 1)
+ // C++ [over.match.oper]p3:
+ // -- For the operator ',', the unary operator '&', or the
+ // operator '->', the built-in candidates set is empty.
+ break;
+
+ OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
+ break;
+
+ case OO_Tilde:
+ OpBuilder.addUnaryTildePromotedIntegralOverloads();
+ break;
+
+ case OO_Equal:
+ OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads();
+ // Fall through.
+
+ case OO_PlusEqual:
+ case OO_MinusEqual:
+ OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal);
+ // Fall through.
+
+ case OO_StarEqual:
+ case OO_SlashEqual:
+ OpBuilder.addAssignmentArithmeticOverloads(Op == OO_Equal);
+ break;
+
+ case OO_PercentEqual:
+ case OO_LessLessEqual:
+ case OO_GreaterGreaterEqual:
+ case OO_AmpEqual:
+ case OO_CaretEqual:
+ case OO_PipeEqual:
+ OpBuilder.addAssignmentIntegralOverloads();
+ break;
+
+ case OO_Exclaim:
+ OpBuilder.addExclaimOverload();
+ break;
+
+ case OO_AmpAmp:
+ case OO_PipePipe:
+ OpBuilder.addAmpAmpOrPipePipeOverload();
+ break;
+
+ case OO_Subscript:
+ OpBuilder.addSubscriptOverloads();
+ break;
+
+ case OO_ArrowStar:
+ OpBuilder.addArrowStarOverloads();
+ break;
+
+ case OO_Conditional:
+ OpBuilder.addConditionalOperatorOverloads();
+ OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false);
+ break;
}
}
@@ -5270,7 +6116,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
if (ExplicitTemplateArgs)
continue;
-
+
AddOverloadCandidate(FD, FoundDecl, Args, NumArgs, CandidateSet,
false, PartialOverloading);
} else
@@ -5284,9 +6130,10 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool
isBetterOverloadCandidate(Sema &S,
- const OverloadCandidate& Cand1,
- const OverloadCandidate& Cand2,
- SourceLocation Loc) {
+ const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2,
+ SourceLocation Loc,
+ bool UserDefinedConversion) {
// Define viable functions to be better candidates than non-viable
// functions.
if (!Cand2.Viable)
@@ -5346,14 +6193,16 @@ isBetterOverloadCandidate(Sema &S,
// according to the partial ordering rules described in 14.5.5.2, or,
// if not that,
if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
- Cand2.Function && Cand2.Function->getPrimaryTemplate())
+ Cand2.Function && Cand2.Function->getPrimaryTemplate()) {
if (FunctionTemplateDecl *BetterTemplate
= S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
Cand2.Function->getPrimaryTemplate(),
Loc,
- isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
- : TPOC_Call))
+ isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
+ : TPOC_Call,
+ Cand1.ExplicitCallArguments))
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
+ }
// -- the context is an initialization by user-defined conversion
// (see 8.5, 13.3.1.5) and the standard conversion sequence
@@ -5361,7 +6210,7 @@ isBetterOverloadCandidate(Sema &S,
// the type of the entity being initialized) is a better
// conversion sequence than the standard conversion sequence
// from the return type of F2 to the destination type.
- if (Cand1.Function && Cand2.Function &&
+ if (UserDefinedConversion && Cand1.Function && Cand2.Function &&
isa<CXXConversionDecl>(Cand1.Function) &&
isa<CXXConversionDecl>(Cand2.Function)) {
switch (CompareStandardConversionSequences(S,
@@ -5398,12 +6247,14 @@ isBetterOverloadCandidate(Sema &S,
/// \returns The result of overload resolution.
OverloadingResult
OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
- iterator& Best) {
+ iterator &Best,
+ bool UserDefinedConversion) {
// Find the best viable function.
Best = end();
for (iterator Cand = begin(); Cand != end(); ++Cand) {
if (Cand->Viable)
- if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc))
+ if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc,
+ UserDefinedConversion))
Best = Cand;
}
@@ -5416,7 +6267,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
for (iterator Cand = begin(); Cand != end(); ++Cand) {
if (Cand->Viable &&
Cand != Best &&
- !isBetterOverloadCandidate(S, *Best, *Cand, Loc)) {
+ !isBetterOverloadCandidate(S, *Best, *Cand, Loc,
+ UserDefinedConversion)) {
Best = end();
return OR_Ambiguous;
}
@@ -5436,6 +6288,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// placement new (5.3.4), as well as non-default initialization (8.5).
if (Best->Function)
S.MarkDeclarationReferenced(Loc, Best->Function);
+
return OR_Success;
}
@@ -5450,7 +6303,8 @@ enum OverloadCandidateKind {
oc_constructor_template,
oc_implicit_default_constructor,
oc_implicit_copy_constructor,
- oc_implicit_copy_assignment
+ oc_implicit_copy_assignment,
+ oc_implicit_inherited_constructor
};
OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
@@ -5468,6 +6322,9 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
if (!Ctor->isImplicit())
return isTemplate ? oc_constructor_template : oc_constructor;
+ if (Ctor->getInheritedConstructor())
+ return oc_implicit_inherited_constructor;
+
return Ctor->isCopyConstructor() ? oc_implicit_copy_constructor
: oc_implicit_default_constructor;
}
@@ -5478,7 +6335,7 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
if (!Meth->isImplicit())
return isTemplate ? oc_method_template : oc_method;
- assert(Meth->isCopyAssignment()
+ assert(Meth->isCopyAssignmentOperator()
&& "implicit method is not copy assignment operator?");
return oc_implicit_copy_assignment;
}
@@ -5486,6 +6343,16 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
return isTemplate ? oc_function_template : oc_function;
}
+void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) {
+ const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
+ if (!Ctor) return;
+
+ Ctor = Ctor->getInheritedConstructor();
+ if (!Ctor) return;
+
+ S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_inherited_constructor);
+}
+
} // end anonymous namespace
// Notes the location of an overload candidate.
@@ -5494,6 +6361,28 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
Diag(Fn->getLocation(), diag::note_ovl_candidate)
<< (unsigned) K << FnDesc;
+ MaybeEmitInheritedConstructorNote(*this, Fn);
+}
+
+//Notes the location of all overload candidates designated through
+// OverloadedExpr
+void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr) {
+ assert(OverloadedExpr->getType() == Context.OverloadTy);
+
+ OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr);
+ OverloadExpr *OvlExpr = Ovl.Expression;
+
+ for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+ IEnd = OvlExpr->decls_end();
+ I != IEnd; ++I) {
+ if (FunctionTemplateDecl *FunTmpl =
+ dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) {
+ NoteOverloadCandidate(FunTmpl->getTemplatedDecl());
+ } else if (FunctionDecl *Fun
+ = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
+ NoteOverloadCandidate(Fun);
+ }
+ }
}
/// Diagnoses an ambiguous conversion. The partial diagnostic is the
@@ -5548,6 +6437,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< ToTy << Name << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
@@ -5582,6 +6472,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
<< FromTy
<< FromQs.getAddressSpace() << ToQs.getAddressSpace()
<< (unsigned) isObjectArgument << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
@@ -5599,6 +6490,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << (CVR - 1) << I+1;
}
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
@@ -5613,6 +6505,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
@@ -5624,7 +6517,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
FromPtrTy->getPointeeType()) &&
!FromPtrTy->getPointeeType()->isIncompleteType() &&
!ToPtrTy->getPointeeType()->isIncompleteType() &&
- S.IsDerivedFrom(ToPtrTy->getPointeeType(),
+ S.IsDerivedFrom(ToPtrTy->getPointeeType(),
FromPtrTy->getPointeeType()))
BaseToDerivedConversion = 1;
}
@@ -5645,22 +6538,24 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy))
BaseToDerivedConversion = 3;
}
-
+
if (BaseToDerivedConversion) {
- S.Diag(Fn->getLocation(),
+ S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_bad_base_to_derived_conv)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< (BaseToDerivedConversion - 1)
- << FromTy << ToTy << I+1;
+ << FromTy << ToTy << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
-
+
// TODO: specialize more based on the kind of mismatch
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << ToTy << (unsigned) isObjectArgument << I+1;
+ MaybeEmitInheritedConstructorNote(S, Fn);
}
void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
@@ -5671,15 +6566,15 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
unsigned MinParams = Fn->getMinRequiredArguments();
-
+
// at least / at most / exactly
- // FIXME: variadic templates "at most" should account for parameter packs
unsigned mode, modeCount;
if (NumFormalArgs < MinParams) {
assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
(Cand->FailureKind == ovl_fail_bad_deduction &&
Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
- if (MinParams != FnTy->getNumArgs() || FnTy->isVariadic())
+ if (MinParams != FnTy->getNumArgs() ||
+ FnTy->isVariadic() || FnTy->isTemplateVariadic())
mode = 0; // "at least"
else
mode = 2; // "exactly"
@@ -5699,8 +6594,9 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
- << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
+ << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
<< modeCount << NumFormalArgs;
+ MaybeEmitInheritedConstructorNote(S, Fn);
}
/// Diagnose a failed template-argument deduction.
@@ -5721,6 +6617,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
assert(ParamD && "no parameter found for incomplete deduction result");
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
<< ParamD->getDeclName();
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
@@ -5732,9 +6629,9 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
// Param will have been canonicalized, but it should just be a
// qualified version of ParamD, so move the qualifiers to that.
- QualifierCollector Qs(S.Context);
+ QualifierCollector Qs;
Qs.strip(Param);
- QualType NonCanonParam = Qs.apply(TParam->getTypeForDecl());
+ QualType NonCanonParam = Qs.apply(S.Context, TParam->getTypeForDecl());
assert(S.Context.hasSameType(Param, NonCanonParam));
// Arg has also been canonicalized, but there's nothing we can do
@@ -5745,11 +6642,12 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified)
<< ParamD->getDeclName() << Arg << NonCanonParam;
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
case Sema::TDK_Inconsistent: {
- assert(ParamD && "no parameter found for inconsistent deduction result");
+ assert(ParamD && "no parameter found for inconsistent deduction result");
int which = 0;
if (isa<TemplateTypeParmDecl>(ParamD))
which = 0;
@@ -5758,18 +6656,19 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
else {
which = 2;
}
-
+
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction)
- << which << ParamD->getDeclName()
+ << which << ParamD->getDeclName()
<< *Cand->DeductionFailure.getFirstArg()
<< *Cand->DeductionFailure.getSecondArg();
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
case Sema::TDK_InvalidExplicitArguments:
- assert(ParamD && "no parameter found for invalid explicit arguments");
+ assert(ParamD && "no parameter found for invalid explicit arguments");
if (ParamD->getDeclName())
- S.Diag(Fn->getLocation(),
+ S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_named)
<< ParamD->getDeclName();
else {
@@ -5781,12 +6680,13 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
index = NTTP->getIndex();
else
index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
- S.Diag(Fn->getLocation(),
+ S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
<< (index + 1);
}
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
-
+
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
DiagnoseArityMismatch(S, Cand, NumArgs);
@@ -5794,6 +6694,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
case Sema::TDK_InstantiationDepth:
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
case Sema::TDK_SubstitutionFailure: {
@@ -5805,14 +6706,16 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
*Args);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
<< ArgString;
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
-
+
// TODO: diagnose these individually, then kill off
// note_ovl_candidate_bad_deduction, which is uselessly vague.
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
}
@@ -5841,6 +6744,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
<< FnKind << FnDesc << Fn->isDeleted();
+ MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
@@ -5868,7 +6772,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
for (unsigned N = Cand->Conversions.size(); I != N; ++I)
if (Cand->Conversions[I].isBad())
return DiagnoseBadConversion(S, Cand, I);
-
+
// FIXME: this currently happens when we're called from SemaInit
// when user-conversion overload fails. Figure out how to handle
// those conditions and diagnose them well.
@@ -5907,6 +6811,7 @@ void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
<< FnType;
+ MaybeEmitInheritedConstructorNote(S, Cand->Surrogate);
}
void NoteBuiltinOperatorCandidate(Sema &S,
@@ -6083,7 +6988,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
Cand->Conversions[ConvIdx]
= TryCopyInitialization(S, Args[ConvIdx],
Cand->BuiltinTypes.ParamTypes[ConvIdx],
- SuppressUserConversions,
+ SuppressUserConversions,
/*InOverloadResolution*/ true);
return;
}
@@ -6094,7 +6999,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
if (ArgIdx < NumArgsInProto)
Cand->Conversions[ConvIdx]
= TryCopyInitialization(S, Args[ArgIdx], Proto->getArgType(ArgIdx),
- SuppressUserConversions,
+ SuppressUserConversions,
/*InOverloadResolution=*/true);
else
Cand->Conversions[ConvIdx].setEllipsis();
@@ -6129,7 +7034,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S,
std::sort(Cands.begin(), Cands.end(),
CompareOverloadCandidatesForDisplay(S));
-
+
bool ReportedAmbiguousConversions = false;
llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E;
@@ -6180,186 +7085,207 @@ static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D);
}
-/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
-/// an overloaded function (C++ [over.over]), where @p From is an
-/// expression with overloaded function type and @p ToType is the type
-/// we're trying to resolve to. For example:
-///
-/// @code
-/// int f(double);
-/// int f(int);
-///
-/// int (*pfd)(double) = f; // selects f(double)
-/// @endcode
-///
-/// This routine returns the resulting FunctionDecl if it could be
-/// resolved, and NULL otherwise. When @p Complain is true, this
-/// routine will emit diagnostics if there is an error.
-FunctionDecl *
-Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
- bool Complain,
- DeclAccessPair &FoundResult) {
- QualType FunctionType = ToType;
- bool IsMember = false;
- if (const PointerType *ToTypePtr = ToType->getAs<PointerType>())
- FunctionType = ToTypePtr->getPointeeType();
- else if (const ReferenceType *ToTypeRef = ToType->getAs<ReferenceType>())
- FunctionType = ToTypeRef->getPointeeType();
- else if (const MemberPointerType *MemTypePtr =
- ToType->getAs<MemberPointerType>()) {
- FunctionType = MemTypePtr->getPointeeType();
- IsMember = true;
- }
- // C++ [over.over]p1:
- // [...] [Note: any redundant set of parentheses surrounding the
- // overloaded function name is ignored (5.1). ]
- // C++ [over.over]p1:
- // [...] The overloaded function name can be preceded by the &
- // operator.
- // However, remember whether the expression has member-pointer form:
- // C++ [expr.unary.op]p4:
- // A pointer to member is only formed when an explicit & is used
- // and its operand is a qualified-id not enclosed in
- // parentheses.
- OverloadExpr::FindResult Ovl = OverloadExpr::find(From);
- OverloadExpr *OvlExpr = Ovl.Expression;
-
- // We expect a pointer or reference to function, or a function pointer.
- FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
- if (!FunctionType->isFunctionType()) {
- if (Complain)
- Diag(From->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
- << OvlExpr->getName() << ToType;
-
- return 0;
- }
- // If the overload expression doesn't have the form of a pointer to
- // member, don't try to convert it to a pointer-to-member type.
- if (IsMember && !Ovl.HasFormOfMemberPointer) {
- if (!Complain) return 0;
- // TODO: Should we condition this on whether any functions might
- // have matched, or is it more appropriate to do that in callers?
- // TODO: a fixit wouldn't hurt.
- Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
- << ToType << OvlExpr->getSourceRange();
- return 0;
- }
+// [PossiblyAFunctionType] --> [Return]
+// NonFunctionType --> NonFunctionType
+// R (A) --> R(A)
+// R (*)(A) --> R (A)
+// R (&)(A) --> R (A)
+// R (S::*)(A) --> R (A)
+QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) {
+ QualType Ret = PossiblyAFunctionType;
+ if (const PointerType *ToTypePtr =
+ PossiblyAFunctionType->getAs<PointerType>())
+ Ret = ToTypePtr->getPointeeType();
+ else if (const ReferenceType *ToTypeRef =
+ PossiblyAFunctionType->getAs<ReferenceType>())
+ Ret = ToTypeRef->getPointeeType();
+ else if (const MemberPointerType *MemTypePtr =
+ PossiblyAFunctionType->getAs<MemberPointerType>())
+ Ret = MemTypePtr->getPointeeType();
+ Ret =
+ Context.getCanonicalType(Ret).getUnqualifiedType();
+ return Ret;
+}
- TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
- if (OvlExpr->hasExplicitTemplateArgs()) {
- OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
- ExplicitTemplateArgs = &ETABuffer;
- }
+// A helper class to help with address of function resolution
+// - allows us to avoid passing around all those ugly parameters
+class AddressOfFunctionResolver
+{
+ Sema& S;
+ Expr* SourceExpr;
+ const QualType& TargetType;
+ QualType TargetFunctionType; // Extracted function type from target type
+
+ bool Complain;
+ //DeclAccessPair& ResultFunctionAccessPair;
+ ASTContext& Context;
- assert(From->getType() == Context.OverloadTy);
+ bool TargetTypeIsNonStaticMemberFunction;
+ bool FoundNonTemplateFunction;
- // Look through all of the overloaded functions, searching for one
- // whose type matches exactly.
+ OverloadExpr::FindResult OvlExprInfo;
+ OverloadExpr *OvlExpr;
+ TemplateArgumentListInfo OvlExplicitTemplateArgs;
llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
- llvm::SmallVector<FunctionDecl *, 4> NonMatches;
-
- bool FoundNonTemplateFunction = false;
- for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
- E = OvlExpr->decls_end(); I != E; ++I) {
- // Look through any using declarations to find the underlying function.
- NamedDecl *Fn = (*I)->getUnderlyingDecl();
-
- // C++ [over.over]p3:
- // Non-member functions and static member functions match
- // targets of type "pointer-to-function" or "reference-to-function."
- // Nonstatic member functions match targets of
- // type "pointer-to-member-function."
- // Note that according to DR 247, the containing class does not matter.
-
- if (FunctionTemplateDecl *FunctionTemplate
- = dyn_cast<FunctionTemplateDecl>(Fn)) {
- if (CXXMethodDecl *Method
- = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
- // Skip non-static function templates when converting to pointer, and
- // static when converting to member pointer.
- if (Method->isStatic() == IsMember)
- continue;
- } else if (IsMember)
- continue;
- // C++ [over.over]p2:
- // If the name is a function template, template argument deduction is
- // done (14.8.2.2), and if the argument deduction succeeds, the
- // resulting template argument list is used to generate a single
- // function template specialization, which is added to the set of
- // overloaded functions considered.
- // FIXME: We don't really want to build the specialization here, do we?
- FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
- if (TemplateDeductionResult Result
- = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
- FunctionType, Specialization, Info)) {
- // FIXME: make a note of the failed deduction for diagnostics.
- (void)Result;
- } else {
- // FIXME: If the match isn't exact, shouldn't we just drop this as
- // a candidate? Find a testcase before changing the code.
- assert(FunctionType
- == Context.getCanonicalType(Specialization->getType()));
- Matches.push_back(std::make_pair(I.getPair(),
- cast<FunctionDecl>(Specialization->getCanonicalDecl())));
+public:
+ AddressOfFunctionResolver(Sema &S, Expr* SourceExpr,
+ const QualType& TargetType, bool Complain)
+ : S(S), SourceExpr(SourceExpr), TargetType(TargetType),
+ Complain(Complain), Context(S.getASTContext()),
+ TargetTypeIsNonStaticMemberFunction(
+ !!TargetType->getAs<MemberPointerType>()),
+ FoundNonTemplateFunction(false),
+ OvlExprInfo(OverloadExpr::find(SourceExpr)),
+ OvlExpr(OvlExprInfo.Expression)
+ {
+ ExtractUnqualifiedFunctionTypeFromTargetType();
+
+ if (!TargetFunctionType->isFunctionType()) {
+ if (OvlExpr->hasExplicitTemplateArgs()) {
+ DeclAccessPair dap;
+ if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
+ OvlExpr, false, &dap) ) {
+ Matches.push_back(std::make_pair(dap,Fn));
+ }
+ }
+ return;
+ }
+
+ if (OvlExpr->hasExplicitTemplateArgs())
+ OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
+
+ if (FindAllFunctionsThatMatchTargetTypeExactly()) {
+ // C++ [over.over]p4:
+ // If more than one function is selected, [...]
+ if (Matches.size() > 1) {
+ if (FoundNonTemplateFunction)
+ EliminateAllTemplateMatches();
+ else
+ EliminateAllExceptMostSpecializedTemplate();
}
-
- continue;
}
+ }
+
+private:
+ bool isTargetTypeAFunction() const {
+ return TargetFunctionType->isFunctionType();
+ }
+
+ // [ToType] [Return]
+ // R (*)(A) --> R (A), IsNonStaticMemberFunction = false
+ // R (&)(A) --> R (A), IsNonStaticMemberFunction = false
+ // R (S::*)(A) --> R (A), IsNonStaticMemberFunction = true
+ void inline ExtractUnqualifiedFunctionTypeFromTargetType() {
+ TargetFunctionType = S.ExtractUnqualifiedFunctionType(TargetType);
+ }
+
+ // return true if any matching specializations were found
+ bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate,
+ const DeclAccessPair& CurAccessFunPair) {
+ if (CXXMethodDecl *Method
+ = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
+ // Skip non-static function templates when converting to pointer, and
+ // static when converting to member pointer.
+ if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
+ return false;
+ }
+ else if (TargetTypeIsNonStaticMemberFunction)
+ return false;
+
+ // C++ [over.over]p2:
+ // If the name is a function template, template argument deduction is
+ // done (14.8.2.2), and if the argument deduction succeeds, the
+ // resulting template argument list is used to generate a single
+ // function template specialization, which is added to the set of
+ // overloaded functions considered.
+ FunctionDecl *Specialization = 0;
+ TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+ if (Sema::TemplateDeductionResult Result
+ = S.DeduceTemplateArguments(FunctionTemplate,
+ &OvlExplicitTemplateArgs,
+ TargetFunctionType, Specialization,
+ Info)) {
+ // FIXME: make a note of the failed deduction for diagnostics.
+ (void)Result;
+ return false;
+ }
+
+ // Template argument deduction ensures that we have an exact match.
+ // This function template specicalization works.
+ Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
+ assert(TargetFunctionType
+ == Context.getCanonicalType(Specialization->getType()));
+ Matches.push_back(std::make_pair(CurAccessFunPair, Specialization));
+ return true;
+ }
+
+ bool AddMatchingNonTemplateFunction(NamedDecl* Fn,
+ const DeclAccessPair& CurAccessFunPair) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
// Skip non-static functions when converting to pointer, and static
// when converting to member pointer.
- if (Method->isStatic() == IsMember)
- continue;
-
- // If we have explicit template arguments, skip non-templates.
- if (OvlExpr->hasExplicitTemplateArgs())
- continue;
- } else if (IsMember)
- continue;
+ if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
+ return false;
+ }
+ else if (TargetTypeIsNonStaticMemberFunction)
+ return false;
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
QualType ResultTy;
- if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
- IsNoReturnConversion(Context, FunDecl->getType(), FunctionType,
+ if (Context.hasSameUnqualifiedType(TargetFunctionType,
+ FunDecl->getType()) ||
+ IsNoReturnConversion(Context, FunDecl->getType(), TargetFunctionType,
ResultTy)) {
- Matches.push_back(std::make_pair(I.getPair(),
- cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
+ Matches.push_back(std::make_pair(CurAccessFunPair,
+ cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
FoundNonTemplateFunction = true;
+ return true;
}
}
+
+ return false;
}
+
+ bool FindAllFunctionsThatMatchTargetTypeExactly() {
+ bool Ret = false;
+
+ // If the overload expression doesn't have the form of a pointer to
+ // member, don't try to convert it to a pointer-to-member type.
+ if (IsInvalidFormOfPointerToMemberFunction())
+ return false;
- // If there were 0 or 1 matches, we're done.
- if (Matches.empty()) {
- if (Complain) {
- Diag(From->getLocStart(), diag::err_addr_ovl_no_viable)
- << OvlExpr->getName() << FunctionType;
- for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
- E = OvlExpr->decls_end();
- I != E; ++I)
- if (FunctionDecl *F = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
- NoteOverloadCandidate(F);
+ for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+ E = OvlExpr->decls_end();
+ I != E; ++I) {
+ // Look through any using declarations to find the underlying function.
+ NamedDecl *Fn = (*I)->getUnderlyingDecl();
+
+ // C++ [over.over]p3:
+ // Non-member functions and static member functions match
+ // targets of type "pointer-to-function" or "reference-to-function."
+ // Nonstatic member functions match targets of
+ // type "pointer-to-member-function."
+ // Note that according to DR 247, the containing class does not matter.
+ if (FunctionTemplateDecl *FunctionTemplate
+ = dyn_cast<FunctionTemplateDecl>(Fn)) {
+ if (AddMatchingTemplateFunction(FunctionTemplate, I.getPair()))
+ Ret = true;
+ }
+ // If we have explicit template arguments supplied, skip non-templates.
+ else if (!OvlExpr->hasExplicitTemplateArgs() &&
+ AddMatchingNonTemplateFunction(Fn, I.getPair()))
+ Ret = true;
}
-
- return 0;
- } else if (Matches.size() == 1) {
- FunctionDecl *Result = Matches[0].second;
- FoundResult = Matches[0].first;
- MarkDeclarationReferenced(From->getLocStart(), Result);
- if (Complain)
- CheckAddressOfMemberAccess(OvlExpr, Matches[0].first);
- return Result;
+ assert(Ret || Matches.empty());
+ return Ret;
}
- // C++ [over.over]p4:
- // If more than one function is selected, [...]
- if (!FoundNonTemplateFunction) {
+ void EliminateAllExceptMostSpecializedTemplate() {
// [...] and any given function template specialization F1 is
// eliminated if the set contains a second function template
// specialization whose function template is more specialized
@@ -6374,84 +7300,159 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
UnresolvedSet<4> MatchesCopy; // TODO: avoid!
for (unsigned I = 0, E = Matches.size(); I != E; ++I)
MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
-
+
UnresolvedSetIterator Result =
- getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
- TPOC_Other, From->getLocStart(),
- PDiag(),
- PDiag(diag::err_addr_ovl_ambiguous)
- << Matches[0].second->getDeclName(),
- PDiag(diag::note_ovl_candidate)
- << (unsigned) oc_function_template);
- assert(Result != MatchesCopy.end() && "no most-specialized template");
- MarkDeclarationReferenced(From->getLocStart(), *Result);
- FoundResult = Matches[Result - MatchesCopy.begin()].first;
- if (Complain) {
- CheckUnresolvedAccess(*this, OvlExpr, FoundResult);
- DiagnoseUseOfDecl(FoundResult, OvlExpr->getNameLoc());
- }
- return cast<FunctionDecl>(*Result);
- }
-
- // [...] any function template specializations in the set are
- // eliminated if the set also contains a non-template function, [...]
- for (unsigned I = 0, N = Matches.size(); I != N; ) {
- if (Matches[I].second->getPrimaryTemplate() == 0)
- ++I;
- else {
- Matches[I] = Matches[--N];
- Matches.set_size(N);
+ S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
+ TPOC_Other, 0, SourceExpr->getLocStart(),
+ S.PDiag(),
+ S.PDiag(diag::err_addr_ovl_ambiguous)
+ << Matches[0].second->getDeclName(),
+ S.PDiag(diag::note_ovl_candidate)
+ << (unsigned) oc_function_template,
+ Complain);
+
+ if (Result != MatchesCopy.end()) {
+ // Make it the first and only element
+ Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
+ Matches[0].second = cast<FunctionDecl>(*Result);
+ Matches.resize(1);
+ }
+ }
+
+ void EliminateAllTemplateMatches() {
+ // [...] any function template specializations in the set are
+ // eliminated if the set also contains a non-template function, [...]
+ for (unsigned I = 0, N = Matches.size(); I != N; ) {
+ if (Matches[I].second->getPrimaryTemplate() == 0)
+ ++I;
+ else {
+ Matches[I] = Matches[--N];
+ Matches.set_size(N);
+ }
}
}
+
+public:
+ void ComplainNoMatchesFound() const {
+ assert(Matches.empty());
+ S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
+ << OvlExpr->getName() << TargetFunctionType
+ << OvlExpr->getSourceRange();
+ S.NoteAllOverloadCandidates(OvlExpr);
+ }
- // [...] After such eliminations, if any, there shall remain exactly one
- // selected function.
- if (Matches.size() == 1) {
- MarkDeclarationReferenced(From->getLocStart(), Matches[0].second);
- FoundResult = Matches[0].first;
- if (Complain) {
- CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
- DiagnoseUseOfDecl(Matches[0].first, OvlExpr->getNameLoc());
- }
- return cast<FunctionDecl>(Matches[0].second);
- }
-
- // FIXME: We should probably return the same thing that BestViableFunction
- // returns (even if we issue the diagnostics here).
- Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
- << Matches[0].second->getDeclName();
- for (unsigned I = 0, E = Matches.size(); I != E; ++I)
- NoteOverloadCandidate(Matches[I].second);
- return 0;
+ bool IsInvalidFormOfPointerToMemberFunction() const {
+ return TargetTypeIsNonStaticMemberFunction &&
+ !OvlExprInfo.HasFormOfMemberPointer;
+ }
+
+ void ComplainIsInvalidFormOfPointerToMemberFunction() const {
+ // TODO: Should we condition this on whether any functions might
+ // have matched, or is it more appropriate to do that in callers?
+ // TODO: a fixit wouldn't hurt.
+ S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
+ << TargetType << OvlExpr->getSourceRange();
+ }
+
+ void ComplainOfInvalidConversion() const {
+ S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
+ << OvlExpr->getName() << TargetType;
+ }
+
+ void ComplainMultipleMatchesFound() const {
+ assert(Matches.size() > 1);
+ S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous)
+ << OvlExpr->getName()
+ << OvlExpr->getSourceRange();
+ S.NoteAllOverloadCandidates(OvlExpr);
+ }
+
+ int getNumMatches() const { return Matches.size(); }
+
+ FunctionDecl* getMatchingFunctionDecl() const {
+ if (Matches.size() != 1) return 0;
+ return Matches[0].second;
+ }
+
+ const DeclAccessPair* getMatchingFunctionAccessPair() const {
+ if (Matches.size() != 1) return 0;
+ return &Matches[0].first;
+ }
+};
+
+/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
+/// an overloaded function (C++ [over.over]), where @p From is an
+/// expression with overloaded function type and @p ToType is the type
+/// we're trying to resolve to. For example:
+///
+/// @code
+/// int f(double);
+/// int f(int);
+///
+/// int (*pfd)(double) = f; // selects f(double)
+/// @endcode
+///
+/// This routine returns the resulting FunctionDecl if it could be
+/// resolved, and NULL otherwise. When @p Complain is true, this
+/// routine will emit diagnostics if there is an error.
+FunctionDecl *
+Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
+ bool Complain,
+ DeclAccessPair &FoundResult) {
+
+ assert(AddressOfExpr->getType() == Context.OverloadTy);
+
+ AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType, Complain);
+ int NumMatches = Resolver.getNumMatches();
+ FunctionDecl* Fn = 0;
+ if ( NumMatches == 0 && Complain) {
+ if (Resolver.IsInvalidFormOfPointerToMemberFunction())
+ Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
+ else
+ Resolver.ComplainNoMatchesFound();
+ }
+ else if (NumMatches > 1 && Complain)
+ Resolver.ComplainMultipleMatchesFound();
+ else if (NumMatches == 1) {
+ Fn = Resolver.getMatchingFunctionDecl();
+ assert(Fn);
+ FoundResult = *Resolver.getMatchingFunctionAccessPair();
+ MarkDeclarationReferenced(AddressOfExpr->getLocStart(), Fn);
+ if (Complain)
+ CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
+ }
+
+ return Fn;
}
-/// \brief Given an expression that refers to an overloaded function, try to
+/// \brief Given an expression that refers to an overloaded function, try to
/// resolve that overloaded function expression down to a single function.
///
/// This routine can only resolve template-ids that refer to a single function
/// template, where that template-id refers to a single template whose template
-/// arguments are either provided by the template-id or have defaults,
+/// arguments are either provided by the template-id or have defaults,
/// as described in C++0x [temp.arg.explicit]p3.
-FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
+FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
+ bool Complain,
+ DeclAccessPair* FoundResult) {
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
-
if (From->getType() != Context.OverloadTy)
return 0;
OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression;
-
+
// If we didn't actually find any template-ids, we're done.
if (!OvlExpr->hasExplicitTemplateArgs())
return 0;
TemplateArgumentListInfo ExplicitTemplateArgs;
OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
-
+
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
FunctionDecl *Matched = 0;
@@ -6459,13 +7460,13 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
E = OvlExpr->decls_end(); I != E; ++I) {
// C++0x [temp.arg.explicit]p3:
// [...] In contexts where deduction is done and fails, or in contexts
- // where deduction is not done, if a template argument list is
- // specified and it, along with any default template arguments,
- // identifies a single function template specialization, then the
+ // where deduction is not done, if a template argument list is
+ // specified and it, along with any default template arguments,
+ // identifies a single function template specialization, then the
// template-id is an lvalue for the function template specialization.
FunctionTemplateDecl *FunctionTemplate
= cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl());
-
+
// C++ [over.over]p2:
// If the name is a function template, template argument deduction is
// done (14.8.2.2), and if the argument deduction succeeds, the
@@ -6480,18 +7481,28 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
// FIXME: make a note of the failed deduction for diagnostics.
(void)Result;
continue;
- }
-
+ }
+
// Multiple matches; we can't resolve to a single declaration.
- if (Matched)
+ if (Matched) {
+ if (FoundResult)
+ *FoundResult = DeclAccessPair();
+
+ if (Complain) {
+ Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
+ << OvlExpr->getName();
+ NoteAllOverloadCandidates(OvlExpr);
+ }
return 0;
-
- Matched = Specialization;
+ }
+
+ if ((Matched = Specialization) && FoundResult)
+ *FoundResult = I.getPair();
}
return Matched;
}
-
+
/// \brief Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
DeclAccessPair FoundDecl,
@@ -6522,7 +7533,7 @@ static void AddOverloadedCallCandidate(Sema &S,
// do nothing?
}
-
+
/// \brief Add the overload candidates named by callee and/or found by argument
/// dependent lookup to the given overload set.
void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
@@ -6570,7 +7581,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
E = ULE->decls_end(); I != E; ++I)
AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs,
- Args, NumArgs, CandidateSet,
+ Args, NumArgs, CandidateSet,
PartialOverloading);
if (ULE->requiresADL())
@@ -6578,7 +7589,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
Args, NumArgs,
ExplicitTemplateArgs,
CandidateSet,
- PartialOverloading);
+ PartialOverloading);
}
/// Attempts to recover from a call where no functions were found.
@@ -6589,7 +7600,6 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
CXXScopeSpec SS;
@@ -6616,7 +7626,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
// casts and such from the call, we don't really care.
ExprResult NewFn = ExprError();
if ((*R.begin())->isCXXClassMember())
- NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, ExplicitTemplateArgs);
+ NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R,
+ ExplicitTemplateArgs);
else if (ExplicitTemplateArgs)
NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs);
else
@@ -6629,8 +7640,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
// an expression with non-empty lookup results, which should never
// end up here.
return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc,
- MultiExprArg(Args, NumArgs),
- CommaLocs, RParenLoc);
+ MultiExprArg(Args, NumArgs), RParenLoc);
}
/// ResolveOverloadedCallFn - Given the call expression that calls Fn
@@ -6644,8 +7654,8 @@ ExprResult
Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
+ SourceLocation RParenLoc,
+ Expr *ExecConfig) {
#ifndef NDEBUG
if (ULE->requiresADL()) {
// To do ADL, we must have found an unqualified name.
@@ -6658,7 +7668,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
(F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&
F->getBuiltinID() && F->isImplicit())
assert(0 && "performing ADL for builtin");
-
+
// We don't perform ADL in C.
assert(getLangOptions().CPlusPlus && "ADL enabled in C");
}
@@ -6675,16 +7685,18 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
// bailout out if it fails.
if (CandidateSet.empty())
return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs,
- CommaLocs, RParenLoc);
+ RParenLoc);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
- DiagnoseUseOfDecl(Best->FoundDecl, ULE->getNameLoc());
+ DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(),
+ ULE->getNameLoc());
Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
- return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
+ return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc,
+ ExecConfig);
}
case OR_No_Viable_Function:
@@ -6746,6 +7758,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// TODO: provide better source location info.
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
+ if (Input->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Input);
+
Expr *Args[2] = { Input, 0 };
unsigned NumArgs = 1;
@@ -6762,19 +7777,21 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
if (Input->isTypeDependent()) {
if (Fns.empty())
return Owned(new (Context) UnaryOperator(Input,
- Opc,
+ Opc,
Context.DependentTy,
+ VK_RValue, OK_Ordinary,
OpLoc));
-
+
CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
+ = UnresolvedLookupExpr::Create(Context, NamingClass,
0, SourceRange(), OpNameInfo,
/*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
&Args[0], NumArgs,
Context.DependentTy,
+ VK_RValue,
OpLoc));
}
@@ -6818,8 +7835,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// Convert the arguments.
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
FnDecl->getParamDecl(0)),
- SourceLocation(),
+ SourceLocation(),
Input);
if (InputInit.isInvalid())
return ExprError();
@@ -6828,20 +7846,20 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
- // Determine the result type
- QualType ResultTy = FnDecl->getCallResultType();
+ // Determine the result type.
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
// Build the actual expression node.
- Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
- SourceLocation());
- UsualUnaryConversions(FnExpr);
+ Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl);
Args[0] = Input;
CallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
- Args, NumArgs, ResultTy, OpLoc);
+ Args, NumArgs, ResultTy, VK, OpLoc);
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
+ if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
FnDecl))
return ExprError();
@@ -6864,8 +7882,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
break;
case OR_Ambiguous:
- Diag(OpLoc, diag::err_ovl_ambiguous_oper)
+ Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary)
<< UnaryOperator::getOpcodeStr(Opc)
+ << Input->getType()
<< Input->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
Args, NumArgs,
@@ -6920,14 +7939,18 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
if (Fns.empty()) {
- // If there are no functions to store, just build a dependent
+ // If there are no functions to store, just build a dependent
// BinaryOperator or CompoundAssignment.
if (Opc <= BO_Assign || Opc > BO_OrAssign)
return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
- Context.DependentTy, OpLoc));
-
+ Context.DependentTy,
+ VK_RValue, OK_Ordinary,
+ OpLoc));
+
return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
Context.DependentTy,
+ VK_LValue,
+ OK_Ordinary,
Context.DependentTy,
Context.DependentTy,
OpLoc));
@@ -6938,20 +7961,48 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// TODO: provide better source location info in DNLoc component.
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
- 0, SourceRange(), OpNameInfo,
- /*ADL*/ true, IsOverloaded(Fns),
+ = UnresolvedLookupExpr::Create(Context, NamingClass, 0, SourceRange(),
+ OpNameInfo, /*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
Args, 2,
Context.DependentTy,
+ VK_RValue,
OpLoc));
}
- // If this is the .* operator, which is not overloadable, just
- // create a built-in binary operator.
- if (Opc == BO_PtrMemD)
- return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+ // Always do property rvalue conversions on the RHS.
+ if (Args[1]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[1]);
+
+ // The LHS is more complicated.
+ if (Args[0]->getObjectKind() == OK_ObjCProperty) {
+
+ // There's a tension for assignment operators between primitive
+ // property assignment and the overloaded operators.
+ if (BinaryOperator::isAssignmentOp(Opc)) {
+ const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty();
+
+ // Is the property "logically" settable?
+ bool Settable = (PRE->isExplicitProperty() ||
+ PRE->getImplicitPropertySetter());
+
+ // To avoid gratuitously inventing semantics, use the primitive
+ // unless it isn't. Thoughts in case we ever really care:
+ // - If the property isn't logically settable, we have to
+ // load and hope.
+ // - If the property is settable and this is simple assignment,
+ // we really should use the primitive.
+ // - If the property is settable, then we could try overloading
+ // on a generic lvalue of the appropriate type; if it works
+ // out to a builtin candidate, we would do that same operation
+ // on the property, and otherwise just error.
+ if (Settable)
+ return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+ }
+
+ ConvertPropertyForRValue(Args[0]);
+ }
// If this is the assignment operator, we only perform overload resolution
// if the left-hand side is a class or enumeration type. This is actually
@@ -6962,6 +8013,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType())
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+ // If this is the .* operator, which is not overloadable, just
+ // create a built-in binary operator.
+ if (Opc == BO_PtrMemD)
+ return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
+
// Build an empty overload set.
OverloadCandidateSet CandidateSet(OpLoc);
@@ -6996,37 +8052,33 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Best->Access is only meaningful for class members.
CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl);
- ExprResult Arg1
- = PerformCopyInitialization(
- InitializedEntity::InitializeParameter(
- FnDecl->getParamDecl(0)),
- SourceLocation(),
- Owned(Args[1]));
+ ExprResult Arg1 =
+ PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(Context,
+ FnDecl->getParamDecl(0)),
+ SourceLocation(), Owned(Args[1]));
if (Arg1.isInvalid())
return ExprError();
- if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
Best->FoundDecl, Method))
return ExprError();
Args[1] = RHS = Arg1.takeAs<Expr>();
} else {
// Convert the arguments.
- ExprResult Arg0
- = PerformCopyInitialization(
- InitializedEntity::InitializeParameter(
- FnDecl->getParamDecl(0)),
- SourceLocation(),
- Owned(Args[0]));
+ ExprResult Arg0 = PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(Context,
+ FnDecl->getParamDecl(0)),
+ SourceLocation(), Owned(Args[0]));
if (Arg0.isInvalid())
return ExprError();
- ExprResult Arg1
- = PerformCopyInitialization(
- InitializedEntity::InitializeParameter(
- FnDecl->getParamDecl(1)),
- SourceLocation(),
- Owned(Args[1]));
+ ExprResult Arg1 =
+ PerformCopyInitialization(
+ InitializedEntity::InitializeParameter(Context,
+ FnDecl->getParamDecl(1)),
+ SourceLocation(), Owned(Args[1]));
if (Arg1.isInvalid())
return ExprError();
Args[0] = LHS = Arg0.takeAs<Expr>();
@@ -7035,21 +8087,19 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
- // Determine the result type
- QualType ResultTy
- = FnDecl->getType()->getAs<FunctionType>()
- ->getCallResultType(Context);
+ // Determine the result type.
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
// Build the actual expression node.
- Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
- OpLoc);
- UsualUnaryConversions(FnExpr);
+ Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc);
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
- Args, 2, ResultTy, OpLoc);
-
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
+ Args, 2, ResultTy, VK, OpLoc);
+
+ if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
FnDecl))
return ExprError();
@@ -7076,11 +8126,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_Comma)
break;
- // For class as left operand for assignment or compound assigment operator
- // do not fall through to handling in built-in, but report that no overloaded
- // assignment operator found
+ // For class as left operand for assignment or compound assigment
+ // operator do not fall through to handling in built-in, but report that
+ // no overloaded assignment operator found
ExprResult Result = ExprError();
- if (Args[0]->getType()->isRecordType() &&
+ if (Args[0]->getType()->isRecordType() &&
Opc >= BO_Assign && Opc <= BO_OrAssign) {
Diag(OpLoc, diag::err_ovl_no_viable_oper)
<< BinaryOperator::getOpcodeStr(Opc)
@@ -7090,7 +8140,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// produce an error. Then, show the non-viable candidates.
Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
- assert(Result.isInvalid() &&
+ assert(Result.isInvalid() &&
"C++ binary operator overloading is missing candidates!");
if (Result.isInvalid())
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
@@ -7099,8 +8149,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
}
case OR_Ambiguous:
- Diag(OpLoc, diag::err_ovl_ambiguous_oper)
+ Diag(OpLoc, diag::err_ovl_ambiguous_oper_binary)
<< BinaryOperator::getOpcodeStr(Opc)
+ << Args[0]->getType() << Args[1]->getType()
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2,
BinaryOperator::getOpcodeStr(Opc), OpLoc);
@@ -7136,7 +8187,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
DeclarationNameInfo OpNameInfo(OpName, LLoc);
OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
UnresolvedLookupExpr *Fn
- = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
+ = UnresolvedLookupExpr::Create(Context, NamingClass,
0, SourceRange(), OpNameInfo,
/*ADL*/ true, /*Overloaded*/ false,
UnresolvedSetIterator(),
@@ -7146,9 +8197,15 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
Args, 2,
Context.DependentTy,
+ VK_RValue,
RLoc));
}
+ if (Args[0]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[0]);
+ if (Args[1]->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Args[1]);
+
// Build an empty overload set.
OverloadCandidateSet CandidateSet(LLoc);
@@ -7176,15 +8233,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
- if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
+ if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
Best->FoundDecl, Method))
return ExprError();
// Convert the arguments.
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
FnDecl->getParamDecl(0)),
- SourceLocation(),
+ SourceLocation(),
Owned(Args[1]));
if (InputInit.isInvalid())
return ExprError();
@@ -7192,19 +8250,17 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
Args[1] = InputInit.takeAs<Expr>();
// Determine the result type
- QualType ResultTy
- = FnDecl->getType()->getAs<FunctionType>()
- ->getCallResultType(Context);
+ QualType ResultTy = FnDecl->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
// Build the actual expression node.
- Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
- LLoc);
- UsualUnaryConversions(FnExpr);
+ Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc);
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
FnExpr, Args, 2,
- ResultTy, RLoc);
+ ResultTy, VK, RLoc);
if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
FnDecl))
@@ -7240,8 +8296,10 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
}
case OR_Ambiguous:
- Diag(LLoc, diag::err_ovl_ambiguous_oper)
- << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ Diag(LLoc, diag::err_ovl_ambiguous_oper_binary)
+ << "[]"
+ << Args[0]->getType() << Args[1]->getType()
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2,
"[]", LLoc);
return ExprError();
@@ -7269,12 +8327,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
ExprResult
Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
SourceLocation LParenLoc, Expr **Args,
- unsigned NumArgs, SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
+ unsigned NumArgs, SourceLocation RParenLoc) {
// Dig out the member expression. This holds both the object
// argument and the member function we're referring to.
Expr *NakedMemExpr = MemExprE->IgnoreParens();
-
+
MemberExpr *MemExpr;
CXXMethodDecl *Method = 0;
DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
@@ -7287,8 +8344,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
} else {
UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
Qualifier = UnresExpr->getQualifier();
-
+
QualType ObjectType = UnresExpr->getBaseType();
+ Expr::Classification ObjectClassification
+ = UnresExpr->isArrow()? Expr::Classification::makeSimpleLValue()
+ : UnresExpr->getBase()->Classify(Context);
// Add overload candidates
OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc());
@@ -7308,20 +8368,26 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
if (isa<UsingShadowDecl>(Func))
Func = cast<UsingShadowDecl>(Func)->getTargetDecl();
- if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
+
+ // Microsoft supports direct constructor calls.
+ if (getLangOptions().Microsoft && isa<CXXConstructorDecl>(Func)) {
+ AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, NumArgs,
+ CandidateSet);
+ } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
// If explicit template arguments were provided, we can't call a
// non-template member function.
if (TemplateArgs)
continue;
-
+
AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType,
- Args, NumArgs,
- CandidateSet, /*SuppressUserConversions=*/false);
+ ObjectClassification,
+ Args, NumArgs, CandidateSet,
+ /*SuppressUserConversions=*/false);
} else {
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
I.getPair(), ActingDC, TemplateArgs,
- ObjectType, Args, NumArgs,
- CandidateSet,
+ ObjectType, ObjectClassification,
+ Args, NumArgs, CandidateSet,
/*SuppressUsedConversions=*/false);
}
}
@@ -7330,7 +8396,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(),
- Best)) {
+ Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
FoundDecl = Best->FoundDecl;
@@ -7374,17 +8440,20 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
}
+ QualType ResultType = Method->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultType);
+ ResultType = ResultType.getNonLValueExprType(Context);
+
assert(Method && "Member call to something that isn't a method?");
- CXXMemberCallExpr *TheCall =
+ CXXMemberCallExpr *TheCall =
new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
- Method->getCallResultType(),
- RParenLoc);
+ ResultType, VK, RParenLoc);
// Check for a valid return type.
- if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(),
+ if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(),
TheCall, Method))
return ExprError();
-
+
// Convert the object argument (for a non-static member function call).
// We only need to do this if there was actually an overload; otherwise
// it was done at lookup.
@@ -7396,7 +8465,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
MemExpr->setBase(ObjectArg);
// Convert the rest of the arguments
- const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *Proto =
+ Method->getType()->getAs<FunctionProtoType>();
if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs,
RParenLoc))
return ExprError();
@@ -7415,8 +8485,10 @@ ExprResult
Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
+ if (Object->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Object);
+
assert(Object->getType()->isRecordType() && "Requires object type argument");
const RecordType *Record = Object->getType()->getAs<RecordType>();
@@ -7430,11 +8502,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
OverloadCandidateSet CandidateSet(LParenLoc);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
- if (RequireCompleteType(LParenLoc, Object->getType(),
+ if (RequireCompleteType(LParenLoc, Object->getType(),
PDiag(diag::err_incomplete_object_call)
<< Object->getSourceRange()))
return true;
-
+
LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
LookupQualifiedName(R, Record->getDecl());
R.suppressDiagnostics();
@@ -7442,10 +8514,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(Oper.getPair(), Object->getType(),
- Args, NumArgs, CandidateSet,
+ Object->Classify(Context), Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/ false);
}
-
+
// C++ [over.call.object]p2:
// In addition, for each conversion function declared in T of the
// form
@@ -7471,7 +8543,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
-
+
// Skip over templated conversion functions; they aren't
// surrogates.
if (isa<FunctionTemplateDecl>(D))
@@ -7487,8 +8559,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
- Object->getType(), Args, NumArgs,
- CandidateSet);
+ Object, Args, NumArgs, CandidateSet);
}
// Perform overload resolution.
@@ -7544,14 +8615,15 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// We selected one of the surrogate functions that converts the
// object parameter to a function pointer. Perform the conversion
// on the object argument, then let ActOnCallExpr finish the job.
-
+
// Create an implicit member expr to refer to the conversion operator.
// and then call it.
- CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Best->FoundDecl,
- Conv);
-
- return ActOnCallExpr(S, CE, LParenLoc, MultiExprArg(Args, NumArgs),
- CommaLocs, RParenLoc);
+ ExprResult Call = BuildCXXMemberCallExpr(Object, Best->FoundDecl, Conv);
+ if (Call.isInvalid())
+ return ExprError();
+
+ return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs),
+ RParenLoc);
}
CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
@@ -7561,7 +8633,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// that calls this method, using Object for the implicit object
// parameter and passing along the remaining arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
- const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *Proto =
+ Method->getType()->getAs<FunctionProtoType>();
unsigned NumArgsInProto = Proto->getNumArgs();
unsigned NumArgsToCheck = NumArgs;
@@ -7580,23 +8653,24 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
MethodArgs[ArgIdx + 1] = Args[ArgIdx];
- Expr *NewFn = new (Context) DeclRefExpr(Method, Method->getType(),
- SourceLocation());
- UsualUnaryConversions(NewFn);
+ Expr *NewFn = CreateFunctionRefExpr(*this, Method);
// Once we've built TheCall, all of the expressions are properly
// owned.
- QualType ResultTy = Method->getCallResultType();
+ QualType ResultTy = Method->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
+
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn,
MethodArgs, NumArgs + 1,
- ResultTy, RParenLoc);
+ ResultTy, VK, RParenLoc);
delete [] MethodArgs;
- if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
+ if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
Method))
return true;
-
+
// We may have default arguments. If so, we need to allocate more
// slots in the call for them.
if (NumArgs < NumArgsInProto)
@@ -7607,7 +8681,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
bool IsError = false;
// Initialize the implicit object parameter.
- IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0,
+ IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0,
Best->FoundDecl, Method);
TheCall->setArg(0, Object);
@@ -7622,9 +8696,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
Method->getParamDecl(i)),
SourceLocation(), Arg);
-
+
IsError |= InputInit.isInvalid();
Arg = InputInit.takeAs<Expr>();
} else {
@@ -7634,7 +8709,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
IsError = true;
break;
}
-
+
Arg = DefArg.takeAs<Expr>();
}
@@ -7664,7 +8739,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
/// @c Member is the name of the member we're trying to find.
ExprResult
Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
- assert(Base->getType()->isRecordType() && "left-hand side must have class type");
+ assert(Base->getType()->isRecordType() &&
+ "left-hand side must have class type");
+
+ if (Base->getObjectKind() == OK_ObjCProperty)
+ ConvertPropertyForRValue(Base);
SourceLocation Loc = Base->getExprLoc();
@@ -7674,7 +8753,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
// for a class object x of type T if T::operator->() exists and if
// the operator is selected as the best match function by the
// overload resolution mechanism (13.3).
- DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
+ DeclarationName OpName =
+ Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
OverloadCandidateSet CandidateSet(Loc);
const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
@@ -7689,8 +8769,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
- AddMethodCandidate(Oper.getPair(), Base->getType(), 0, 0, CandidateSet,
- /*SuppressUserConversions=*/false);
+ AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),
+ 0, 0, CandidateSet, /*SuppressUserConversions=*/false);
}
// Perform overload resolution.
@@ -7711,8 +8791,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
return ExprError();
case OR_Ambiguous:
- Diag(OpLoc, diag::err_ovl_ambiguous_oper)
- << "->" << Base->getSourceRange();
+ Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary)
+ << "->" << Base->getType() << Base->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, &Base, 1);
return ExprError();
@@ -7734,16 +8814,16 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
return ExprError();
// Build the operator call.
- Expr *FnExpr = new (Context) DeclRefExpr(Method, Method->getType(),
- SourceLocation());
- UsualUnaryConversions(FnExpr);
-
- QualType ResultTy = Method->getCallResultType();
+ Expr *FnExpr = CreateFunctionRefExpr(*this, Method);
+
+ QualType ResultTy = Method->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultTy);
+ ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
- new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr,
- &Base, 1, ResultTy, OpLoc);
+ new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr,
+ &Base, 1, ResultTy, VK, OpLoc);
- if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
+ if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
Method))
return ExprError();
return Owned(TheCall);
@@ -7760,27 +8840,27 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(),
Found, Fn);
if (SubExpr == PE->getSubExpr())
- return PE->Retain();
-
+ return PE;
+
return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr);
- }
-
+ }
+
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(),
Found, Fn);
- assert(Context.hasSameType(ICE->getSubExpr()->getType(),
+ assert(Context.hasSameType(ICE->getSubExpr()->getType(),
SubExpr->getType()) &&
"Implicit cast type cannot be determined from overload");
assert(ICE->path_empty() && "fixing up hierarchy conversion?");
if (SubExpr == ICE->getSubExpr())
- return ICE->Retain();
-
- return ImplicitCastExpr::Create(Context, ICE->getType(),
+ return ICE;
+
+ return ImplicitCastExpr::Create(Context, ICE->getType(),
ICE->getCastKind(),
SubExpr, 0,
ICE->getValueKind());
- }
-
+ }
+
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
assert(UnOp->getOpcode() == UO_AddrOf &&
"Can only take the address of an overloaded function");
@@ -7795,7 +8875,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
Found, Fn);
if (SubExpr == UnOp->getSubExpr())
- return UnOp->Retain();
+ return UnOp;
assert(isa<DeclRefExpr>(SubExpr)
&& "fixed to something other than a decl ref");
@@ -7810,19 +8890,21 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
QualType MemPtrType
= Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
- return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
- MemPtrType, UnOp->getOperatorLoc());
+ return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
+ VK_RValue, OK_Ordinary,
+ UnOp->getOperatorLoc());
}
}
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
Found, Fn);
if (SubExpr == UnOp->getSubExpr())
- return UnOp->Retain();
-
+ return UnOp;
+
return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
Context.getPointerType(SubExpr->getType()),
+ VK_RValue, OK_Ordinary,
UnOp->getOperatorLoc());
- }
+ }
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
// FIXME: avoid copy.
@@ -7838,6 +8920,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
Fn,
ULE->getNameLoc(),
Fn->getType(),
+ VK_LValue,
TemplateArgs);
}
@@ -7851,7 +8934,8 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
Expr *Base;
- // If we're filling in
+ // If we're filling in a static method where we used to have an
+ // implicit member access, rewrite to a simple decl ref.
if (MemExpr->isImplicitAccess()) {
if (cast<CXXMethodDecl>(Fn)->isStatic()) {
return DeclRefExpr::Create(Context,
@@ -7860,6 +8944,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
Fn,
MemExpr->getMemberLoc(),
Fn->getType(),
+ VK_LValue,
TemplateArgs);
} else {
SourceLocation Loc = MemExpr->getMemberLoc();
@@ -7870,24 +8955,27 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
/*isImplicit=*/true);
}
} else
- Base = MemExpr->getBase()->Retain();
+ Base = MemExpr->getBase();
return MemberExpr::Create(Context, Base,
- MemExpr->isArrow(),
- MemExpr->getQualifier(),
+ MemExpr->isArrow(),
+ MemExpr->getQualifier(),
MemExpr->getQualifierRange(),
- Fn,
+ Fn,
Found,
MemExpr->getMemberNameInfo(),
TemplateArgs,
- Fn->getType());
+ Fn->getType(),
+ cast<CXXMethodDecl>(Fn)->isStatic()
+ ? VK_LValue : VK_RValue,
+ OK_Ordinary);
}
-
- assert(false && "Invalid reference to overloaded function");
- return E->Retain();
+
+ llvm_unreachable("Invalid reference to overloaded function");
+ return E;
}
-ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
+ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
DeclAccessPair Found,
FunctionDecl *Fn) {
return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn));
OpenPOWER on IntegriCloud