[clang] d801823 - Revert "CWG2352: Allow qualification conversions during reference binding."

David Blaikie via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 27 12:27:29 PST 2019


Author: David Blaikie
Date: 2019-12-27T12:27:20-08:00
New Revision: d8018233d1ea4234de68d5b4593abd773db79484

URL: https://github.com/llvm/llvm-project/commit/d8018233d1ea4234de68d5b4593abd773db79484
DIFF: https://github.com/llvm/llvm-project/commit/d8018233d1ea4234de68d5b4593abd773db79484.diff

LOG: Revert "CWG2352: Allow qualification conversions during reference binding."

This reverts commit de21704ba96fa80d3e9402f12c6505917a3885f4.

Regressed/causes this to error due to ambiguity:

  void f(const int * const &);
  void f(int *);
  int main() {
    int * x;
    f(x);
  }

(in case it's important - the original case where this turned up was a
member function overload in a class template with, essentially:

  f(const T1&)
  f(T2*)

(where T1 == X const *, T2 == X))

It's not super clear to me if this ^ is expected behavior, in which case
I'm sorry about the revert & happy to look into ways to fix the original
code.

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaExprCXX.cpp
    clang/lib/Sema/SemaInit.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/test/CXX/drs/dr23xx.cpp
    clang/test/CXX/drs/dr4xx.cpp
    clang/test/SemaObjCXX/arc-overloading.mm
    clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
    clang/www/cxx_dr_status.html
    clang/www/make_cxx_dr_status

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b86abd0db73e..54299a0409fd 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1933,8 +1933,7 @@ def err_lvalue_reference_bind_to_unrelated : Error<
   "cannot bind to a value of unrelated type}1,2">;
 def err_reference_bind_drops_quals : Error<
   "binding reference %
diff {of type $ to value of type $|to value}0,1 "
-  "%select{drops %3 qualifier%plural{1:|2:|4:|:s}4|changes address space|"
-  "not permitted due to incompatible qualifiers}2">;
+  "%select{drops %3 qualifier%plural{1:|2:|4:|:s}4|changes address space}2">;
 def err_reference_bind_failed : Error<
   "reference %
diff {to %select{type|incomplete type}1 $ could not bind to an "
   "%select{rvalue|lvalue}2 of type $|could not bind to %select{rvalue|lvalue}2 of "

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index cd78f096bb22..cfb3a05e9c14 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5864,8 +5864,6 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
   //   one of the operands is reference-compatible with the other, in order
   //   to support conditionals between functions 
diff ering in noexcept. This
   //   will similarly cover 
diff erence in array bounds after P0388R4.
-  // FIXME: If LTy and RTy have a composite pointer type, should we convert to
-  //   that instead?
   ExprValueKind LVK = LHS.get()->getValueKind();
   ExprValueKind RVK = RHS.get()->getValueKind();
   if (!Context.hasSameType(LTy, RTy) &&

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index ef4fa827064e..94d524a63f5a 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -8919,17 +8919,11 @@ bool InitializationSequence::Diagnose(Sema &S,
       S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
           << NonRefType << SourceType << 1 /*addr space*/
           << Args[0]->getSourceRange();
-    else if (DroppedQualifiers.hasQualifiers())
+    else
       S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
           << NonRefType << SourceType << 0 /*cv quals*/
           << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers())
           << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange();
-    else
-      // FIXME: Consider decomposing the type and explaining which qualifiers
-      // were dropped where, or on which level a 'const' is missing, etc.
-      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
-          << NonRefType << SourceType << 2 /*incompatible quals*/
-          << Args[0]->getSourceRange();
     break;
   }
 

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 92058c3aa5fd..74a0bc7c78ff 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -3153,70 +3153,6 @@ static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals,
   return true;
 }
 
-/// Perform a single iteration of the loop for checking if a qualification
-/// conversion is valid.
-///
-/// Specifically, check whether any change between the qualifiers of \p
-/// FromType and \p ToType is permissible, given knowledge about whether every
-/// outer layer is const-qualified.
-static bool isQualificationConversionStep(QualType FromType, QualType ToType,
-                                          bool CStyle,
-                                          bool &PreviousToQualsIncludeConst,
-                                          bool &ObjCLifetimeConversion) {
-  Qualifiers FromQuals = FromType.getQualifiers();
-  Qualifiers ToQuals = ToType.getQualifiers();
-
-  // Ignore __unaligned qualifier if this type is void.
-  if (ToType.getUnqualifiedType()->isVoidType())
-    FromQuals.removeUnaligned();
-
-  // Objective-C ARC:
-  //   Check Objective-C lifetime conversions.
-  if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime()) {
-    if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) {
-      if (isNonTrivialObjCLifetimeConversion(FromQuals, ToQuals))
-        ObjCLifetimeConversion = true;
-      FromQuals.removeObjCLifetime();
-      ToQuals.removeObjCLifetime();
-    } else {
-      // Qualification conversions cannot cast between 
diff erent
-      // Objective-C lifetime qualifiers.
-      return false;
-    }
-  }
-
-  // Allow addition/removal of GC attributes but not changing GC attributes.
-  if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() &&
-      (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) {
-    FromQuals.removeObjCGCAttr();
-    ToQuals.removeObjCGCAttr();
-  }
-
-  //   -- for every j > 0, if const is in cv 1,j then const is in cv
-  //      2,j, and similarly for volatile.
-  if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
-    return false;
-
-  // For a C-style cast, just require the address spaces to overlap.
-  // FIXME: Does "superset" also imply the representation of a pointer is the
-  // same? We're assuming that it does here and in compatiblyIncludes.
-  if (CStyle && !ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
-      !FromQuals.isAddressSpaceSupersetOf(ToQuals))
-    return false;
-
-  //   -- if the cv 1,j and cv 2,j are 
diff erent, then const is in
-  //      every cv for 0 < k < j.
-  if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers() &&
-      !PreviousToQualsIncludeConst)
-    return false;
-
-  // Keep track of whether all prior cv-qualifiers in the "to" type
-  // include const.
-  PreviousToQualsIncludeConst =
-      PreviousToQualsIncludeConst && ToQuals.hasConst();
-  return true;
-}
-
 /// IsQualificationConversion - Determines whether the conversion from
 /// an rvalue of type FromType to ToType is a qualification conversion
 /// (C++ 4.4).
@@ -3242,16 +3178,73 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
   bool PreviousToQualsIncludeConst = true;
   bool UnwrappedAnyPointer = false;
   while (Context.UnwrapSimilarTypes(FromType, ToType)) {
-    if (!isQualificationConversionStep(FromType, ToType, CStyle,
-                                       PreviousToQualsIncludeConst,
-                                       ObjCLifetimeConversion))
-      return false;
+    // Within each iteration of the loop, we check the qualifiers to
+    // determine if this still looks like a qualification
+    // conversion. Then, if all is well, we unwrap one more level of
+    // pointers or pointers-to-members and do it all again
+    // until there are no more pointers or pointers-to-members left to
+    // unwrap.
     UnwrappedAnyPointer = true;
+
+    Qualifiers FromQuals = FromType.getQualifiers();
+    Qualifiers ToQuals = ToType.getQualifiers();
+
+    // Ignore __unaligned qualifier if this type is void.
+    if (ToType.getUnqualifiedType()->isVoidType())
+      FromQuals.removeUnaligned();
+
+    // Objective-C ARC:
+    //   Check Objective-C lifetime conversions.
+    if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() &&
+        UnwrappedAnyPointer) {
+      if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) {
+        if (isNonTrivialObjCLifetimeConversion(FromQuals, ToQuals))
+          ObjCLifetimeConversion = true;
+        FromQuals.removeObjCLifetime();
+        ToQuals.removeObjCLifetime();
+      } else {
+        // Qualification conversions cannot cast between 
diff erent
+        // Objective-C lifetime qualifiers.
+        return false;
+      }
+    }
+
+    // Allow addition/removal of GC attributes but not changing GC attributes.
+    if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() &&
+        (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) {
+      FromQuals.removeObjCGCAttr();
+      ToQuals.removeObjCGCAttr();
+    }
+
+    //   -- for every j > 0, if const is in cv 1,j then const is in cv
+    //      2,j, and similarly for volatile.
+    if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
+      return false;
+
+    //   -- if the cv 1,j and cv 2,j are 
diff erent, then const is in
+    //      every cv for 0 < k < j.
+    if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers()
+        && !PreviousToQualsIncludeConst)
+      return false;
+
+    // Keep track of whether all prior cv-qualifiers in the "to" type
+    // include const.
+    PreviousToQualsIncludeConst
+      = PreviousToQualsIncludeConst && ToQuals.hasConst();
+  }
+
+  // Allows address space promotion by language rules implemented in
+  // Type::Qualifiers::isAddressSpaceSupersetOf.
+  Qualifiers FromQuals = FromType.getQualifiers();
+  Qualifiers ToQuals = ToType.getQualifiers();
+  if (!ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
+      !FromQuals.isAddressSpaceSupersetOf(ToQuals)) {
+    return false;
   }
 
   // We are left with FromType and ToType being the pointee types
   // after unwrapping the original FromType and ToType the same number
-  // of times. If we unwrapped any pointers, and if FromType and
+  // of types. If we unwrapped any pointers, and if FromType and
   // ToType have the same unqualified type (since we checked
   // qualifiers above), then this is a qualification conversion.
   return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
@@ -3997,41 +3990,32 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
     //      top-level cv-qualifiers, and the type to which the reference
     //      initialized by S2 refers is more cv-qualified than the type
     //      to which the reference initialized by S1 refers.
-    // FIXME: This should have been updated by DR2352, but was overlooked. The
-    // corrected rule is:
-    //   -- S1 and S2 include reference bindings, and references refer to types
-    //      T1 and T2, respectively, where T2 is reference-compatible with T1.
     QualType T1 = SCS1.getToType(2);
     QualType T2 = SCS2.getToType(2);
+    T1 = S.Context.getCanonicalType(T1);
+    T2 = S.Context.getCanonicalType(T2);
+    Qualifiers T1Quals, T2Quals;
+    QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
+    QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
+    if (UnqualT1 == UnqualT2) {
+      // Objective-C++ ARC: If the references refer to objects with 
diff erent
+      // lifetimes, prefer bindings that don't change lifetime.
+      if (SCS1.ObjCLifetimeConversionBinding !=
+                                          SCS2.ObjCLifetimeConversionBinding) {
+        return SCS1.ObjCLifetimeConversionBinding
+                                           ? ImplicitConversionSequence::Worse
+                                           : ImplicitConversionSequence::Better;
+      }
 
-    // Objective-C++ ARC: If the references refer to objects with 
diff erent
-    // lifetimes, prefer bindings that don't change lifetime.
-    //
-    // FIXME: Should this really override ordering based on qualification
-    // conversions? In the correspnding check for pointers, we treat a case
-    // where one candidate has worse qualifications and the other has a
-    // lifetime conversion as ambiguous.
-    if (SCS1.ObjCLifetimeConversionBinding !=
-            SCS2.ObjCLifetimeConversionBinding &&
-        S.Context.hasSameUnqualifiedType(T1, T2)) {
-      return SCS1.ObjCLifetimeConversionBinding
-                 ? ImplicitConversionSequence::Worse
-                 : ImplicitConversionSequence::Better;
-    }
-
-    if (!S.Context.hasSameType(T1, T2)) {
-      // FIXME: Unfortunately, there are pairs of types that admit reference
-      // bindings in both directions, so we can't shortcut the second check
-      // here.
-      bool Better =
-          S.CompareReferenceRelationship(Loc, T2, T1) == Sema::Ref_Compatible;
-      bool Worse =
-          S.CompareReferenceRelationship(Loc, T1, T2) == Sema::Ref_Compatible;
-      if (Better && Worse)
-        return ImplicitConversionSequence::Indistinguishable;
-      if (Better)
+      // 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)
+        T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
+      if (T2.isMoreQualifiedThan(T1))
         return ImplicitConversionSequence::Better;
-      if (Worse)
+      else if (T1.isMoreQualifiedThan(T2))
         return ImplicitConversionSequence::Worse;
     }
   }
@@ -4418,19 +4402,10 @@ static bool isTypeValid(QualType T) {
   return true;
 }
 
-static QualType withoutUnaligned(ASTContext &Ctx, QualType T) {
-  if (!T.getQualifiers().hasUnaligned())
-    return T;
-
-  Qualifiers Q;
-  T = Ctx.getUnqualifiedArrayType(T, Q);
-  Q.removeUnaligned();
-  return Ctx.getQualifiedType(T, Q);
-}
-
 /// CompareReferenceRelationship - Compare the two types T1 and T2 to
-/// determine whether they are reference-compatible,
-/// reference-related, or incompatible, for use in C++ initialization by
+/// determine whether they are reference-related,
+/// reference-compatible, reference-compatible with added
+/// qualification, or incompatible, for use in C++ initialization by
 /// reference (C++ [dcl.ref.init]p4). Neither type can be a reference
 /// type, and the first type (T1) is the pointee type of the reference
 /// type being initialized.
@@ -4452,17 +4427,10 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
   ReferenceConversions &Conv = ConvOut ? *ConvOut : ConvTmp;
   Conv = ReferenceConversions();
 
-  // C++2a [dcl.init.ref]p4:
+  // C++ [dcl.init.ref]p4:
   //   Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
-  //   reference-related to "cv2 T2" if T1 is similar to T2, or
+  //   reference-related to "cv2 T2" if T1 is the same type as T2, or
   //   T1 is a base class of T2.
-  //   "cv1 T1" is reference-compatible with "cv2 T2" if
-  //   a prvalue of type "pointer to cv2 T2" can be converted to the type
-  //   "pointer to cv1 T1" via a standard conversion sequence.
-
-  // Check for standard conversions we can apply to pointers: derived-to-base
-  // conversions, ObjC pointer conversions, and function pointer conversions.
-  // (Qualification conversions are checked last.)
   QualType ConvertedT2;
   if (UnqualT1 == UnqualT2) {
     // Nothing to do.
@@ -4476,47 +4444,59 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
     Conv |= ReferenceConversions::ObjC;
   else if (UnqualT2->isFunctionType() &&
            IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2)) {
+    // C++1z [dcl.init.ref]p4:
+    //   cv1 T1" is reference-compatible with "cv2 T2" if [...] T2 is "noexcept
+    //   function" and T1 is "function"
+    //
+    // We extend this to also apply to 'noreturn', so allow any function
+    // conversion between function types.
     Conv |= ReferenceConversions::Function;
-    // No need to check qualifiers; function types don't have them.
     return Ref_Compatible;
+  } else
+    return Ref_Incompatible;
+
+  // At this point, we know that T1 and T2 are reference-related (at
+  // least).
+
+  // If the type is an array type, promote the element qualifiers to the type
+  // for comparison.
+  if (isa<ArrayType>(T1) && T1Quals)
+    T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+  if (isa<ArrayType>(T2) && T2Quals)
+    T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+
+  // C++ [dcl.init.ref]p4:
+  //   "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
+  //   reference-related to T2 and cv1 is the same cv-qualification
+  //   as, or greater cv-qualification than, cv2. For purposes of
+  //   overload resolution, cases for which cv1 is greater
+  //   cv-qualification than cv2 are identified as
+  //   reference-compatible with added qualification (see 13.3.3.2).
+  //
+  // Note that we also require equivalence of Objective-C GC and address-space
+  // qualifiers when performing these computations, so that e.g., an int in
+  // address space 1 is not reference-compatible with an int in address
+  // space 2.
+  if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() &&
+      T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) {
+    if (isNonTrivialObjCLifetimeConversion(T2Quals, T1Quals))
+      Conv |= ReferenceConversions::ObjCLifetime;
+
+    T1Quals.removeObjCLifetime();
+    T2Quals.removeObjCLifetime();
   }
-  bool ConvertedReferent = Conv != 0;
 
-  // We can have a qualification conversion. Compute whether the types are
-  // similar at the same time.
-  bool PreviousToQualsIncludeConst = true;
-  do {
-    if (T1 == T2)
-      break;
+  // MS compiler ignores __unaligned qualifier for references; do the same.
+  T1Quals.removeUnaligned();
+  T2Quals.removeUnaligned();
 
-    // We will need a qualification conversion.
+  if (T1Quals != T2Quals)
     Conv |= ReferenceConversions::Qualification;
 
-    // MS compiler ignores __unaligned qualifier for references; do the same.
-    T1 = withoutUnaligned(Context, T1);
-    T2 = withoutUnaligned(Context, T2);
-
-    // If we find a qualifier mismatch, the types are not reference-compatible,
-    // but are still be reference-related if they're similar.
-    bool ObjCLifetimeConversion = false;
-    if (!isQualificationConversionStep(T2, T1, /*CStyle=*/false,
-                                       PreviousToQualsIncludeConst,
-                                       ObjCLifetimeConversion))
-      return (ConvertedReferent || Context.hasSimilarType(T1, T2))
-                 ? Ref_Related
-                 : Ref_Incompatible;
-
-    // FIXME: Should we track this for any level other than the first?
-    if (ObjCLifetimeConversion)
-      Conv |= ReferenceConversions::ObjCLifetime;
-  } while (Context.UnwrapSimilarTypes(T1, T2));
-
-  // At this point, if the types are reference-related, we must either have the
-  // same inner type (ignoring qualifiers), or must have already worked out how
-  // to convert the referent.
-  return (ConvertedReferent || Context.hasSameUnqualifiedType(T1, T2))
-             ? Ref_Compatible
-             : Ref_Incompatible;
+  if (T1Quals.compatiblyIncludes(T2Quals))
+    return Ref_Compatible;
+  else
+    return Ref_Related;
 }
 
 /// Look for a user-defined conversion to a value reference-compatible

diff  --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp
index caf3be114547..763abd5368ef 100644
--- a/clang/test/CXX/drs/dr23xx.cpp
+++ b/clang/test/CXX/drs/dr23xx.cpp
@@ -4,38 +4,9 @@
 // RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 // RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
 
-namespace dr2352 { // dr2352: 10
-  int **p;
-  const int *const *const &f1() { return p; }
-  int *const *const &f2() { return p; }
-  int **const &f3() { return p; }
-
-  const int **const &f4() { return p; } // expected-error {{reference to type 'const int **const' could not bind to an lvalue of type 'int **'}}
-  const int *const *&f5() { return p; } // expected-error {{binding reference of type 'const int *const *' to value of type 'int **' not permitted due to incompatible qualifiers}}
-
-  // FIXME: We permit this as a speculative defect resolution, allowing
-  // qualification conversions when forming a glvalue conditional expression.
-  const int * const * const q = 0;
-  __typeof(&(true ? p : q)) x = &(true ? p : q);
-
-  // FIXME: Should we compute the composite pointer type here and produce an
-  // lvalue of type 'const int *const * const'?
-  const int * const * r;
-  void *y = &(true ? p : r); // expected-error {{rvalue of type 'const int *const *'}}
-
-  // FIXME: We order these as a speculative defect resolution.
-  void f(const int * const * const &r);
-#if __cplusplus >= 201103L
-  constexpr
+#if __cplusplus <= 201103L
+// expected-no-diagnostics
 #endif
-  int *const *const &f(int * const * const &r) { return r; }
-
-  // No temporary is created here.
-  int *const *const &check_f = f(p);
-#if __cplusplus >= 201103L
-  static_assert(&p == &check_f, "");
-#endif
-}
 
 namespace dr2353 { // dr2353: 9
   struct X {

diff  --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp
index d37ece6cb882..8eeb7715cadf 100644
--- a/clang/test/CXX/drs/dr4xx.cpp
+++ b/clang/test/CXX/drs/dr4xx.cpp
@@ -486,21 +486,14 @@ namespace dr433 { // dr433: yes
   S<int> s;
 }
 
-namespace dr434 { // dr434: sup 2352
+namespace dr434 { // dr434: yes
   void f() {
     const int ci = 0;
     int *pi = 0;
-    const int *&rpci = pi; // expected-error {{incompatible qualifiers}}
-    const int * const &rcpci = pi; // OK
+    const int *&rpci = pi; // expected-error {{cannot bind}}
     rpci = &ci;
     *pi = 1;
   }
-
-#if __cplusplus >= 201103L
-  int *pi = 0;
-  const int * const &rcpci = pi;
-  static_assert(&rcpci == &pi, "");
-#endif
 }
 
 // dr435: na

diff  --git a/clang/test/SemaObjCXX/arc-overloading.mm b/clang/test/SemaObjCXX/arc-overloading.mm
index 910b5c7be978..3ac9c51293b7 100644
--- a/clang/test/SemaObjCXX/arc-overloading.mm
+++ b/clang/test/SemaObjCXX/arc-overloading.mm
@@ -174,36 +174,6 @@ void test_f9() {
   const __autoreleasing id& ar4 = weak_a;
 }
 
-int &f10(__strong id *&); // expected-note 2{{not viable: no known conversion}}
-float &f10(__autoreleasing id *&); // expected-note 2{{not viable: no known conversion}}
-
-void test_f10() {
-  __strong id *strong_id;
-  __weak id *weak_id;
-  __autoreleasing id *autoreleasing_id;
-  __unsafe_unretained id *unsafe_id;
-
-  int &ir1 = f10(strong_id);
-  float &fr1 = f10(autoreleasing_id);
-  float &fr2 = f10(unsafe_id); // expected-error {{no match}}
-  float &fr2a = f10(weak_id); // expected-error {{no match}}
-}
-
-int &f11(__strong id *const &); // expected-note {{not viable: 1st argument ('__weak id *') has __weak ownership, but parameter has __strong ownership}}
-float &f11(const __autoreleasing id *const &); // expected-note {{not viable: 1st argument ('__weak id *') has __weak ownership, but parameter has __autoreleasing ownership}}
-
-void test_f11() {
-  __strong id *strong_id;
-  __weak id *weak_id;
-  __autoreleasing id *autoreleasing_id;
-  __unsafe_unretained id *unsafe_id;
-
-  int &ir1 = f11(strong_id);
-  float &fr1 = f11(autoreleasing_id);
-  float &fr2 = f11(unsafe_id);
-  float &fr2a = f11(weak_id); // expected-error {{no match}}
-}
-
 // rdar://9790531
 void f9790531(void *inClientData); // expected-note {{candidate function not viable: cannot implicitly convert argument of type 'MixerEQGraphTestDelegate *const __strong' to 'void *' for 1st argument under ARC}}
 void f9790531_1(struct S*inClientData); // expected-note {{candidate function not viable}}

diff  --git a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
index 14f7cf3a0e7e..c46e4e08a2cd 100644
--- a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
+++ b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl
@@ -501,9 +501,12 @@ void test_pointer_chains() {
   // Case 1:
   //  * address spaces of corresponded most outer pointees overlaps, their canonical types are equal
   //  * CVR, address spaces and canonical types of the rest of pointees are equivalent.
-  var_as_as_int = var_asc_as_int;
   var_as_as_int = 0 ? var_as_as_int : var_asc_as_int;
-
+#if __OPENCL_CPP_VERSION__
+#ifdef GENERIC
+// expected-error at -3{{incompatible operand types ('__generic int *__generic *' and '__generic int *__local *')}}
+#endif
+#endif
   // Case 2: Corresponded inner pointees has non-overlapping address spaces.
   var_as_as_int = 0 ? var_as_as_int : var_asc_asn_int;
 #if !__OPENCL_CPP_VERSION__
@@ -513,17 +516,12 @@ void test_pointer_chains() {
 #endif
 
   // Case 3: Corresponded inner pointees has overlapping but not equivalent address spaces.
-  // FIXME: Should this really be allowed in C++ mode?
-  var_as_as_int = var_asc_asc_int;
-#if !__OPENCL_CPP_VERSION__
 #ifdef GENERIC
-// expected-error at -3 {{assigning '__local int *__local *__private' to '__generic int *__generic *__private' changes address space of nested pointer}}
-#endif
-#endif
   var_as_as_int = 0 ? var_as_as_int : var_asc_asc_int;
 #if !__OPENCL_CPP_VERSION__
-#ifdef GENERIC
-// expected-warning at -3{{pointer type mismatch ('__generic int *__generic *' and '__local int *__local *')}}
+// expected-warning-re at -2{{pointer type mismatch ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' and '__{{(local|global|constant)}} int *__{{(local|global|constant)}} *')}}
+#else
+// expected-error-re at -4{{incompatible operand types ('__{{generic|global|constant}} int *__{{generic|global|constant}} *' and '__{{local|global|constant}} int *__{{local|global|constant}} *')}}
 #endif
 #endif
 }

diff  --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index c4ec45736524..23a7218e897a 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -2645,7 +2645,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://wg21.link/cwg434">434</a></td>
     <td>NAD</td>
     <td>Unclear suppression of standard conversions while binding reference to lvalue</td>
-    <td class="svn" align="center">Superseded by <a href="#2352">2352</a></td>
+    <td class="full" align="center">Yes</td>
   </tr>
   <tr id="435">
     <td><a href="https://wg21.link/cwg435">435</a></td>
@@ -13927,7 +13927,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://wg21.link/cwg2352">2352</a></td>
     <td>DR</td>
     <td>Similar types and reference binding</td>
-    <td class="svn" align="center">SVN</td>
+    <td class="none" align="center">Unknown</td>
   </tr>
   <tr id="2353">
     <td><a href="https://wg21.link/cwg2353">2353</a></td>

diff  --git a/clang/www/make_cxx_dr_status b/clang/www/make_cxx_dr_status
index fd5eb7fbabb4..4351d659e41a 100755
--- a/clang/www/make_cxx_dr_status
+++ b/clang/www/make_cxx_dr_status
@@ -28,7 +28,7 @@ def parse(dr):
   _, url, issue = issue_link.split('"', 2)
   url = url.strip()
   issue = int(issue.split('>', 1)[1].split('<', 1)[0])
-  title = title.replace('<issue_title>', '').replace('</issue_title>', '').replace('\r\n', '\n').strip()
+  title = title.replace('<issue_title>', '').replace('</issue_title>', '').strip()
   return DR(section, issue, url, status, title)
 
 status_re = re.compile(r'\bdr([0-9]+): (.*)')
@@ -171,7 +171,7 @@ for dr in drs:
 
   print >> out_file, '''\
   <tr%s id="%s">
-    <td><a href="https://wg21.link/cwg%s">%s</a></td>
+    <td><a href="http://wg21.link/cwg%s">%s</a></td>
     <td>%s</td>
     <td>%s</td>
     <td%s align="center">%s</td>


        


More information about the cfe-commits mailing list