On Fri, 27 Dec 2019 at 15:59, David Blaikie via cfe-commits < cfe-commits@lists.llvm.org> wrote:
> On Fri, Dec 27, 2019 at 3:48 PM Richard Smith <rich...@metafoo.co.uk> > wrote: > >> On Fri, 27 Dec 2019 at 12:27, David Blaikie via cfe-commits < >> cfe-commits@lists.llvm.org> wrote: >> >>> >>> 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. >>> >> >> I believe the new Clang behavior here is correct according to the >> standard wording. >> > > Ah, OK. Thanks for looking/checking! > > >> However, GCC trunk also implements CWG2352 and accepts this, >> > > Right, I should've mentioned I checked against GCC trunk. The other case > that showed up with this change: > > template<typename T> > void f(T&&); > void f() { > int *i; > f<const int *>(i); > } > > that one failed with both GCC and Clang (& I've written up a fix for it > internally) & /seems/ roughly like what I believe is to be correct behavior > form the compiler/new patch here (& consistent with GCC, giving it a bit > more a vote for "this seems like good behavior") > Yes, I think this one is correct behavior. > and there's a natural-seeming way to get that result, so I'm going to take >> this back to the core reflector and see if people agree that this ought to >> remain valid. >> > > OK - happy to help with internal fixes if/when that's needed (I think it > might just be the one, though - so maybe that goes to show this isn't the > worst behavior) > > >> >> >>> 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@-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@-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@-3{{pointer type mismatch ('__generic int >>> *__generic *' and '__local int *__local *')}} >>> +// expected-warning-re@-2{{pointer type mismatch >>> ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' >>> and '__{{(local|global|constant)}} int *__{{(local|global|constant)}} *')}} >>> +#else >>> +// expected-error-re@-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> >>> >>> >>> >>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits@lists.llvm.org >>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> >> _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits