diff options
author | David Blaikie <dblaikie@gmail.com> | 2019-12-27 12:17:01 -0800 |
---|---|---|
committer | David Blaikie <dblaikie@gmail.com> | 2019-12-27 12:27:20 -0800 |
commit | d8018233d1ea4234de68d5b4593abd773db79484 (patch) | |
tree | 875fe6e8d822c1e8ffea309bbffebe4661315712 | |
parent | c3d3569d4ca6d8ca85fa0755b3d5bd659d81e758 (diff) | |
download | bcm5719-llvm-d8018233d1ea4234de68d5b4593abd773db79484.tar.gz bcm5719-llvm-d8018233d1ea4234de68d5b4593abd773db79484.zip |
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.
-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, 153 insertions, 250 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b86abd0db73..54299a0409f 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 cd78f096bb2..cfb3a05e9c1 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 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 ef4fa827064..94d524a63f5 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 92058c3aa5f..74a0bc7c78f 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 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). @@ -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 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) + 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 different + // 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 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) + // 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 caf3be11454..763abd5368e 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 d37ece6cb88..8eeb7715cad 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 910b5c7be97..3ac9c51293b 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 14f7cf3a0e7..c46e4e08a2c 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 c4ec4573652..23a7218e897 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="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 @@ 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="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 fd5eb7fbabb..4351d659e41 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> |