diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7868,23 +7868,6 @@ return true; } -/// Handle when one or both operands are void type. -static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS, - ExprResult &RHS) { - Expr *LHSExpr = LHS.get(); - Expr *RHSExpr = RHS.get(); - - if (!LHSExpr->getType()->isVoidType()) - S.Diag(RHSExpr->getBeginLoc(), diag::ext_typecheck_cond_one_void) - << RHSExpr->getSourceRange(); - if (!RHSExpr->getType()->isVoidType()) - S.Diag(LHSExpr->getBeginLoc(), diag::ext_typecheck_cond_one_void) - << LHSExpr->getSourceRange(); - LHS = S.ImpCastExprToType(LHS.get(), S.Context.VoidTy, CK_ToVoid); - RHS = S.ImpCastExprToType(RHS.get(), S.Context.VoidTy, CK_ToVoid); - return S.Context.VoidTy; -} - /// Return false if the NullExpr can be promoted to PointerTy, /// true otherwise. static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr, @@ -7908,7 +7891,7 @@ if (S.Context.hasSameType(LHSTy, RHSTy)) { // Two identical pointers types are always compatible. - return LHSTy; + return S.Context.getCommonSugar(LHSTy, RHSTy); } QualType lhptee, rhptee; @@ -8401,7 +8384,7 @@ // And if they're both bfloat (which isn't arithmetic), that's fine too. if (LHSTy->isBFloat16Type() && RHSTy->isBFloat16Type()) { - return LHSTy; + return Context.getCommonSugar(LHSTy, RHSTy); } // If both operands are the same structure or union type, the result is that @@ -8411,14 +8394,29 @@ if (LHSRT->getDecl() == RHSRT->getDecl()) // "If both the operands have structure or union type, the result has // that type." This implies that CV qualifiers are dropped. - return LHSTy.getUnqualifiedType(); + return Context.getCommonSugar(LHSTy.getUnqualifiedType(), + RHSTy.getUnqualifiedType()); // FIXME: Type of conditional expression must be complete in C mode. } // C99 6.5.15p5: "If both operands have void type, the result has void type." // The following || allows only one side to be void (a GCC-ism). if (LHSTy->isVoidType() || RHSTy->isVoidType()) { - return checkConditionalVoidType(*this, LHS, RHS); + /// Handle when one or both operands are void type. + QualType VoidTy = LHSTy->isVoidType() && RHSTy->isVoidType() + ? Context.getCommonSugar(LHSTy, RHSTy) + : LHSTy->isVoidType() ? LHSTy + : RHSTy; + + if (!LHSTy->isVoidType()) + Diag(RHS.get()->getBeginLoc(), diag::ext_typecheck_cond_one_void) + << RHS.get()->getSourceRange(); + if (!RHSTy->isVoidType()) + Diag(LHS.get()->getBeginLoc(), diag::ext_typecheck_cond_one_void) + << LHS.get()->getSourceRange(); + LHS = ImpCastExprToType(LHS.get(), VoidTy, CK_ToVoid); + RHS = ImpCastExprToType(RHS.get(), VoidTy, CK_ToVoid); + return VoidTy; } // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has @@ -8457,7 +8455,7 @@ // Allow ?: operations in which both operands have the same // built-in sizeless type. if (LHSTy->isSizelessBuiltinType() && Context.hasSameType(LHSTy, RHSTy)) - return LHSTy; + return Context.getCommonSugar(LHSTy, RHSTy); // Emit a better diagnostic if one of the expressions is a null pointer // constant and the other is not a pointer type. In this case, the user most @@ -10094,7 +10092,7 @@ // If the vector types are identical, return. if (Context.hasSameType(LHSType, RHSType)) - return LHSType; + return Context.getCommonSugar(LHSType, RHSType); // If we have compatible AltiVec and GCC vector types, use the AltiVec type. if (LHSVecType && RHSVecType && @@ -12517,7 +12515,7 @@ assert((LHSMatType || RHSMatType) && "At least one operand must be a matrix"); if (Context.hasSameType(LHSType, RHSType)) - return LHSType; + return Context.getCommonSugar(LHSType, RHSType); // Type conversion may change LHS/RHS. Keep copies to the original results, in // case we have to return InvalidOperands. @@ -12565,9 +12563,10 @@ RHSMatType->getElementType())) return InvalidOperands(Loc, LHS, RHS); - return Context.getConstantMatrixType(LHSMatType->getElementType(), - LHSMatType->getNumRows(), - RHSMatType->getNumColumns()); + return Context.getConstantMatrixType( + Context.getCommonSugar(LHSMatType->getElementType(), + RHSMatType->getElementType()), + LHSMatType->getNumRows(), RHSMatType->getNumColumns()); } return CheckMatrixElementwiseOperands(LHS, RHS, Loc, IsCompAssign); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6087,7 +6087,7 @@ << LHSType << RHSType; return {}; } - ResultType = LHSType; + ResultType = Context.getCommonSugar(LHSType, RHSType); } else if (LHSVT || RHSVT) { ResultType = CheckVectorOperands( LHS, RHS, QuestionLoc, /*isCompAssign*/ false, /*AllowBothBool*/ true, @@ -6101,7 +6101,7 @@ RHSType = RHSType.getCanonicalType().getUnqualifiedType(); if (Context.hasSameType(LHSType, RHSType)) - ResultElementTy = LHSType; + ResultElementTy = Context.getCommonSugar(LHSType, RHSType); else ResultElementTy = UsualArithmeticConversions(LHS, RHS, QuestionLoc, ACK_Conditional); @@ -6237,7 +6237,7 @@ // -- Both the second and third operands have type void; the result is of // type void and is a prvalue. if (LVoid && RVoid) - return Context.VoidTy; + return Context.getCommonSugar(LTy, RTy); // Neither holds, error. Diag(QuestionLoc, diag::err_conditional_void_nonvoid) @@ -6352,9 +6352,10 @@ assert(!LTy.isNull() && "failed to find composite pointer type for " "canonically equivalent function ptr types"); assert(Context.hasSameType(LTy, RTy) && "bad composite pointer type"); + return LTy; } - return LTy; + return Context.getCommonSugar(LTy, RTy); } // C++11 [expr.cond]p5 @@ -6411,9 +6412,10 @@ LTy = FindCompositePointerType(QuestionLoc, LHS, RHS); assert(!LTy.isNull() && "failed to find composite pointer type for " "canonically equivalent function ptr types"); + return LTy; } - return LTy; + return Context.getCommonSugar(LTy, RTy); } // Extension: conditional operator involving vector types. diff --git a/clang/test/Sema/nullability.c b/clang/test/Sema/nullability.c --- a/clang/test/Sema/nullability.c +++ b/clang/test/Sema/nullability.c @@ -166,7 +166,7 @@ p = c ? nonnullP2 : nonnullP2; p = c ? nonnullP2 : nullableP2; // expected-warning{{implicit conversion from nullable pointer 'IntP _Nullable' (aka 'int *') to non-nullable pointer type 'int * _Nonnull'}} - p = c ? nullableP2 : nonnullP2; // expected-warning{{implicit conversion from nullable pointer 'NullableIntP1' (aka 'int *') to non-nullable pointer type 'int * _Nonnull'}} + p = c ? nullableP2 : nonnullP2; // expected-warning{{implicit conversion from nullable pointer 'IntP _Nullable' (aka 'int *') to non-nullable pointer type 'int * _Nonnull'}} p = c ? nullableP2 : nullableP2; // expected-warning{{implicit conversion from nullable pointer 'NullableIntP1' (aka 'int *') to non-nullable pointer type 'int * _Nonnull'}} }