Sorry if this is expected behavior, but saw a regression that looks /plausibly/ correct & is rendered ambiguous by this change so I've gone ahead and reverted this patch in d8018233d1ea4234de68d5b4593abd773db79484
Comment from the original: 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)) On Thu, Dec 19, 2019 at 6:56 PM Richard Smith via cfe-commits < cfe-commits@lists.llvm.org> wrote: > > Author: Richard Smith > Date: 2019-12-19T18:37:55-08:00 > New Revision: de21704ba96fa80d3e9402f12c6505917a3885f4 > > URL: > https://github.com/llvm/llvm-project/commit/de21704ba96fa80d3e9402f12c6505917a3885f4 > DIFF: > https://github.com/llvm/llvm-project/commit/de21704ba96fa80d3e9402f12c6505917a3885f4.diff > > LOG: CWG2352: Allow qualification conversions during reference binding. > > The language wording change forgot to update overload resolution to rank > implicit conversion sequences based on qualification conversions in > reference bindings. The anticipated resolution for that oversight is > implemented here -- we order candidates based on qualification > conversion, not only on top-level cv-qualifiers. > > For OpenCL/C++, this allows reference binding between pointers with > differing (nested) address spaces. This makes the behavior of reference > binding consistent with that of implicit pointer conversions, as is the > purpose of this change, but that pre-existing behavior for pointer > conversions is itself probably not correct. In any case, it's now > consistently the same behavior and implemented in only one place. > > 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 c7b501b9bb2b..315e836cd397 100644 > --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td > +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td > @@ -1927,7 +1927,8 @@ 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}2">; > + "%select{drops %3 qualifier%plural{1:|2:|4:|:s}4|changes address space|" > + "not permitted due to incompatible qualifiers}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 cfb3a05e9c14..cd78f096bb22 100644 > --- a/clang/lib/Sema/SemaExprCXX.cpp > +++ b/clang/lib/Sema/SemaExprCXX.cpp > @@ -5864,6 +5864,8 @@ 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 94d524a63f5a..ef4fa827064e 100644 > --- a/clang/lib/Sema/SemaInit.cpp > +++ b/clang/lib/Sema/SemaInit.cpp > @@ -8919,11 +8919,17 @@ bool InitializationSequence::Diagnose(Sema &S, > S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) > << NonRefType << SourceType << 1 /*addr space*/ > << Args[0]->getSourceRange(); > - else > + else if (DroppedQualifiers.hasQualifiers()) > 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 74a0bc7c78ff..92058c3aa5fd 100644 > --- a/clang/lib/Sema/SemaOverload.cpp > +++ b/clang/lib/Sema/SemaOverload.cpp > @@ -3153,6 +3153,70 @@ 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). > @@ -3178,73 +3242,16 @@ Sema::IsQualificationConversion(QualType FromType, > QualType ToType, > bool PreviousToQualsIncludeConst = true; > bool UnwrappedAnyPointer = false; > while (Context.UnwrapSimilarTypes(FromType, ToType)) { > - // 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) > + if (!isQualificationConversionStep(FromType, ToType, CStyle, > + PreviousToQualsIncludeConst, > + ObjCLifetimeConversion)) > 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; > + UnwrappedAnyPointer = true; > } > > // We are left with FromType and ToType being the pointee types > // after unwrapping the original FromType and ToType the same number > - // of types. If we unwrapped any pointers, and if FromType and > + // of times. 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); > @@ -3990,32 +3997,41 @@ 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; > - } > > - // 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)) > + // 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) > return ImplicitConversionSequence::Better; > - else if (T1.isMoreQualifiedThan(T2)) > + if (Worse) > return ImplicitConversionSequence::Worse; > } > } > @@ -4402,10 +4418,19 @@ 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-related, > -/// reference-compatible, reference-compatible with added > -/// qualification, or incompatible, for use in C++ initialization by > +/// determine whether they are reference-compatible, > +/// reference-related, 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. > @@ -4427,10 +4452,17 @@ Sema::CompareReferenceRelationship(SourceLocation > Loc, > ReferenceConversions &Conv = ConvOut ? *ConvOut : ConvTmp; > Conv = ReferenceConversions(); > > - // C++ [dcl.init.ref]p4: > + // C++2a [dcl.init.ref]p4: > // Given types "cv1 T1" and "cv2 T2," "cv1 T1" is > - // reference-related to "cv2 T2" if T1 is the same type as T2, or > + // reference-related to "cv2 T2" if T1 is similar to 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. > @@ -4444,59 +4476,47 @@ 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; > > - // MS compiler ignores __unaligned qualifier for references; do the > same. > - T1Quals.removeUnaligned(); > - T2Quals.removeUnaligned(); > + // We can have a qualification conversion. Compute whether the types are > + // similar at the same time. > + bool PreviousToQualsIncludeConst = true; > + do { > + if (T1 == T2) > + break; > > - if (T1Quals != T2Quals) > + // We will need a qualification conversion. > Conv |= ReferenceConversions::Qualification; > > - if (T1Quals.compatiblyIncludes(T2Quals)) > - return Ref_Compatible; > - else > - return Ref_Related; > + // 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; > } > > /// 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 763abd5368ef..caf3be114547 100644 > --- a/clang/test/CXX/drs/dr23xx.cpp > +++ b/clang/test/CXX/drs/dr23xx.cpp > @@ -4,9 +4,38 @@ > // 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 > > -#if __cplusplus <= 201103L > -// expected-no-diagnostics > +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 > #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 8eeb7715cadf..d37ece6cb882 100644 > --- a/clang/test/CXX/drs/dr4xx.cpp > +++ b/clang/test/CXX/drs/dr4xx.cpp > @@ -486,14 +486,21 @@ namespace dr433 { // dr433: yes > S<int> s; > } > > -namespace dr434 { // dr434: yes > +namespace dr434 { // dr434: sup 2352 > void f() { > const int ci = 0; > int *pi = 0; > - const int *&rpci = pi; // expected-error {{cannot bind}} > + const int *&rpci = pi; // expected-error {{incompatible qualifiers}} > + const int * const &rcpci = pi; // OK > 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 3ac9c51293b7..910b5c7be978 100644 > --- a/clang/test/SemaObjCXX/arc-overloading.mm > +++ b/clang/test/SemaObjCXX/arc-overloading.mm > @@ -174,6 +174,36 @@ 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 a97565f3a2e5..0209e1ea24de 100644 > --- a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl > +++ b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl > @@ -501,12 +501,9 @@ 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__ > @@ -516,12 +513,17 @@ 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 *' to '__generic > int *__generic *' 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__ > -// 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}} *')}} > +#ifdef GENERIC > +// expected-warning@-3{{pointer type mismatch ('__generic int *__generic > *' and '__local int *__local *')}} > #endif > #endif > } > > diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html > index 23a7218e897a..c4ec45736524 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="full" align="center">Yes</td> > + <td class="svn" align="center">Superseded by <a > href="#2352">2352</a></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="none" align="center">Unknown</td> > + <td class="svn" align="center">SVN</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 4351d659e41a..fd5eb7fbabb4 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>', > '').strip() > + title = title.replace('<issue_title>', '').replace('</issue_title>', > '').replace('\r\n', '\n').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="http://wg21.link/cwg%s">%s</a></td> > + <td><a href="https://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