Issue error on invalid arithemtic conversions in C ternary

As reported in PR46774, an invalid arithemetic conversion used in a C
ternary operator resulted in an assertion. This patch replaces that
assertion with a diagnostic stating that the conversion failed.

At the moment, I believe the only case of this happening is _ExtInt
types.
This commit is contained in:
Erich Keane 2020-07-20 08:00:13 -07:00
parent ad8e900cb3
commit 66aff32398
3 changed files with 30 additions and 0 deletions

View File

@ -8106,6 +8106,15 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
// Disallow invalid arithmetic conversions, such as those between ExtInts of
// different sizes, or between ExtInts and other types.
if (ResTy.isNull() && (LHSTy->isExtIntType() || RHSTy->isExtIntType())) {
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
return QualType();
}
LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy));
RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy));

12
clang/test/Sema/ext-int.c Normal file
View File

@ -0,0 +1,12 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -Wimplicit-int-conversion -triple x86_64-gnu-linux
typedef _ExtInt(31) EI31;
void Ternary(_ExtInt(30) s30, EI31 s31a, _ExtInt(31) s31b,
_ExtInt(32) s32, int b) {
b ? s30 : s31a; // expected-error{{incompatible operand types}}
b ? s31a : s30; // expected-error{{incompatible operand types}}
b ? s32 : 0; // expected-error{{incompatible operand types}}
(void)(b ? s31a : s31b);
(void)(s30 ? s31a : s31b);
}

View File

@ -275,3 +275,12 @@ void ImplicitCasts(_ExtInt(31) s31, _ExtInt(33) s33, int i) {
// expected-warning@+1{{implicit conversion loses integer precision}}
i = s33;
}
void Ternary(_ExtInt(30) s30, _ExtInt(31) s31a, _ExtInt(31) s31b,
_ExtInt(32) s32, bool b) {
b ? s30 : s31a; // expected-error{{incompatible operand types}}
b ? s31a : s30; // expected-error{{incompatible operand types}}
b ? s32 : (int)0; // expected-error{{incompatible operand types}}
(void)(b ? s31a : s31b);
(void)(s30 ? s31a : s31b);
}