[Clang] Fix crash on invalid size in user-defined static_assert message (#89420)
This addresses two problems observed in #89407 wrt user-defined `static_assert` messages: 1. In `Expr::EvaluateCharRangeAsString`, we were calling `getExtValue()` instead of `getZExtValue()`, which would assert if a negative or very large number was returned from `size()`. 2. If the value could not be converted to `std::size_t`, attempting to diagnose that would crash because `ext_cce_narrowing` was missing two `%select` cases. This fixes #89407.
This commit is contained in:
parent
c4c54af569
commit
b6628c24ef
@ -555,6 +555,8 @@ Bug Fixes to C++ Support
|
||||
- Fix a crash caused by defined struct in a type alias template when the structure
|
||||
has fields with dependent type. Fixes (#GH75221).
|
||||
- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906)
|
||||
- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()``
|
||||
function returns a large or negative value. Fixes (#GH89407).
|
||||
|
||||
Bug Fixes to AST Handling
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -87,9 +87,9 @@ def err_expr_not_cce : Error<
|
||||
"call to 'size()'|call to 'data()'}0 is not a constant expression">;
|
||||
def ext_cce_narrowing : ExtWarn<
|
||||
"%select{case value|enumerator value|non-type template argument|"
|
||||
"array size|explicit specifier argument|noexcept specifier argument}0 "
|
||||
"%select{cannot be narrowed from type %2 to %3|"
|
||||
"evaluates to %2, which cannot be narrowed to type %3}1">,
|
||||
"array size|explicit specifier argument|noexcept specifier argument|"
|
||||
"call to 'size()'|call to 'data()'}0 %select{cannot be narrowed from "
|
||||
"type %2 to %3|evaluates to %2, which cannot be narrowed to type %3}1">,
|
||||
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
|
||||
def err_ice_not_integral : Error<
|
||||
"%select{integer|integral}1 constant expression must have "
|
||||
|
||||
@ -16853,13 +16853,13 @@ bool Expr::EvaluateCharRangeAsString(std::string &Result,
|
||||
if (!::EvaluateInteger(SizeExpression, SizeValue, Info))
|
||||
return false;
|
||||
|
||||
int64_t Size = SizeValue.getExtValue();
|
||||
uint64_t Size = SizeValue.getZExtValue();
|
||||
|
||||
if (!::EvaluatePointer(PtrExpression, String, Info))
|
||||
return false;
|
||||
|
||||
QualType CharTy = PtrExpression->getType()->getPointeeType();
|
||||
for (int64_t I = 0; I < Size; ++I) {
|
||||
for (uint64_t I = 0; I < Size; ++I) {
|
||||
APValue Char;
|
||||
if (!handleLValueToRValueConversion(Info, PtrExpression, CharTy, String,
|
||||
Char))
|
||||
|
||||
@ -341,3 +341,77 @@ struct Callable {
|
||||
} data;
|
||||
};
|
||||
static_assert(false, Callable{}); // expected-error {{static assertion failed: hello}}
|
||||
|
||||
namespace GH89407 {
|
||||
struct A {
|
||||
constexpr __SIZE_TYPE__ size() const { return -1; }
|
||||
constexpr const char* data() const { return ""; }
|
||||
};
|
||||
|
||||
struct B {
|
||||
constexpr long long size() const { return 18446744073709551615U; }
|
||||
constexpr const char* data() const { return ""; }
|
||||
};
|
||||
|
||||
struct C {
|
||||
constexpr __int128 size() const { return -1; }
|
||||
constexpr const char* data() const { return ""; }
|
||||
};
|
||||
|
||||
struct D {
|
||||
constexpr unsigned __int128 size() const { return -1; }
|
||||
constexpr const char* data() const { return ""; }
|
||||
};
|
||||
|
||||
struct E {
|
||||
constexpr __SIZE_TYPE__ size() const { return 18446744073709551615U; }
|
||||
constexpr const char* data() const { return ""; }
|
||||
};
|
||||
|
||||
static_assert(true, A{}); // expected-error {{the message in this static assertion is not a constant expression}}
|
||||
// expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
static_assert(true, B{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}}
|
||||
// expected-error@-1 {{the message in this static assertion is not a constant expression}}
|
||||
// expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
static_assert(true, C{}); // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}}
|
||||
// expected-error@-1 {{the message in this static assertion is not a constant expression}}
|
||||
// expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
static_assert(true, D{}); // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type 'unsigned long'}}
|
||||
// expected-error@-1 {{the message in this static assertion is not a constant expression}}
|
||||
// expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
static_assert(true, E{}); // expected-error {{the message in this static assertion is not a constant expression}}
|
||||
// expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
|
||||
static_assert(
|
||||
false, // expected-error {{static assertion failed}}
|
||||
A{} // expected-error {{the message in a static assertion must be produced by a constant expression}}
|
||||
// expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
);
|
||||
|
||||
static_assert(
|
||||
false, // expected-error {{static assertion failed}}
|
||||
B{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}}
|
||||
// expected-error@-1 {{the message in a static assertion must be produced by a constant expression}}
|
||||
// expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
);
|
||||
|
||||
static_assert(
|
||||
false, // expected-error {{static assertion failed}}
|
||||
C{} // expected-error {{call to 'size()' evaluates to -1, which cannot be narrowed to type 'unsigned long'}}
|
||||
// expected-error@-1 {{the message in a static assertion must be produced by a constant expression}}
|
||||
// expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
);
|
||||
|
||||
static_assert(
|
||||
false, // expected-error {{static assertion failed}}
|
||||
D{} // expected-error {{call to 'size()' evaluates to 340282366920938463463374607431768211455, which cannot be narrowed to type 'unsigned long'}}
|
||||
// expected-error@-1 {{the message in a static assertion must be produced by a constant expression}}
|
||||
// expected-note@-2 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
);
|
||||
|
||||
static_assert(
|
||||
false, // expected-error {{static assertion failed}}
|
||||
E{} // expected-error {{the message in a static assertion must be produced by a constant expression}}
|
||||
// expected-note@-1 {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user