diff --git a/parsing_c/parse_c.ml b/parsing_c/parse_c.ml index b1b7c8f7c79f23a9dabfe166a552c9be49f7be77..94bd9f251630d4a2b64b290a4ce4b38672049227 100644 --- a/parsing_c/parse_c.ml +++ b/parsing_c/parse_c.ml @@ -1102,7 +1102,10 @@ and _parse_print_error_heuristic2bis saved_typedefs saved_macros if parse_strings then Parsing_hacks.fix_tokens_strings toks else toks in - + let toks = + if !Flag.c_plus_plus <> Flag.Off + then Parsing_hacks.c_plus_plus_operator toks + else toks in let tr = mk_tokens_state toks in diff --git a/parsing_c/parser_c.mly b/parsing_c/parser_c.mly index 5431ff9115c560467f1b77f42091e70450f0178b..949c0bfcf610409176d259432d8e133e7ca3be17 100644 --- a/parsing_c/parser_c.mly +++ b/parsing_c/parser_c.mly @@ -793,6 +793,8 @@ cond_expr: { $1 } | arith_expr TWhy gcc_opt_expr TDotDot cond_expr { mk_e (CondExpr ($1,$3,$5)) [$2;$4] } + | Tnew new_argument { mk_e(New (None, $2)) [$1] } + | Tnew TOPar argument_list_ne TCPar new_argument { mk_e(New (Some $3, $5)) [$1; $2; $4] } arith_expr: @@ -839,8 +841,6 @@ unary_expr: match (fst $3) with (* warn about dropped attributes *) [] -> ret | _ -> warning "attributes found in sizeof(...), dropping" ret } - | Tnew new_argument { mk_e(New (None, $2)) [$1] } - | Tnew TOPar argument_list_ne TCPar new_argument { mk_e(New (Some $3, $5)) [$1; $2; $4] } | Tdelete cast_expr { mk_e(Delete(false, $2)) [$1] } | Tdelete TOCro TCCro cast_expr { mk_e(Delete(true, $4)) [$1;$2;$3] } | Tdefined identifier_cpp { mk_e(Defined $2) [$1] } @@ -860,9 +860,16 @@ new_argument: | TypedefIdent TOPar TCPar { let fn = mk_e(Ident (RegularName (mk_string_wrap $1))) [] in Left (mk_e(FunCall (fn, [])) [$2;$3]) } - | type_spec + | type_spec muls { let ty = addTypeD ($1,nullDecl) in let ((returnType,hasreg), iihasreg) = fixDeclSpecForParam ty in + let returnType = + let rec loop = function + [] -> returnType + | mul::muls -> + let res = loop muls in + mk_ty (Pointer res) [mul] in + loop (List.rev $2) in Right (ArgType { p_namei = None; p_type = returnType; p_register = hasreg, iihasreg; p_attr = []; p_midattr = []; p_endattr = []; @@ -879,6 +886,10 @@ new_argument: | _ -> raise (Impossible 88) } +muls: + {[]} + | muls TMul { $1@[$2] } + unary_op: | TAnd { GetRef, $1 } | TMul { DeRef, $1 } diff --git a/parsing_c/parsing_hacks.ml b/parsing_c/parsing_hacks.ml index 2ec3bc283b44b6da4c6c4faa04733fb11be9d192..d169ca9594c15a6f50c46746adf64667301768dc 100644 --- a/parsing_c/parsing_hacks.ml +++ b/parsing_c/parsing_hacks.ml @@ -2978,3 +2978,72 @@ let cpp_ifdef_statementize (ast :toplevel list) :toplevel list = aux xs ); } ast + +(* ----------------------------------------------------------------------- *) +(* Changes specific to C++ *) + +(* The following needs to be a separate pass because we convert two tokens into one *) +(* Can't hack the lexer because we don't want "operator" to become unusable by C code *) +exception No_operator +let c_plus_plus_operator toks = + let opinfo start = function + TPlus i | TMinus i | TMul i | TDiv i | TShl i | TShr i + | TOrLog i | TAndLog i | TOr i | TXor i | TAnd i | TEqEq i | TNotEq i + | TInf i | TSup i | TInfEq i | TSupEq i -> + let opstart = Ast_c.pos_of_info i in + if start + (String.length "operator") = opstart + then Some (Ast_c.str_of_info i,i) (* no space allowed *) + else None + | _ -> None in + let mergei i1 i2 = + let pinfo1 = i1.pinfo in + let cocci_tag1 = i1.cocci_tag in + let comments_tag1 = i1.comments_tag in + let annots_tag1 = i1.annots_tag in + let danger1 = i1.danger in + let pinfo2 = i2.pinfo in + let comments_tag2 = i2.comments_tag in + let annots_tag2 = i2.annots_tag in + if !comments_tag1.mafter = [] && !comments_tag2.mbefore = [] + then + let merged_pinfo = + match (pinfo1,pinfo2) with + (OriginTok pi1,OriginTok pi2) -> + Some (OriginTok { pi1 with str = pi1.str ^ pi2.str }) + | (ExpandedTok(pi1,v1),ExpandedTok(pi2,v2)) -> + let (vpi1,o1) = v1 in + let (vpi2, _) = v2 in + Some (ExpandedTok ({ pi1 with str = pi1.str ^ pi2.str }, + ({ vpi1 with str = vpi1.str ^ vpi2.str }, o1))) + | _ -> None in + match merged_pinfo with + None -> None + | Some merged_pinfo -> + let merged_cocci_tag = cocci_tag1 in + let merged_comments_tag = + ref + { mbefore = !comments_tag1.mbefore; + mafter = !comments_tag2.mafter; + mbefore2 = !comments_tag1.mbefore2; + mafter2 = !comments_tag2.mafter2 } in + let merged_annots_tag = + Token_annot.append_annots annots_tag1 annots_tag2 in + let merged_danger = danger1 in + Some { pinfo = merged_pinfo; cocci_tag = merged_cocci_tag; + comments_tag = merged_comments_tag; annots_tag = merged_annots_tag; + danger = merged_danger } + else None in + let rec loop changed acc = function + [] -> if changed then List.rev acc else raise No_operator + | ((TIdent("operator",i1)) as a) :: op :: rest -> + (match opinfo (Ast_c.pos_of_info i1) op with + Some (ops,i2) -> + let news = Printf.sprintf "operator%s" ops in + (match mergei i1 i2 with + Some newi -> + loop true ((TIdent(news,newi)) :: acc) rest + | None -> loop changed (a :: acc) (op::rest)) + | _ -> loop changed (a :: acc) (op::rest)) + | x :: xs -> loop changed (x :: acc) xs in + try loop false [] toks + with No_operator -> toks diff --git a/parsing_c/parsing_hacks.mli b/parsing_c/parsing_hacks.mli index 74d37b9547391dbd4f1d3237e80290b32dcb9a81..b0fb24fa7cdcbabb5c61d444f8f55195326cfc9b 100644 --- a/parsing_c/parsing_hacks.mli +++ b/parsing_c/parsing_hacks.mli @@ -90,3 +90,5 @@ val tokens_include: (* #ifdef *) val cpp_ifdef_statementize: Ast_c.program -> Ast_c.program + +val c_plus_plus_operator : Parser_c.token list -> Parser_c.token list diff --git a/parsing_c/token_annot.ml b/parsing_c/token_annot.ml index a879f64fa5a3e3a03f1cdf2ca50793adfeebc1df..117f81751672296d3068df989a4deac408fe6bd3 100644 --- a/parsing_c/token_annot.ml +++ b/parsing_c/token_annot.ml @@ -28,3 +28,5 @@ let get_annot anns key = let put_annot key value anns = (key, value) :: anns + +let append_annots a1 a2 = a1 @ a2 diff --git a/parsing_c/token_annot.mli b/parsing_c/token_annot.mli index ad78f1bd01bb225615565cd7c03a5d82ea424f3a..733a33dfce62b69a40bb2e7d944d3ebb05748616 100644 --- a/parsing_c/token_annot.mli +++ b/parsing_c/token_annot.mli @@ -10,3 +10,4 @@ type annots val empty : annots val get_annot : annots -> annot_key -> annot_val option val put_annot : annot_key -> annot_val -> annots -> annots +val append_annots : annots -> annots -> annots