[clang] d801823 - Revert "CWG2352: Allow qualification conversions during reference binding."
David Blaikie via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 27 15:59:36 PST 2019
On Fri, Dec 27, 2019 at 3:48 PM Richard Smith <richard at metafoo.co.uk> wrote:
> On Fri, 27 Dec 2019 at 12:27, David Blaikie via cfe-commits <
> cfe-commits at 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")
> 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 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>
>>
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191227/75e8eb92/attachment-0001.html>
More information about the cfe-commits
mailing list