(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) MODULE M3CharExprsToConsider; IMPORT AST, ASTWalk; IMPORT M3AST_AS, M3AST_PG; IMPORT M3AST_AS_F, M3AST_SM_F, M3AST_PG_F; IMPORT SeqM3AST_AS_EXP; IMPORT M3CStdProcs; IMPORT M3Error; IMPORT M3CharPreds; TYPE BitStack = REF RECORD head: AST.NODE; tail: BitStack END; (* head=NIL is where Es warnings should be skipped *) PROCEDURE Cons (head: AST.NODE; tail: BitStack): BitStack RAISES {} = BEGIN RETURN NEW(BitStack, head := head, tail := tail) END Cons; REVEAL Handle = Public BRANDED OBJECT consider, distant: BOOLEAN; inType : BitStack := NIL OVERRIDES callback := Node; END; PROCEDURE NewHandle (consider, distant: BOOLEAN): Handle RAISES {} = BEGIN RETURN NEW(Handle, consider := consider, distant := distant).init(); END NewHandle; PROCEDURE Node (h: Handle; n: AST.NODE; vm: ASTWalk.VisitMode) RAISES {} = PROCEDURE NoteUsedId (u: M3AST_AS.USED_ID) = VAR e: M3AST_PG.EXTERNAL_ID; d := u.sm_def; BEGIN IF d # NIL AND M3AST_PG.IsA_EXTERNAL_ID(d, e) THEN IF e # NIL AND e.pg_external # NIL THEN TYPECASE d OF | M3AST_AS.TYPED_ID (tid) => IF tid.sm_type_spec # NIL AND M3CharPreds.Tm(tid.sm_type_spec) THEN M3Error.WarnWithId( n, "Use of EXTERNAL Tm item %s", u.lx_symrep) END ELSE END END END; END NoteUsedId; BEGIN TYPECASE n OF | M3AST_AS.Subrange_type, M3AST_AS.Packed_type => CASE vm OF | ASTWalk.VisitMode.Entry => h.inType := Cons(NIL, h.inType); | ASTWalk.VisitMode.Exit => IF h.inType # NIL AND h.inType.head = NIL THEN h.inType := h.inType.tail ELSE M3Error.Report(n, "inType broken") END (*if*); END (*case*); | M3AST_AS.TYPE_SPEC => CASE vm OF | ASTWalk.VisitMode.Entry => IF h.inType # NIL AND h.inType.head = NIL THEN h.inType := Cons(n, h.inType) END; | ASTWalk.VisitMode.Exit => IF h.inType # NIL AND h.inType.head = n THEN h.inType := h.inType.tail END; END (*case*); ELSE END (*typecase*); IF vm = ASTWalk.VisitMode.Entry THEN TYPECASE n OF | M3AST_AS.Exp_used_id (u) => NoteUsedId(u.vUSED_ID); | M3AST_AS.USED_ID (u) => NoteUsedId(u); | M3AST_AS.Call (call) => VAR st_call: M3CStdProcs.T; ta, tb : M3AST_AS.EXP; tat : M3AST_AS.TYPE_SPEC; PROCEDURE Grade (ts: M3AST_AS.TYPE_SPEC): M3CharPreds.Char_Grade = VAR g: M3CharPreds.Char_Grade; BEGIN IF h.consider AND NOT h.distant THEN IF M3CharPreds.TC(ts, M3CharPreds.Ts) THEN RETURN M3CharPreds.Char_Grade.TcTs ELSE RETURN M3CharPreds.Char_Grade.No END END; g := M3CharPreds.Grade(ts); IF g = M3CharPreds.Char_Grade.TcTs AND NOT h.consider THEN g := M3CharPreds.Char_Grade.No END; RETURN g; END Grade; BEGIN IF NOT (h.inType # NIL AND h.inType.head = NIL) THEN IF M3CharPreds.Es(call) THEN M3Error.Warn(call, "Expr depends on NUM(CHAR)") END; END; IF M3CStdProcs.IsStandardCall(call, st_call) THEN ta := SeqM3AST_AS_EXP.First(call.sm_actual_s); tat := ta.sm_exp_type_spec; CASE st_call OF | M3CStdProcs.T.Subarray => IF M3CharPreds.Tr(tat) THEN M3Error.Warn( call, "SUBARRAY of a changing array"); END; | M3CStdProcs.T.Ord => IF ta.sm_exp_value = NIL AND M3CharPreds.Tn(tat) THEN M3Error.Warn( call, "ORD(var in NUM(CHAR)-dependent type)"); END; | M3CStdProcs.T.Val => tb := SeqM3AST_AS_EXP.Ith(call.sm_actual_s, 1); IF M3CharPreds.Tn(tb.sm_exp_type_spec) THEN M3Error.Warn( call, "VAL(..., NUM(CHAR)-dependent type)"); END; | M3CStdProcs.T.Loophole => CASE Grade(tat) OF | M3CharPreds.Char_Grade.No => | M3CharPreds.Char_Grade.Td => M3Error.Warn( call, "LOOPHOLE from a type related to CHAR"); | M3CharPreds.Char_Grade.TcTs => M3Error.Warn( call, "LOOPHOLE from a CHAR-size-dependent type"); END (*case*); tb := SeqM3AST_AS_EXP.Ith(call.sm_actual_s, 1); CASE Grade(tb.sm_exp_type_spec) OF | M3CharPreds.Char_Grade.No => | M3CharPreds.Char_Grade.Td => M3Error.Warn( call, "LOOPHOLE to a type related to CHAR"); | M3CharPreds.Char_Grade.TcTs => M3Error.Warn( call, "LOOPHOLE to a CHAR-size-dependent type"); END (*case*); | M3CStdProcs.T.Adr => CASE Grade(tat) OF | M3CharPreds.Char_Grade.No => | M3CharPreds.Char_Grade.Td => M3Error.Warn( call, "ADR of a type related to CHAR"); | M3CharPreds.Char_Grade.TcTs => M3Error.Warn( call, "ADR of a CHAR-size-dependent type"); END (*case*); ELSE END; END; END; ELSE END (* typecase *); END (* if *); END Node; BEGIN END M3CharExprsToConsider.