Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/xlint/lint1 lint: add quickstart documentation to th...
details: https://anonhg.NetBSD.org/src/rev/adc449bc68a2
branches: trunk
changeset: 365177:adc449bc68a2
user: rillig <rillig%NetBSD.org@localhost>
date: Sun Apr 10 00:42:29 2022 +0000
description:
lint: add quickstart documentation to the implementation of lint
diffstat:
usr.bin/xlint/lint1/README.md | 139 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 139 insertions(+), 0 deletions(-)
diffs (143 lines):
diff -r 44b96b1a9ca6 -r adc449bc68a2 usr.bin/xlint/lint1/README.md
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/xlint/lint1/README.md Sun Apr 10 00:42:29 2022 +0000
@@ -0,0 +1,139 @@
+[//]: # ($NetBSD: README.md,v 1.1 2022/04/10 00:42:29 rillig Exp $)
+
+# Introduction
+
+To learn how a specific message is triggered, read the corresponding unit
+test in `tests/usr.bin/xlint/lint1/msg_???.c`.
+
+# Features
+
+## Type checking
+
+Lint has stricter type checking than most C compilers.
+It warns about type conversions that may result in alignment problems,
+see the test `msg_135.c` for examples.
+
+## Control flow analysis
+
+Lint roughly tracks the control flow inside a single function.
+It doesn't follow `goto` statements though.
+See the test `msg_193.c` for examples.
+
+## Error handling
+
+Lint tries to continue parsing and checking even after seeing errors.
+This part of lint is not robust though, so expect some crashes here,
+as variables may not be properly initialized or be null pointers.
+
+# Fundamental types
+
+Lint mainly analyzes expressions (`tnode_t`), which are formed from operators
+(`op_t`) and their operands (`tnode_t`).
+Each node has a type (`type_t`) and a few other properties.
+
+## type_t
+
+The basic types are `int`, `_Bool`, `unsigned long`, and so on.
+A basic type is created by `gettyp(INT)`.
+Derived types are created by `block_derive_pointer`,
+`block_derive_array` and `block_derive_function`.
+(See [below](#memory-management) for the meaning of the prefix `block_`.)
+
+After a type has been created, it should not be modified anymore.
+Ideally all references to types would be `const`, but that's a lot of work.
+Until that is implemented, before modifying a type,
+it needs to be copied using `block_dup_type` or `expr_dup_type`.
+
+## tnode_t
+
+When lint parses an expressions,
+it builds a tree of nodes representing the AST.
+Each node has an operator, which defines which other members may be accessed.
+The operators and their properties are defined in `ops.def`.
+Some examples for operators:
+
+| Operator | Meaning |
+|----------|---------------------------------------------------------|
+| CON | compile-time constant in `tn_val` |
+| NAME | references the identifier in `tn_sym` |
+| UPLUS | the unary operator `+tn_left` |
+| PLUS | the binary operator `tn_left + tn_right` |
+| CALL | a function call, typically CALL(LOAD(NAME("function"))) |
+| CVT | an implicit conversion or an explicit cast |
+
+## sym_t
+
+There is a single symbol table (`symtab`) for the whole translation unit.
+This means that the same identifier may appear multiple times.
+To distinguish the identifiers, each symbol has a block level.
+Symbols from inner scopes are added to the beginning of the table,
+so they are found first when looking for the identifier.
+
+# Memory management
+
+## Block scope
+
+The memory that is allocated by the `block_*_alloc` functions is freed at the
+end of analyzing the block, that is, after the closing `}`.
+See `compound_statement_rbrace:` in `cgram.y`.
+
+## Expression scope
+
+The memory that is allocated by the `expr_*_alloc` functions is freed at the
+end of analyzing the expression.
+See `expr_free_all`.
+
+# Null pointers
+
+* Expressions can be null.
+ * This typically happens in case of syntax errors or other errors.
+* The subtype of a pointer, array or function is never null.
+
+# Common variable names
+
+| Name | Type | Meaning |
+|------|-----------|------------------------------------------------------|
+| t | `tspec_t` | a simple type such as `INT`, `FUNC`, `PTR` |
+| tp | `type_t` | a complete type such as `pointer to array[3] of int` |
+| stp | `type_t` | the subtype of a pointer, array or function |
+| tn | `tnode_t` | a tree node, mostly used for expressions |
+| op | `op_t` | an operator used in an expression |
+| ln | `tnode_t` | the left-hand side operand of a binary operator |
+| rn | `tnode_t` | the right-hand side operand of a binary operator |
+| sym | `sym_t` | a symbol from the symbol table |
+
+# Abbreviations
+
+| Abbr | Expanded |
+|------|----------|
+| l | left |
+| r | right |
+| st | subtype |
+| op | operator |
+
+# Tests
+
+The tests are in `tests/usr.bin/xlint`.
+By default, each test is run with the lint flags `-g` for GNU mode,
+`-S` for C99 mode and `-w` to report warnings as errors.
+
+Each test can override the lint flags using comments of the following forms:
+* `/* lint1-flags: -tw */` replaces the default flags.
+* `/* lint1-extra-flags: -p */` adds to the default flags.
+
+Most tests check the diagnostics that lint generates.
+They do this by placing `expect` comments near the location of the diagnostic.
+The comment `/* expect+1: ... */` expects a diagnostic to be generated for the
+code 1 line below, `/* expect-5: ... */` expects a diagnostic to be generated
+for the code 5 lines above.
+Each `expect` comment must be in a single line.
+There may be other code or comments in the same line.
+
+Each diagnostic has its own test `msg_???.c` that triggers the corresponding
+diagnostic.
+Most other tests focus on a single feature.
+
+## Adding a new test
+
+1. Run `make -C tests/usr.bin/xlint/lint1 add-test NAME=test_name`.
+2. Run `cvs commit distrib/sets/lists/tests/mi tests/usr.bin/xlint`.
Home |
Main Index |
Thread Index |
Old Index