diff options
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 565 |
1 files changed, 403 insertions, 162 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 9aae9289b514..a73e6906fceb 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -921,7 +921,7 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, // cannot be a simple walk of the class's decls. Instead, we must perform // lookup and overload resolution. CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0); - if (!CD) + if (!CD || CD->isDeleted()) continue; // Mark the constructor referenced as it is used by this throw expression. @@ -2323,7 +2323,7 @@ static bool resolveAllocationOverload( PartialDiagnosticAt(R.getNameLoc(), S.PDiag(diag::err_ovl_ambiguous_call) << R.getLookupName() << Range), - S, OCD_ViableCandidates, Args); + S, OCD_AmbiguousCandidates, Args); } return true; @@ -3513,7 +3513,7 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, PartialDiagnosticAt(R.getNameLoc(), S.PDiag(diag::err_ovl_ambiguous_call) << R.getLookupName() << Range), - S, OCD_ViableCandidates, Args); + S, OCD_AmbiguousCandidates, Args); return true; case OR_Deleted: { @@ -4095,9 +4095,26 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, << From->getSourceRange(); } + // Defer address space conversion to the third conversion. + QualType FromPteeType = From->getType()->getPointeeType(); + QualType ToPteeType = ToType->getPointeeType(); + QualType NewToType = ToType; + if (!FromPteeType.isNull() && !ToPteeType.isNull() && + FromPteeType.getAddressSpace() != ToPteeType.getAddressSpace()) { + NewToType = Context.removeAddrSpaceQualType(ToPteeType); + NewToType = Context.getAddrSpaceQualType(NewToType, + FromPteeType.getAddressSpace()); + if (ToType->isObjCObjectPointerType()) + NewToType = Context.getObjCObjectPointerType(NewToType); + else if (ToType->isBlockPointerType()) + NewToType = Context.getBlockPointerType(NewToType); + else + NewToType = Context.getPointerType(NewToType); + } + CastKind Kind; CXXCastPath BasePath; - if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle)) + if (CheckPointerConversion(From, NewToType, Kind, BasePath, CStyle)) return ExprError(); // Make sure we extend blocks if necessary. @@ -4108,8 +4125,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, From = E.get(); } if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) - CheckObjCConversion(SourceRange(), ToType, From, CCK); - From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) + CheckObjCConversion(SourceRange(), NewToType, From, CCK); + From = ImpCastExprToType(From, NewToType, Kind, VK_RValue, &BasePath, CCK) .get(); break; } @@ -5730,38 +5747,157 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { return false; } +// Check the condition operand of ?: to see if it is valid for the GCC +// extension. +static bool isValidVectorForConditionalCondition(ASTContext &Ctx, + QualType CondTy) { + if (!CondTy->isVectorType() || CondTy->isExtVectorType()) + return false; + const QualType EltTy = + cast<VectorType>(CondTy.getCanonicalType())->getElementType(); + + assert(!EltTy->isBooleanType() && !EltTy->isEnumeralType() && + "Vectors cant be boolean or enum types"); + return EltTy->isIntegralType(Ctx); +} + +QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS, + ExprResult &RHS, + SourceLocation QuestionLoc) { + LHS = DefaultFunctionArrayLvalueConversion(LHS.get()); + RHS = DefaultFunctionArrayLvalueConversion(RHS.get()); + + QualType CondType = Cond.get()->getType(); + const auto *CondVT = CondType->getAs<VectorType>(); + QualType CondElementTy = CondVT->getElementType(); + unsigned CondElementCount = CondVT->getNumElements(); + QualType LHSType = LHS.get()->getType(); + const auto *LHSVT = LHSType->getAs<VectorType>(); + QualType RHSType = RHS.get()->getType(); + const auto *RHSVT = RHSType->getAs<VectorType>(); + + QualType ResultType; + + // FIXME: In the future we should define what the Extvector conditional + // operator looks like. + if (LHSVT && isa<ExtVectorType>(LHSVT)) { + Diag(QuestionLoc, diag::err_conditional_vector_operand_type) + << /*isExtVector*/ true << LHSType; + return {}; + } + + if (RHSVT && isa<ExtVectorType>(RHSVT)) { + Diag(QuestionLoc, diag::err_conditional_vector_operand_type) + << /*isExtVector*/ true << RHSType; + return {}; + } + + if (LHSVT && RHSVT) { + // If both are vector types, they must be the same type. + if (!Context.hasSameType(LHSType, RHSType)) { + Diag(QuestionLoc, diag::err_conditional_vector_mismatched_vectors) + << LHSType << RHSType; + return {}; + } + ResultType = LHSType; + } else if (LHSVT || RHSVT) { + ResultType = CheckVectorOperands( + LHS, RHS, QuestionLoc, /*isCompAssign*/ false, /*AllowBothBool*/ true, + /*AllowBoolConversions*/ false); + if (ResultType.isNull()) + return {}; + } else { + // Both are scalar. + QualType ResultElementTy; + LHSType = LHSType.getCanonicalType().getUnqualifiedType(); + RHSType = RHSType.getCanonicalType().getUnqualifiedType(); + + if (Context.hasSameType(LHSType, RHSType)) + ResultElementTy = LHSType; + else + ResultElementTy = + UsualArithmeticConversions(LHS, RHS, QuestionLoc, ACK_Conditional); + + if (ResultElementTy->isEnumeralType()) { + Diag(QuestionLoc, diag::err_conditional_vector_operand_type) + << /*isExtVector*/ false << ResultElementTy; + return {}; + } + ResultType = Context.getVectorType( + ResultElementTy, CondType->getAs<VectorType>()->getNumElements(), + VectorType::GenericVector); + + LHS = ImpCastExprToType(LHS.get(), ResultType, CK_VectorSplat); + RHS = ImpCastExprToType(RHS.get(), ResultType, CK_VectorSplat); + } + + assert(!ResultType.isNull() && ResultType->isVectorType() && + "Result should have been a vector type"); + QualType ResultElementTy = ResultType->getAs<VectorType>()->getElementType(); + unsigned ResultElementCount = + ResultType->getAs<VectorType>()->getNumElements(); + + if (ResultElementCount != CondElementCount) { + Diag(QuestionLoc, diag::err_conditional_vector_size) << CondType + << ResultType; + return {}; + } + + if (Context.getTypeSize(ResultElementTy) != + Context.getTypeSize(CondElementTy)) { + Diag(QuestionLoc, diag::err_conditional_vector_element_size) << CondType + << ResultType; + return {}; + } + + return ResultType; +} + /// Check the operands of ?: under C++ semantics. /// /// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y /// extension. In this case, LHS == Cond. (But they're not aliases.) +/// +/// This function also implements GCC's vector extension for conditionals. +/// GCC's vector extension permits the use of a?b:c where the type of +/// a is that of a integer vector with the same number of elements and +/// size as the vectors of b and c. If one of either b or c is a scalar +/// it is implicitly converted to match the type of the vector. +/// Otherwise the expression is ill-formed. If both b and c are scalars, +/// then b and c are checked and converted to the type of a if possible. +/// Unlike the OpenCL ?: operator, the expression is evaluated as +/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]). QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc) { - // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++ - // interface pointers. + // FIXME: Handle C99's complex types, block pointers and Obj-C++ interface + // pointers. + + // Assume r-value. + VK = VK_RValue; + OK = OK_Ordinary; + bool IsVectorConditional = + isValidVectorForConditionalCondition(Context, Cond.get()->getType()); // C++11 [expr.cond]p1 // The first expression is contextually converted to bool. - // - // FIXME; GCC's vector extension permits the use of a?b:c where the type of - // a is that of a integer vector with the same number of elements and - // size as the vectors of b and c. If one of either b or c is a scalar - // it is implicitly converted to match the type of the vector. - // Otherwise the expression is ill-formed. If both b and c are scalars, - // then b and c are checked and converted to the type of a if possible. - // Unlike the OpenCL ?: operator, the expression is evaluated as - // (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]). if (!Cond.get()->isTypeDependent()) { - ExprResult CondRes = CheckCXXBooleanCondition(Cond.get()); + ExprResult CondRes = IsVectorConditional + ? DefaultFunctionArrayLvalueConversion(Cond.get()) + : CheckCXXBooleanCondition(Cond.get()); if (CondRes.isInvalid()) return QualType(); Cond = CondRes; + } else { + // To implement C++, the first expression typically doesn't alter the result + // type of the conditional, however the GCC compatible vector extension + // changes the result type to be that of the conditional. Since we cannot + // know if this is a vector extension here, delay the conversion of the + // LHS/RHS below until later. + return Context.DependentTy; } - // Assume r-value. - VK = VK_RValue; - OK = OK_Ordinary; // Either of the arguments dependent? if (LHS.get()->isTypeDependent() || RHS.get()->isTypeDependent()) @@ -5780,6 +5916,17 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // and value category of the other. bool LThrow = isa<CXXThrowExpr>(LHS.get()->IgnoreParenImpCasts()); bool RThrow = isa<CXXThrowExpr>(RHS.get()->IgnoreParenImpCasts()); + + // Void expressions aren't legal in the vector-conditional expressions. + if (IsVectorConditional) { + SourceRange DiagLoc = + LVoid ? LHS.get()->getSourceRange() : RHS.get()->getSourceRange(); + bool IsThrow = LVoid ? LThrow : RThrow; + Diag(DiagLoc.getBegin(), diag::err_conditional_vector_has_void) + << DiagLoc << IsThrow; + return QualType(); + } + if (LThrow != RThrow) { Expr *NonThrow = LThrow ? RHS.get() : LHS.get(); VK = NonThrow->getValueKind(); @@ -5802,6 +5949,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, } // Neither is void. + if (IsVectorConditional) + return CheckGNUVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc); // C++11 [expr.cond]p3 // Otherwise, if the second and third operand have different types, and @@ -5845,29 +5994,33 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // FIXME: // Resolving a defect in P0012R1: we extend this to cover all cases where // one of the operands is reference-compatible with the other, in order - // to support conditionals between functions differing in noexcept. + // 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) && LVK == RVK && LVK != VK_RValue) { // DerivedToBase was already handled by the class-specific case above. // FIXME: Should we allow ObjC conversions here? - bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion, - FunctionConversion; - if (CompareReferenceRelationship(QuestionLoc, LTy, RTy, DerivedToBase, - ObjCConversion, ObjCLifetimeConversion, - FunctionConversion) == Ref_Compatible && - !DerivedToBase && !ObjCConversion && !ObjCLifetimeConversion && + const ReferenceConversions AllowedConversions = + ReferenceConversions::Qualification | + ReferenceConversions::NestedQualification | + ReferenceConversions::Function; + + ReferenceConversions RefConv; + if (CompareReferenceRelationship(QuestionLoc, LTy, RTy, &RefConv) == + Ref_Compatible && + !(RefConv & ~AllowedConversions) && // [...] subject to the constraint that the reference must bind // directly [...] !RHS.get()->refersToBitField() && !RHS.get()->refersToVectorElement()) { RHS = ImpCastExprToType(RHS.get(), LTy, CK_NoOp, RVK); RTy = RHS.get()->getType(); - } else if (CompareReferenceRelationship( - QuestionLoc, RTy, LTy, DerivedToBase, ObjCConversion, - ObjCLifetimeConversion, - FunctionConversion) == Ref_Compatible && - !DerivedToBase && !ObjCConversion && !ObjCLifetimeConversion && + } else if (CompareReferenceRelationship(QuestionLoc, RTy, LTy, &RefConv) == + Ref_Compatible && + !(RefConv & ~AllowedConversions) && !LHS.get()->refersToBitField() && !LHS.get()->refersToVectorElement()) { LHS = ImpCastExprToType(LHS.get(), RTy, CK_NoOp, LVK); @@ -5976,7 +6129,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // the usual arithmetic conversions are performed to bring them to a // common type, and the result is of that type. if (LTy->isArithmeticType() && RTy->isArithmeticType()) { - QualType ResTy = UsualArithmeticConversions(LHS, RHS); + QualType ResTy = + UsualArithmeticConversions(LHS, RHS, QuestionLoc, ACK_Conditional); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); if (ResTy.isNull()) { @@ -6098,10 +6252,10 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1, /// Find a merged pointer type and convert the two expressions to it. /// -/// This finds the composite pointer type (or member pointer type) for @p E1 -/// and @p E2 according to C++1z 5p14. It converts both expressions to this -/// type and returns it. -/// It does not emit diagnostics. +/// This finds the composite pointer type for \p E1 and \p E2 according to +/// C++2a [expr.type]p3. It converts both expressions to this type and returns +/// it. It does not emit diagnostics (FIXME: that's not true if \p ConvertArgs +/// is \c true). /// /// \param Loc The location of the operator requiring these two expressions to /// be converted to the composite pointer type. @@ -6154,60 +6308,117 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, assert(!T1->isNullPtrType() && !T2->isNullPtrType() && "nullptr_t should be a null pointer constant"); - // - if T1 or T2 is "pointer to cv1 void" and the other type is - // "pointer to cv2 T", "pointer to cv12 void", where cv12 is - // the union of cv1 and cv2; - // - if T1 or T2 is "pointer to noexcept function" and the other type is - // "pointer to function", where the function types are otherwise the same, - // "pointer to function"; - // FIXME: This rule is defective: it should also permit removing noexcept - // from a pointer to member function. As a Clang extension, we also - // permit removing 'noreturn', so we generalize this rule to; - // - [Clang] If T1 and T2 are both of type "pointer to function" or - // "pointer to member function" and the pointee types can be unified - // by a function pointer conversion, that conversion is applied - // before checking the following rules. + struct Step { + enum Kind { Pointer, ObjCPointer, MemberPointer, Array } K; + // Qualifiers to apply under the step kind. + Qualifiers Quals; + /// The class for a pointer-to-member; a constant array type with a bound + /// (if any) for an array. + const Type *ClassOrBound; + + Step(Kind K, const Type *ClassOrBound = nullptr) + : K(K), Quals(), ClassOrBound(ClassOrBound) {} + QualType rebuild(ASTContext &Ctx, QualType T) const { + T = Ctx.getQualifiedType(T, Quals); + switch (K) { + case Pointer: + return Ctx.getPointerType(T); + case MemberPointer: + return Ctx.getMemberPointerType(T, ClassOrBound); + case ObjCPointer: + return Ctx.getObjCObjectPointerType(T); + case Array: + if (auto *CAT = cast_or_null<ConstantArrayType>(ClassOrBound)) + return Ctx.getConstantArrayType(T, CAT->getSize(), nullptr, + ArrayType::Normal, 0); + else + return Ctx.getIncompleteArrayType(T, ArrayType::Normal, 0); + } + llvm_unreachable("unknown step kind"); + } + }; + + SmallVector<Step, 8> Steps; + // - if T1 is "pointer to cv1 C1" and T2 is "pointer to cv2 C2", where C1 // is reference-related to C2 or C2 is reference-related to C1 (8.6.3), // the cv-combined type of T1 and T2 or the cv-combined type of T2 and T1, // respectively; // - if T1 is "pointer to member of C1 of type cv1 U1" and T2 is "pointer - // to member of C2 of type cv2 U2" where C1 is reference-related to C2 or - // C2 is reference-related to C1 (8.6.3), the cv-combined type of T2 and - // T1 or the cv-combined type of T1 and T2, respectively; + // to member of C2 of type cv2 U2" for some non-function type U, where + // C1 is reference-related to C2 or C2 is reference-related to C1, the + // cv-combined type of T2 and T1 or the cv-combined type of T1 and T2, + // respectively; // - if T1 and T2 are similar types (4.5), the cv-combined type of T1 and // T2; // - // If looked at in the right way, these bullets all do the same thing. - // What we do here is, we build the two possible cv-combined types, and try - // the conversions in both directions. If only one works, or if the two - // composite types are the same, we have succeeded. - // FIXME: extended qualifiers? - // - // Note that this will fail to find a composite pointer type for "pointer - // to void" and "pointer to function". We can't actually perform the final - // conversion in this case, even though a composite pointer type formally - // exists. - SmallVector<unsigned, 4> QualifierUnion; - SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass; + // Dismantle T1 and T2 to simultaneously determine whether they are similar + // and to prepare to form the cv-combined type if so. QualType Composite1 = T1; QualType Composite2 = T2; unsigned NeedConstBefore = 0; while (true) { + assert(!Composite1.isNull() && !Composite2.isNull()); + + Qualifiers Q1, Q2; + Composite1 = Context.getUnqualifiedArrayType(Composite1, Q1); + Composite2 = Context.getUnqualifiedArrayType(Composite2, Q2); + + // Top-level qualifiers are ignored. Merge at all lower levels. + if (!Steps.empty()) { + // Find the qualifier union: (approximately) the unique minimal set of + // qualifiers that is compatible with both types. + Qualifiers Quals = Qualifiers::fromCVRUMask(Q1.getCVRUQualifiers() | + Q2.getCVRUQualifiers()); + + // Under one level of pointer or pointer-to-member, we can change to an + // unambiguous compatible address space. + if (Q1.getAddressSpace() == Q2.getAddressSpace()) { + Quals.setAddressSpace(Q1.getAddressSpace()); + } else if (Steps.size() == 1) { + bool MaybeQ1 = Q1.isAddressSpaceSupersetOf(Q2); + bool MaybeQ2 = Q2.isAddressSpaceSupersetOf(Q1); + if (MaybeQ1 == MaybeQ2) + return QualType(); // No unique best address space. + Quals.setAddressSpace(MaybeQ1 ? Q1.getAddressSpace() + : Q2.getAddressSpace()); + } else { + return QualType(); + } + + // FIXME: In C, we merge __strong and none to __strong at the top level. + if (Q1.getObjCGCAttr() == Q2.getObjCGCAttr()) + Quals.setObjCGCAttr(Q1.getObjCGCAttr()); + else + return QualType(); + + // Mismatched lifetime qualifiers never compatibly include each other. + if (Q1.getObjCLifetime() == Q2.getObjCLifetime()) + Quals.setObjCLifetime(Q1.getObjCLifetime()); + else + return QualType(); + + Steps.back().Quals = Quals; + if (Q1 != Quals || Q2 != Quals) + NeedConstBefore = Steps.size() - 1; + } + + // FIXME: Can we unify the following with UnwrapSimilarTypes? const PointerType *Ptr1, *Ptr2; if ((Ptr1 = Composite1->getAs<PointerType>()) && (Ptr2 = Composite2->getAs<PointerType>())) { Composite1 = Ptr1->getPointeeType(); Composite2 = Ptr2->getPointeeType(); + Steps.emplace_back(Step::Pointer); + continue; + } - // If we're allowed to create a non-standard composite type, keep track - // of where we need to fill in additional 'const' qualifiers. - if (Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers()) - NeedConstBefore = QualifierUnion.size(); - - QualifierUnion.push_back( - Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers()); - MemberOfClass.push_back(std::make_pair(nullptr, nullptr)); + const ObjCObjectPointerType *ObjPtr1, *ObjPtr2; + if ((ObjPtr1 = Composite1->getAs<ObjCObjectPointerType>()) && + (ObjPtr2 = Composite2->getAs<ObjCObjectPointerType>())) { + Composite1 = ObjPtr1->getPointeeType(); + Composite2 = ObjPtr2->getPointeeType(); + Steps.emplace_back(Step::ObjCPointer); continue; } @@ -6217,34 +6428,79 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, Composite1 = MemPtr1->getPointeeType(); Composite2 = MemPtr2->getPointeeType(); - // If we're allowed to create a non-standard composite type, keep track - // of where we need to fill in additional 'const' qualifiers. - if (Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers()) - NeedConstBefore = QualifierUnion.size(); + // At the top level, we can perform a base-to-derived pointer-to-member + // conversion: + // + // - [...] where C1 is reference-related to C2 or C2 is + // reference-related to C1 + // + // (Note that the only kinds of reference-relatedness in scope here are + // "same type or derived from".) At any other level, the class must + // exactly match. + const Type *Class = nullptr; + QualType Cls1(MemPtr1->getClass(), 0); + QualType Cls2(MemPtr2->getClass(), 0); + if (Context.hasSameType(Cls1, Cls2)) + Class = MemPtr1->getClass(); + else if (Steps.empty()) + Class = IsDerivedFrom(Loc, Cls1, Cls2) ? MemPtr1->getClass() : + IsDerivedFrom(Loc, Cls2, Cls1) ? MemPtr2->getClass() : nullptr; + if (!Class) + return QualType(); - QualifierUnion.push_back( - Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers()); - MemberOfClass.push_back(std::make_pair(MemPtr1->getClass(), - MemPtr2->getClass())); + Steps.emplace_back(Step::MemberPointer, Class); continue; } + // Special case: at the top level, we can decompose an Objective-C pointer + // and a 'cv void *'. Unify the qualifiers. + if (Steps.empty() && ((Composite1->isVoidPointerType() && + Composite2->isObjCObjectPointerType()) || + (Composite1->isObjCObjectPointerType() && + Composite2->isVoidPointerType()))) { + Composite1 = Composite1->getPointeeType(); + Composite2 = Composite2->getPointeeType(); + Steps.emplace_back(Step::Pointer); + continue; + } + + // FIXME: arrays + // FIXME: block pointer types? // Cannot unwrap any more types. break; } - // Apply the function pointer conversion to unify the types. We've already - // unwrapped down to the function types, and we want to merge rather than - // just convert, so do this ourselves rather than calling + // - if T1 or T2 is "pointer to noexcept function" and the other type is + // "pointer to function", where the function types are otherwise the same, + // "pointer to function"; + // - if T1 or T2 is "pointer to member of C1 of type function", the other + // type is "pointer to member of C2 of type noexcept function", and C1 + // is reference-related to C2 or C2 is reference-related to C1, where + // the function types are otherwise the same, "pointer to member of C2 of + // type function" or "pointer to member of C1 of type function", + // respectively; + // + // We also support 'noreturn' here, so as a Clang extension we generalize the + // above to: + // + // - [Clang] If T1 and T2 are both of type "pointer to function" or + // "pointer to member function" and the pointee types can be unified + // by a function pointer conversion, that conversion is applied + // before checking the following rules. + // + // We've already unwrapped down to the function types, and we want to merge + // rather than just convert, so do this ourselves rather than calling // IsFunctionConversion. // // FIXME: In order to match the standard wording as closely as possible, we // currently only do this under a single level of pointers. Ideally, we would // allow this in general, and set NeedConstBefore to the relevant depth on - // the side(s) where we changed anything. - if (QualifierUnion.size() == 1) { + // the side(s) where we changed anything. If we permit that, we should also + // consider this conversion when determining type similarity and model it as + // a qualification conversion. + if (Steps.size() == 1) { if (auto *FPT1 = Composite1->getAs<FunctionProtoType>()) { if (auto *FPT2 = Composite2->getAs<FunctionProtoType>()) { FunctionProtoType::ExtProtoInfo EPI1 = FPT1->getExtProtoInfo(); @@ -6270,88 +6526,72 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, } } - if (NeedConstBefore) { - // Extension: Add 'const' to qualifiers that come before the first qualifier - // mismatch, so that our (non-standard!) composite type meets the - // requirements of C++ [conv.qual]p4 bullet 3. - for (unsigned I = 0; I != NeedConstBefore; ++I) - if ((QualifierUnion[I] & Qualifiers::Const) == 0) - QualifierUnion[I] = QualifierUnion[I] | Qualifiers::Const; + // There are some more conversions we can perform under exactly one pointer. + if (Steps.size() == 1 && Steps.front().K == Step::Pointer && + !Context.hasSameType(Composite1, Composite2)) { + // - if T1 or T2 is "pointer to cv1 void" and the other type is + // "pointer to cv2 T", where T is an object type or void, + // "pointer to cv12 void", where cv12 is the union of cv1 and cv2; + if (Composite1->isVoidType() && Composite2->isObjectType()) + Composite2 = Composite1; + else if (Composite2->isVoidType() && Composite1->isObjectType()) + Composite1 = Composite2; + // - if T1 is "pointer to cv1 C1" and T2 is "pointer to cv2 C2", where C1 + // is reference-related to C2 or C2 is reference-related to C1 (8.6.3), + // the cv-combined type of T1 and T2 or the cv-combined type of T2 and + // T1, respectively; + // + // The "similar type" handling covers all of this except for the "T1 is a + // base class of T2" case in the definition of reference-related. + else if (IsDerivedFrom(Loc, Composite1, Composite2)) + Composite1 = Composite2; + else if (IsDerivedFrom(Loc, Composite2, Composite1)) + Composite2 = Composite1; } - // Rewrap the composites as pointers or member pointers with the union CVRs. - auto MOC = MemberOfClass.rbegin(); - for (unsigned CVR : llvm::reverse(QualifierUnion)) { - Qualifiers Quals = Qualifiers::fromCVRMask(CVR); - auto Classes = *MOC++; - if (Classes.first && Classes.second) { - // Rebuild member pointer type - Composite1 = Context.getMemberPointerType( - Context.getQualifiedType(Composite1, Quals), Classes.first); - Composite2 = Context.getMemberPointerType( - Context.getQualifiedType(Composite2, Quals), Classes.second); - } else { - // Rebuild pointer type - Composite1 = - Context.getPointerType(Context.getQualifiedType(Composite1, Quals)); - Composite2 = - Context.getPointerType(Context.getQualifiedType(Composite2, Quals)); - } - } - - struct Conversion { - Sema &S; - Expr *&E1, *&E2; - QualType Composite; - InitializedEntity Entity; - InitializationKind Kind; - InitializationSequence E1ToC, E2ToC; - bool Viable; - - Conversion(Sema &S, SourceLocation Loc, Expr *&E1, Expr *&E2, - QualType Composite) - : S(S), E1(E1), E2(E2), Composite(Composite), - Entity(InitializedEntity::InitializeTemporary(Composite)), - Kind(InitializationKind::CreateCopy(Loc, SourceLocation())), - E1ToC(S, Entity, Kind, E1), E2ToC(S, Entity, Kind, E2), - Viable(E1ToC && E2ToC) {} - - bool perform() { - ExprResult E1Result = E1ToC.Perform(S, Entity, Kind, E1); - if (E1Result.isInvalid()) - return true; - E1 = E1Result.getAs<Expr>(); + // At this point, either the inner types are the same or we have failed to + // find a composite pointer type. + if (!Context.hasSameType(Composite1, Composite2)) + return QualType(); - ExprResult E2Result = E2ToC.Perform(S, Entity, Kind, E2); - if (E2Result.isInvalid()) - return true; - E2 = E2Result.getAs<Expr>(); + // Per C++ [conv.qual]p3, add 'const' to every level before the last + // differing qualifier. + for (unsigned I = 0; I != NeedConstBefore; ++I) + Steps[I].Quals.addConst(); - return false; - } - }; + // Rebuild the composite type. + QualType Composite = Composite1; + for (auto &S : llvm::reverse(Steps)) + Composite = S.rebuild(Context, Composite); - // Try to convert to each composite pointer type. - Conversion C1(*this, Loc, E1, E2, Composite1); - if (C1.Viable && Context.hasSameType(Composite1, Composite2)) { - if (ConvertArgs && C1.perform()) + if (ConvertArgs) { + // Convert the expressions to the composite pointer type. + InitializedEntity Entity = + InitializedEntity::InitializeTemporary(Composite); + InitializationKind Kind = + InitializationKind::CreateCopy(Loc, SourceLocation()); + + InitializationSequence E1ToC(*this, Entity, Kind, E1); + if (!E1ToC) return QualType(); - return C1.Composite; - } - Conversion C2(*this, Loc, E1, E2, Composite2); - if (C1.Viable == C2.Viable) { - // Either Composite1 and Composite2 are viable and are different, or - // neither is viable. - // FIXME: How both be viable and different? - return QualType(); - } + InitializationSequence E2ToC(*this, Entity, Kind, E2); + if (!E2ToC) + return QualType(); - // Convert to the chosen type. - if (ConvertArgs && (C1.Viable ? C1 : C2).perform()) - return QualType(); + // FIXME: Let the caller know if these fail to avoid duplicate diagnostics. + ExprResult E1Result = E1ToC.Perform(*this, Entity, Kind, E1); + if (E1Result.isInvalid()) + return QualType(); + E1 = E1Result.get(); + + ExprResult E2Result = E2ToC.Perform(*this, Entity, Kind, E2); + if (E2Result.isInvalid()) + return QualType(); + E2 = E2Result.get(); + } - return C1.Viable ? C1.Composite : C2.Composite; + return Composite; } ExprResult Sema::MaybeBindToTemporary(Expr *E) { @@ -7780,8 +8020,9 @@ class TransformTypos : public TreeTransform<TransformTypos> { // If we found a valid result, double check to make sure it's not ambiguous. if (!IsAmbiguous && !Res.isInvalid() && !AmbiguousTypoExprs.empty()) { - auto SavedTransformCache = std::move(TransformCache); - TransformCache.clear(); + auto SavedTransformCache = + llvm::SmallDenseMap<TypoExpr *, ExprResult, 2>(TransformCache); + // Ensure none of the TypoExprs have multiple typo correction candidates // with the same edit length that pass all the checks and filters. while (!AmbiguousTypoExprs.empty()) { |