diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 290 | ||||
-rw-r--r-- | clang/test/CXX/drs/dr23xx.cpp | 33 | ||||
-rw-r--r-- | clang/test/CXX/drs/dr4xx.cpp | 11 | ||||
-rw-r--r-- | clang/test/SemaObjCXX/arc-overloading.mm | 30 | ||||
-rw-r--r-- | clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl | 18 | ||||
-rwxr-xr-x | clang/www/cxx_dr_status.html | 4 | ||||
-rwxr-xr-x | clang/www/make_cxx_dr_status | 4 |
10 files changed, 250 insertions, 153 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c7b501b9bb2..315e836cd39 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 cfb3a05e9c1..cd78f096bb2 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 differing in noexcept. This // will similarly cover difference 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 94d524a63f5..ef4fa827064 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 74a0bc7c78f..92058c3aa5f 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 different + // 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 different, 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 different - // 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 different, 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 different - // 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 different + // 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 763abd5368e..caf3be11454 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 8eeb7715cad..d37ece6cb88 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 3ac9c51293b..910b5c7be97 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 a97565f3a2e..0209e1ea24d 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 23a7218e897..c4ec4573652 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -2645,7 +2645,7 @@ of class templates</td> <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 @@ and <I>POD class</I></td> <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 4351d659e41..fd5eb7fbabb 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> |