From 01b597450f81fe475704e61349c84ecb7b5f7275 Mon Sep 17 00:00:00 2001 From: Virgile Prevosto <virgile.prevosto@m4x.org> Date: Mon, 12 Sep 2022 16:56:51 +0200 Subject: [PATCH] [kernel] AST diff can take into account enum tags depending on previous tags supports pattern such as ```c enum { TAG1 = 42, TAG2 = TAG1 << 3 }; ``` --- src/kernel_services/ast_queries/ast_diff.ml | 32 ++++++++++++++++----- tests/syntax/ast_diff_1.i | 5 +++- tests/syntax/ast_diff_2.i | 5 +++- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/kernel_services/ast_queries/ast_diff.ml b/src/kernel_services/ast_queries/ast_diff.ml index 7d7b9c041e1..ef9985a6b22 100644 --- a/src/kernel_services/ast_queries/ast_diff.ml +++ b/src/kernel_services/ast_queries/ast_diff.ml @@ -187,6 +187,12 @@ type is_same_env = We thus collect them in the environment. *) goto_targets: (stmt * stmt) list; + (* enum items are added collectively when the whole enuminfo is + found to be identical (or not). On the other hand, the + definition of an enumitem can refer to the previous ones in the + same enuminfo. We keep the list of previously visited tags here. + *) + enumitem: enumitem Cil_datatype.Enumitem.Map.t; } module type Correspondence_table = sig @@ -271,7 +277,8 @@ let empty_env = logic_type_info = Cil_datatype.Logic_type_info.Map.empty; logic_local_vars = Cil_datatype.Logic_var.Map.empty; logic_type_vars = Datatype.String.Map.empty; - goto_targets = [] + goto_targets = []; + enumitem = Cil_datatype.Enumitem.Map.empty; } let add_locals f f' env = @@ -915,9 +922,12 @@ and is_same_compinfo ci ci' env = is_same_opt (is_same_list is_same_fieldinfo) ci.cfields ci'.cfields env and is_same_enuminfo ei ei' env = - Cil_datatype.Attributes.equal ei.eattr ei'.eattr && - Ikind.equal ei.ekind ei'.ekind && - is_same_list is_same_enumitem ei.eitems ei'.eitems env + let res, _ = + (Cil_datatype.Attributes.equal ei.eattr ei'.eattr && + Ikind.equal ei.ekind ei'.ekind, env) &&& + is_same_list_env is_same_enumitem ei.eitems ei'.eitems + in + res and is_same_fieldinfo fi fi' env = (* we don't compare names: it's the order in which they appear in the @@ -927,7 +937,12 @@ and is_same_fieldinfo fi fi' env = is_same_opt (fun x y _ -> x = y) fi.fbitfield fi'.fbitfield env && Cil_datatype.Attributes.equal fi.fattr fi'.fattr -and is_same_enumitem ei ei' env = is_same_exp ei.eival ei'.eival env +and is_same_enumitem ei ei' env = + if is_same_exp ei.eival ei'.eival env then + true, + { env with enumitem = Cil_datatype.Enumitem.Map.add ei ei' env.enumitem } + else + false, env and is_same_formal (_,t,a) (_,t',a') env = is_same_type t t' env && Cil_datatype.Attributes.equal a a' @@ -1365,8 +1380,11 @@ and enumitem_correspondence ?loc ei env = | `Not_present -> `Not_present | `Same _ -> Enumitem.find ei in - try Enumitem.find ei with - | Not_found -> add ei + match Cil_datatype.Enumitem.Map.find_opt ei env.enumitem with + | Some ei' -> `Same ei' + | None -> + (try Enumitem.find ei with + | Not_found -> add ei) and gvar_correspondence ?loc vi env = let add vi = diff --git a/tests/syntax/ast_diff_1.i b/tests/syntax/ast_diff_1.i index 7b64586683d..623a7b7ba87 100644 --- a/tests/syntax/ast_diff_1.i +++ b/tests/syntax/ast_diff_1.i @@ -95,7 +95,10 @@ void with_goto_unchanged(int c) { L2: X++; } -enum e { t = 1 }; +enum e { + t = 1, + u = t + 2 +}; struct s { char c[t]; }; diff --git a/tests/syntax/ast_diff_2.i b/tests/syntax/ast_diff_2.i index 9ef726b37e4..b83f852c99d 100644 --- a/tests/syntax/ast_diff_2.i +++ b/tests/syntax/ast_diff_2.i @@ -88,7 +88,10 @@ void with_goto_unchanged(int c) { L2: X++; } -enum e { t = 1 }; +enum e { + t = 1, + u = t + 2 +}; struct s { char c[t]; }; -- GitLab