This replaces numeric tag-based prefixes with the actual tag name.
While this means in general slightly larger trap files, it aids
debugging them for a human.
In the future we can make this conditional on some kind of trap debug
option, but for the moment it does not seem detrimental.
Firstly, this change reworks how inter-process races are resolved.
Moreover some responsability reorganization has led to merging
`TrapArena` and `TrapOutput` again into a `TrapDomain` class.
A `TargetFile` class is introduced, that is successfully created
only for the first process that starts processing a given trap output
file. From then on `TargetFile` simply wraps around `<<` stream
operations, dumping them to a temporary file. When `TargetFile::commit`
is called, the temporary file is moved on to the actual target trap
file.
Processes that lose the race can now just ignore the unneeded
extraction and go on, while previously all processes would carry out
all extractions overwriting each other at the end.
Some of the file system logic contained in `SwiftExtractor.cpp` has been
moved to this class, and two TODOs are solved:
* introducing a better inter process file collision avoidance strategy
* better error handling for trap output operations: if unable to write
to the trap file (or carry out other basic file operations), we just
abort.
The changes to `ExprVisitor` and `StmtVisitor` are due to wanting to
hide the raw `TrapDomain::createLabel` from them, and bring more
funcionality under the generic caching/dispatching mechanism.
Now `TypeRepr` is a final class in the AST, which is more or less just
a type with a location in code.
As the frontend does not provide a direct way to get a type from a
type representation, this information must be provided when fetching
the label of a type repr.
This meant:
* removing the type repr field from `EnumIsCaseExpr`: this is a virtual
AST node introduced in place of some kinds of `IsEpxr`. The type
repr is still available from the `ConditionalCheckedCastExpr` wrapped
by this virtual node, and we will rebuild the original `IsExpr` with
the IPA layer.
* some logic to get the type of keypath roots has been added to
`KeyPathExpr`. This was done to keep the `TypeRepr` to `Type` relation
total in the DB, but goes against the design of a dumb extractor. The
logic could be moved to QL in the future
* in the control flow library, `TypeRepr` children are now ignored. As
far as I can tell, there is no runtime evaluation going on in
`TypeRepr`s, so it does not make much sense to have control flow
through them.
Some fields of base classes pose some problems with diamond hierarchies,
and we don't use them any way as we are emitting them using directly
trap entries instead of structured C++ classes.
This introduces a `cpp_skip` pragma to skip generation of those fields
in structured generated C++ classes, and applies it to `is_unknown` and
`location`.
As `ASTMangler` crashes when called on `ModuleDecl`, we simply use
its name.
This might probably not work reliably in a scenario where multiple
modules are compiled with the same name (like `main`), but this is left
for future work. At the moment this cannot create DB inconsistencies.
The `getName` in `Type.qll` was issuing a warning in other generated
classes having a `getName` from a `name` property in `schema.yml`.
To fix the possible inconsistency, `diagnostic_name` is being renamed to
`name` in the schema. Despite the scary doc comment on
`swift::Type::getString` (namely `for use in diagnostics only`), that
seems to be the right generic naming mechanism for types, and it
coincides with the name we were extracting on types with an explicit
`name` property.
In case we find a case where `Type::getString` gives something wrong,
we can probably just patch it on that specific type class.
It turns out the threshold of 5 lines for stub modification detection
was too strict: in case of a long class name the QL formatter will put
the closing brace of the empty class definition on a new line, leading
to codegen fail with an error thinking the stub was modified.
On the other side of things, also adding a base to a stub class was not
being detected as a modification.
Now the modification test is slightly smarter. If the stub still marked
as generated and
* has more than 6 lines, or
* the contents does not match a regexp aproximation of a plain stub
then codegen will abort. The test will still avoid reading the whole
contents of all the stubs.
If one modifies a QL stub but forgets to remove the `// generated`
header comment, codegen will now abort with an error rather than
silently reverting the change.
This is based on the rough heuristic of just counting the lines. If any
change is done to the stub class, the number of lines is bound to be
5 or more.