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. However, GCC trunk also implements CWG2352 and accepts this, 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. > 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