From: Douglas Gregor Date: Tue, 13 Jan 2009 00:52:54 +0000 (+0000) Subject: Add the proper restrictions on the left-hand argument of a built-in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=88b4bf202a6bb67ed241281b8dea973f38df2782;p=clang 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 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index fc619c6f1f..dde9b761e2 100644 --- a/lib/Sema/Sema.h +++ b/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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7ef7d85426..be1a27e5c6 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/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/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp index 284bdb8d30..242493076c 100644 --- a/test/SemaCXX/overloaded-builtin-operators.cpp +++ b/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/www/cxx_status.html b/www/cxx_status.html index 4df163faeb..9a9f12604b 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -1243,8 +1243,8 @@ welcome!

      13.3.1.2 [over.match.oper] ✓ - - + + @@ -1382,7 +1382,7 @@ welcome!

    13.5.3 [over.ass] N/A - +