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") > 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