Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
4811-Fix-compiler-crash-when-using-a-record-as-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 4811-Fix-compiler-crash-when-using-a-record-as-LC-filter.patch of Package erlang
From 70096d80493247a39de8b3810f28a67e4ebe149a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Thu, 24 Nov 2022 07:45:11 +0100 Subject: [PATCH] Fix compiler crash when using a record as LC filter Closes #6501 --- lib/stdlib/src/erl_expand_records.erl | 8 +++-- lib/stdlib/src/erl_lint.erl | 37 +++++++++++++------- lib/stdlib/test/erl_expand_records_SUITE.erl | 16 +++++++++ 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 83f21670c2..7715f7d458 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -30,6 +30,7 @@ vcount=0, % Variable counter calltype=#{}, % Call types records=#{}, % Record definitions + raw_records=[],% Raw record forms strict_ra=[], % strict record accesses checked_ra=[], % successfully accessed records dialyzer=false % Cached value of compile flag 'dialyzer' @@ -70,7 +71,8 @@ init_calltype_imports([], Ctype) -> Ctype. forms([{attribute,_,record,{Name,Defs}}=Attr | Fs], St0) -> NDefs = normalise_fields(Defs), - St = St0#exprec{records=maps:put(Name, NDefs, St0#exprec.records)}, + St = St0#exprec{records=maps:put(Name, NDefs, St0#exprec.records), + raw_records=[Attr | St0#exprec.raw_records]}, {Fs1, St1} = forms(Fs, St), {[Attr | Fs1], St1}; forms([{function,Anno,N,A,Cs0} | Fs0], St0) -> @@ -511,7 +513,7 @@ lc_tq(Anno, [{b_generate,AnnoG,P0,G0} | Qs0], St0) -> {P1,St2} = pattern(P0, St1), {Qs1,St3} = lc_tq(Anno, Qs0, St2), {[{b_generate,AnnoG,P1,G1} | Qs1],St3}; -lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype}=St0) -> +lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype,raw_records=Records}=St0) -> %% Allow record/2 and expand out as guard test. IsOverriden = fun(FA) -> case Calltype of @@ -520,7 +522,7 @@ lc_tq(Anno, [F0 | Qs0], #exprec{calltype=Calltype}=St0) -> _ -> false end end, - case erl_lint:is_guard_test(F0, [], IsOverriden) of + case erl_lint:is_guard_test(F0, Records, IsOverriden) of true -> {F1,St1} = guard_test(F0, St0), {Qs1,St2} = lc_tq(Anno, Qs0, St1), diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 7400e3c64d..b9b58d6576 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -2299,17 +2299,24 @@ is_guard_test(Expression, Forms) -> IsOverridden :: fun((fa()) -> boolean()). is_guard_test(Expression, Forms, IsOverridden) -> - RecordAttributes = [A || A = {attribute, _, record, _D} <- Forms], - is_guard_test1(set_file(Expression, "nofile"), RecordAttributes, IsOverridden). - -is_guard_test1(NoFileExpression, [], IsOverridden) -> - is_guard_test2(NoFileExpression, {maps:new(),IsOverridden}); -is_guard_test1(NoFileExpression, RecordAttributes, IsOverridden) -> - St0 = foldl(fun(Attr0, St1) -> - Attr = set_file(Attr0, "none"), - attribute_state(Attr, St1) - end, start(), RecordAttributes), - is_guard_test2(NoFileExpression, {St0#lint.records,IsOverridden}). + NoFileExpression = set_file(Expression, "nofile"), + + %% Unless the expression constructs a record, the record + %% definitions are not needed. Therefore, because there can be a + %% huge number of record definitions in the forms, delay + %% processing the forms until we'll know that the record + %% definitions are truly needed. + F = fun() -> + St = foldl(fun({attribute, _, record, _}=Attr0, St0) -> + Attr = set_file(Attr0, "none"), + attribute_state(Attr, St0); + (_, St0) -> + St0 + end, start(), Forms), + St#lint.records + end, + + is_guard_test2(NoFileExpression, {F,IsOverridden}). %% is_guard_test2(Expression, RecordDefs :: dict:dict()) -> boolean(). is_guard_test2({call,Anno,{atom,Ar,record},[E,A]}, Info) -> @@ -2347,7 +2354,13 @@ is_gexpr({record_index,_A,_Name,Field}, Info) -> is_gexpr(Field, Info); is_gexpr({record_field,_A,Rec,_Name,Field}, Info) -> is_gexpr_list([Rec,Field], Info); -is_gexpr({record,A,Name,Inits}, Info) -> +is_gexpr({record,A,Name,Inits}, Info0) -> + Info = case Info0 of + {#{},_} -> + Info0; + {F,IsOverridden} when is_function(F, 0) -> + {F(),IsOverridden} + end, is_gexpr_fields(Inits, A, Name, Info); is_gexpr({bin,_A,Fs}, Info) -> all(fun ({bin_element,_Anno,E,Sz,_Ts}) -> diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl index c48a1ac90e..ea5cc4a354 100644 --- a/lib/stdlib/test/erl_expand_records_SUITE.erl +++ b/lib/stdlib/test/erl_expand_records_SUITE.erl @@ -148,6 +148,22 @@ expr(Config) when is_list(Config) -> is_record(_, _, _) -> error(wrong_is_record). + ">>, + <<" + -record(foo, {bar = [Bar || Bar <- ?MODULE:id([]), size(Bar) > 0]}). + + t() -> + {'EXIT',{{bad_filter,{foo,[]}},[_|_]}} = catch gh6501a(whatever), + [whatever] = gh6501b(whatever), + ok. + + gh6501a(Bar) -> + [Bar || #foo{}]. + + gh6501b(Bar) -> + [Bar || is_tuple(#foo{})]. + + id(I) -> I. ">> ], -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor