Add the proper restrictions on the left-hand argument of a built-in

assignment operator candidate (C++ [over.match.oper]p4).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62128 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2009-01-13 00:52:54 +00:00
Родитель e63ef48b76
Коммит 88b4bf202a
4 изменённых файлов: 41 добавлений и 13 удалений

Просмотреть файл

@ -458,7 +458,8 @@ public:
OverloadCandidateSet& CandidateSet);
void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet);
OverloadCandidateSet& CandidateSet,
bool IsAssignmentOperator = false);
void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet);

Просмотреть файл

@ -2199,10 +2199,13 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
/// AddBuiltinCandidate - Add a candidate for a built-in
/// operator. ResultTy and ParamTys are the result and parameter types
/// of the built-in candidate, respectively. Args and NumArgs are the
/// arguments being passed to the candidate.
/// arguments being passed to the candidate. IsAssignmentOperator
/// should be true when this built-in candidate is an assignment
/// operator.
void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet) {
OverloadCandidateSet& CandidateSet,
bool IsAssignmentOperator) {
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
@ -2218,8 +2221,21 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
Candidate.Viable = true;
Candidate.Conversions.resize(NumArgs);
for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
// C++ [over.match.oper]p4:
// For the built-in assignment operators, conversions of the
// left operand are restricted as follows:
// -- no temporaries are introduced to hold the left operand, and
// -- no user-defined conversions are applied to the left
// operand to achieve a type match with the left-most
// parameter of a built-in candidate.
//
// We block these conversions by turning off user-defined
// conversions, since that is the only way that initialization of
// a reference to a non-class type can occur from something that
// is not of the same type.
Candidate.Conversions[ArgIdx]
= TryCopyInitialization(Args[ArgIdx], ParamTys[ArgIdx], false);
= TryCopyInitialization(Args[ArgIdx], ParamTys[ArgIdx],
ArgIdx == 0 && IsAssignmentOperator);
if (Candidate.Conversions[ArgIdx].ConversionKind
== ImplicitConversionSequence::BadConversion) {
Candidate.Viable = false;
@ -2794,13 +2810,15 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
// T& operator=(T&, T)
ParamTypes[0] = Context.getReferenceType(*Enum);
ParamTypes[1] = *Enum;
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssignmentOperator=*/true);
if (!Context.getCanonicalType(*Enum).isVolatileQualified()) {
// volatile T& operator=(volatile T&, T)
ParamTypes[0] = Context.getReferenceType((*Enum).withVolatile());
ParamTypes[1] = *Enum;
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssignmentOperator=*/true);
}
}
// Fall through.
@ -2830,12 +2848,14 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
// non-volatile version
ParamTypes[0] = Context.getReferenceType(*Ptr);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
// volatile version
ParamTypes[0] = Context.getReferenceType((*Ptr).withVolatile());
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
}
}
// Fall through.
@ -2862,12 +2882,14 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
// Add this built-in operator as a candidate (VQ is empty).
ParamTypes[0] = Context.getReferenceType(ArithmeticTypes[Left]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
// Add this built-in operator as a candidate (VQ is 'volatile').
ParamTypes[0] = ArithmeticTypes[Left].withVolatile();
ParamTypes[0] = Context.getReferenceType(ParamTypes[0]);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
/*IsAssigmentOperator=*/Op == OO_Equal);
}
}
break;

Просмотреть файл

@ -115,3 +115,8 @@ void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr,
int const &icr2 = 17[cip];
}
// C++ [over.match.open]p4
void test_assign_restrictions(ShortRef& sr) {
sr = (short)0; // expected-error{{incompatible type assigning 'short', expected 'struct ShortRef'}}
}

Просмотреть файл

@ -1243,8 +1243,8 @@ welcome!</p>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13.3.1.2 [over.match.oper]</td>
<td class="complete" align="center">&#x2713;</td>
<td class="medium" align="center"></td>
<td class="medium" align="center"></td>
<td class="advanced" align="center"></td>
<td class="advanced" align="center"></td>
<td class="broken" align="center"></td>
<td></td>
</tr>
@ -1382,7 +1382,7 @@ welcome!</p>
<td>&nbsp;&nbsp;&nbsp;&nbsp;13.5.3 [over.ass]</td>
<td class="na" align="center">N/A</td>
<td class="advanced" align="center"></td>
<td class="basic" align="center"></td>
<td class="advanced" align="center"></td>
<td class="broken" align="center"></td>
<td></td>
</tr>