diff options
-rw-r--r-- | clang/lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 40 | ||||
-rw-r--r-- | clang/test/SemaCXX/overloaded-builtin-operators.cpp | 5 | ||||
-rw-r--r-- | clang/www/cxx_status.html | 6 |
4 files changed, 41 insertions, 13 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index fc619c6f1f2..dde9b761e24 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7ef7d854268..be1a27e5c68 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -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; diff --git a/clang/test/SemaCXX/overloaded-builtin-operators.cpp b/clang/test/SemaCXX/overloaded-builtin-operators.cpp index 284bdb8d308..242493076c7 100644 --- a/clang/test/SemaCXX/overloaded-builtin-operators.cpp +++ b/clang/test/SemaCXX/overloaded-builtin-operators.cpp @@ -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'}} +} diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 4df163faebd..9a9f12604bb 100644 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -1243,8 +1243,8 @@ welcome!</p> <tr>
<td> 13.3.1.2 [over.match.oper]</td>
<td class="complete" align="center">✓</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> 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>
|