diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8348,6 +8348,10 @@ def err_overflow_builtin_ext_int_max_size : Error< "__builtin_mul_overflow does not support signed _ExtInt operands of more " "than %0 bits">; +def err_overflow_builtin_mul_special_condition_max_size : Error< + "when __builtin_mul_overflow's result argument points to unsigned 128 bit integer, pls make sure " + "input operands won't produce positive (2^127)~(2^128-1) from two negative integer value. That's " + "not supported yet.">; def err_atomic_load_store_uses_lib : Error< "atomic %select{load|store}0 requires runtime support that is not " diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -328,6 +328,22 @@ // Disallow signed ExtIntType args larger than 128 bits to mul function until // we improve backend support. if (BuiltinID == Builtin::BI__builtin_mul_overflow) { + const auto LeftTy = TheCall->getArg(0)->getType(); + const auto RightTy = TheCall->getArg(1)->getType(); + const auto ResultPointeeTy = + TheCall->getArg(2)->getType()->getPointeeType(); + // Input combination below will also emit an integer value larger than + // 128 bits in the backend, disallow same as above. + if (!ResultPointeeTy->isSignedIntegerType() && + S.getASTContext().getIntWidth(ResultPointeeTy) == 128 && + ((LeftTy->isSignedIntegerType() ? S.getASTContext().getIntWidth(LeftTy) + : 0) + + (RightTy->isSignedIntegerType() + ? S.getASTContext().getIntWidth(RightTy) + : 0)) > 128) { + return S.Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_overflow_builtin_mul_special_condition_max_size); + } for (unsigned I = 0; I < 3; ++I) { const auto Arg = TheCall->getArg(I); // Third argument will be a pointer. diff --git a/clang/test/Sema/builtins-overflow.c b/clang/test/Sema/builtins-overflow.c --- a/clang/test/Sema/builtins-overflow.c +++ b/clang/test/Sema/builtins-overflow.c @@ -38,4 +38,22 @@ _ExtInt(129) result; _Bool status = __builtin_mul_overflow(x, y, &result); // expected-error {{__builtin_mul_overflow does not support signed _ExtInt operands of more than 128 bits}} } + { + _ExtInt(128) x = 1; + _ExtInt(128) y = 1; + unsigned _ExtInt(128) result; + _Bool status = __builtin_mul_overflow(x, y, &result); // expected-error {{when __builtin_mul_overflow's result argument points to unsigned 128 bit integer, pls make sure input operands won't produce positive (2^127)~(2^128-1) from two negative integer value. That's not supported yet.}} + } + { + _ExtInt(65) x = 1; + _ExtInt(64) y = 1; + unsigned _ExtInt(128) result; + _Bool status = __builtin_mul_overflow(x, y, &result); // expected-error {{when __builtin_mul_overflow's result argument points to unsigned 128 bit integer, pls make sure input operands won't produce positive (2^127)~(2^128-1) from two negative integer value. That's not supported yet.}} + } + { + _ExtInt(64) x = 1; + _ExtInt(64) y = 1; + unsigned _ExtInt(128) result; + _Bool status = __builtin_mul_overflow(x, y, &result); // expected ok + } }