mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-08 00:52:54 +00:00
Fix crash-on-invalid-code in lambda constant evaluation.
If the lambda used 'this' without without capturing it, an error was emitted, but the constant evaluator would still attempt to lookup the capture, and failing to find it, dereference a null pointer. This only happens in C++17 (as that's when lambdas were made potentially-constexpr). Therefore, I also updated the lambda-expressions.cpp test to run in both C++14 and C++17 modes.
This commit is contained in:
parent
975a435127
commit
90fce46fa6
@ -7861,6 +7861,11 @@ public:
|
||||
// either copied into the closure object's field that represents the '*this'
|
||||
// or refers to '*this'.
|
||||
if (isLambdaCallOperator(Info.CurrentCall->Callee)) {
|
||||
// Ensure we actually have captured 'this'. (an error will have
|
||||
// been previously reported if not).
|
||||
if (!Info.CurrentCall->LambdaThisCaptureField)
|
||||
return false;
|
||||
|
||||
// Update 'Result' to refer to the data member/field of the closure object
|
||||
// that represents the '*this' capture.
|
||||
if (!HandleLValueMember(Info, E, Result,
|
||||
|
@ -1,4 +1,5 @@
|
||||
// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -fblocks %s
|
||||
// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -verify=expected-cxx14 -fblocks %s
|
||||
// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -fsyntax-only -verify -fblocks %s
|
||||
|
||||
namespace std { class type_info; };
|
||||
|
||||
@ -12,6 +13,7 @@ namespace ExplicitCapture {
|
||||
|
||||
void ImplicitThisCapture() {
|
||||
[](){(void)Member;}; // expected-error {{'this' cannot be implicitly captured in this context}}
|
||||
const int var = [](){(void)Member; return 0;}(); // expected-error {{'this' cannot be implicitly captured in this context}}
|
||||
[&](){(void)Member;};
|
||||
|
||||
[this](){(void)Member;};
|
||||
@ -105,7 +107,7 @@ namespace SpecialMembers {
|
||||
a = static_cast<decltype(a)&&>(a); // expected-error {{copy assignment operator is implicitly deleted}}
|
||||
}
|
||||
struct P {
|
||||
P(const P&) = delete; // expected-note 2{{deleted here}}
|
||||
P(const P&) = delete; //expected-note {{deleted here}} // expected-cxx14-note {{deleted here}}
|
||||
};
|
||||
struct Q {
|
||||
~Q() = delete; // expected-note {{deleted here}}
|
||||
@ -118,8 +120,8 @@ namespace SpecialMembers {
|
||||
};
|
||||
void g(P &p, Q &q, R &r) {
|
||||
// FIXME: The note attached to the second error here is just amazingly bad.
|
||||
auto pp = [p]{}; // expected-error {{deleted constructor}} expected-error {{deleted copy constructor of '(lambda}}
|
||||
// expected-note@-1 {{copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor}}
|
||||
auto pp = [p]{}; // expected-error {{deleted constructor}} expected-cxx14-error {{deleted copy constructor of '(lambda}}
|
||||
// expected-cxx14-note@-1 {{copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor}}
|
||||
auto qq = [q]{}; // expected-error {{deleted function}} expected-note {{because}}
|
||||
|
||||
auto a = [r]{}; // expected-note 2{{here}}
|
||||
@ -365,7 +367,7 @@ namespace PR18128 {
|
||||
int (*f())[true ? 1 : ([=]{ return n; }(), 0)];
|
||||
// expected-error@-1 {{non-local lambda expression cannot have a capture-default}}
|
||||
// expected-error@-2 {{invalid use of non-static data member 'n'}}
|
||||
// expected-error@-3 {{a lambda expression may not appear inside of a constant expression}}
|
||||
// expected-cxx14-error@-3 {{a lambda expression may not appear inside of a constant expression}}
|
||||
int g(int k = ([=]{ return n; }(), 0));
|
||||
// expected-error@-1 {{non-local lambda expression cannot have a capture-default}}
|
||||
// expected-error@-2 {{invalid use of non-static data member 'n'}}
|
||||
@ -596,8 +598,13 @@ namespace ConversionOperatorDoesNotHaveDeducedReturnType {
|
||||
using ExpectedTypeU = void (*)(T&);
|
||||
|
||||
struct X {
|
||||
#if __cplusplus > 201402L
|
||||
friend constexpr auto T::operator()(int) const;
|
||||
friend constexpr T::operator ExpectedTypeT() const noexcept;
|
||||
#else
|
||||
friend auto T::operator()(int) const;
|
||||
friend T::operator ExpectedTypeT() const;
|
||||
#endif
|
||||
|
||||
// FIXME: The first of these should match. The second should not.
|
||||
template<typename T>
|
||||
|
Loading…
Reference in New Issue
Block a user