]> granicus.if.org Git - clang/commitdiff
Add the proper restrictions on the left-hand argument of a built-in
authorDouglas Gregor <dgregor@apple.com>
Tue, 13 Jan 2009 00:52:54 +0000 (00:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 13 Jan 2009 00:52:54 +0000 (00:52 +0000)
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

lib/Sema/Sema.h
lib/Sema/SemaOverload.cpp
test/SemaCXX/overloaded-builtin-operators.cpp
www/cxx_status.html

index fc619c6f1f2274a6ce364111d1383279ffa48d2a..dde9b761e24c045d8182e46e00bfcf900cbf7217 100644 (file)
@@ -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);
index 7ef7d85426830bf67e1499abd2691ef8e3e5b5c3..be1a27e5c688337ee6f981aa2765b9d388c8201e 100644 (file)
@@ -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;
index 284bdb8d3080110c47bc610f5d7b5360833368a3..242493076c7463889e8c3ec9b643518ce41a51d8 100644 (file)
@@ -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'}}
+}
index 4df163faebd7e45a8ce3f36939cf9b8e6f46d866..9a9f12604bbf4314a188081d2461c33a6c99237f 100644 (file)
@@ -1243,8 +1243,8 @@ welcome!</p>
 <tr>\r
   <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13.3.1.2 [over.match.oper]</td>\r
   <td class="complete" align="center">&#x2713;</td>  \r
-  <td class="medium" align="center"></td>\r
-  <td class="medium" align="center"></td>\r
+  <td class="advanced" align="center"></td>\r
+  <td class="advanced" align="center"></td>\r
   <td class="broken" align="center"></td>  \r
   <td></td>\r
 </tr>\r
@@ -1382,7 +1382,7 @@ welcome!</p>
   <td>&nbsp;&nbsp;&nbsp;&nbsp;13.5.3 [over.ass]</td>\r
   <td class="na" align="center">N/A</td>  \r
   <td class="advanced" align="center"></td>\r
-  <td class="basic" align="center"></td>\r
+  <td class="advanced" align="center"></td>\r
   <td class="broken" align="center"></td>  \r
   <td></td>\r
 </tr>\r