Downcasting an AST Type* to a more specific type is increasingly unsafe in the
AST. In general any Type* picked out of the AST might contain so-called 'sugar',
i.e. visible or invisible structure that does not change the identity of the
underlying type, but adds information.
After Clang 15f3cd6bfc670ba6106184a903eb04be059e5977, almost every Type is
wrapped in an ElaboratedType with kind ETK_None (i.e. "no elaboration").
ElaboratedType counts as sugar, and thus needs to be stripped off before we do
dynamic type checking of Type nodes.
The recommended way to look through sugar downwards in the tree is
'type->getAs<MostDerivedType>()', which will recursively remove sugar until a
node of MostDerivedType is reached. If there is no MostDerivedType node it
returns nullptr, so it's safe to consider getAs a desugaring dynamic downcast.
There are still some places where we use DynCastFrom or isa<> on Types, I have
only modified the ones that had any effect on broken testcases. Planning to look
into the rest separately once the test suite is working.
This fixes 4 broken testcases, and is an improvement towards fixing #1092.
Use the new IsElaboratedTypeSpecifier instead of node type-checking.
Just because an AST node is an ElaboratedType does not mean it's an
actual elaborated type specifier (which is what we care about here).
This fixes 10 broken testcases after Clang 15f3cd6bfc670ba6106184a903eb
wrapped every Type inside an ElaboratedType in the AST, but it is
strictly a bugfix in general: all elaborated type nodes are not type
specifiers.
Part of fix for #1092.
'Elaborated type specifier' is the formal term for 'struct X', 'class Y' or
'union Z'. Use it to avoid potential confusion around what 'elaboration node'
means.
Clean up a comment that claimed 'MostElaboratedAncestor' used
'IsElaborationNode', where it actually doesn't.
No functional change.
Vanilla PrintableType just prints the type name, on a declaration-like form.
But it's sometimes useful to see also what AST node the type comes from
(e.g. PointerType, ElaboratedType, RecordType), particularly when
investigating changes in the Clang AST.
Add a debug flag 'printtypeclass' to change type printing from e.g.:
struct IndirectClass
to:
ElaboratedType:struct IndirectClass
RecordType:struct IndirectClass
depending on the actual dynamic class of the AST type node.
Sometimes for debugging and testing, it helps to be able to tweak IWYU behavior
beyond the log verbosity.
Add a free-form --debug argument that takes a comma-separated list of flag
names. No validation is performed on these flags, they just serve as a global
switchboard to enable/disable custom behavior.
Note that these are not intended as a replacement for switches in general, just
as a support structure for quickly adding conditional debug behavior while
troubleshooting.
The IwyuBaseAstVisitor has a base class, BaseAstVisitor, but it only has a
small number of Visit functions implemented, for logging.
So there is no need to call Base::VisitX in general, only for the few with
an implementation that actually does something, and they are preserved
here.
This covers the common C pattern of declaring a typedef for a struct before the
struct itself, e.g.
typedef struct foo foo_t;
struct foo {
int value;
foo_t *next;
};
Fixes issue #1065.
Previously, it doesn't really check the need of including a file
with a type referred to by typedef from specialized template
'Container<Class>', because that file was reported due to declaration
of 'Pair' typedef. Now, it shows an error: Class1 full usage through
nested typedef or alias doesn't trigger full type requirement.
Some standard libraries require that any std::less<> specializations have a
const operator(). That seems hygienic anyway, so add a const qualifier.
Fixes the precomputed_tpl_args test on FreeBSD (and probably Mac).
Clang 9f57b65a272817752aa00e2fb94154e6eed1d0ec sometimes prints the 'final'
keyword twice for a declaration (tracking bug:
https://github.com/llvm/llvm-project/issues/56517).
This triggered several bugs in MungedForwardDeclareLineForTemplates:
* Only removed first 'final'
* Removed one character too many (sizeof(char[]) includes the trailing NUL)
Instead, replace all occurrences of 'final' and do it first so the stripping of
superclasses and body also get rid of trailing spaces. This should now work even
if the upstream bug is fixed.
I couldn't find an documentation about where it should be defined
(POSIX doesn't define it), so my best guess was to find the
definitions experimentally. Combining my findings in the glibc
repo with the findings in my own Debian system, and ignoring
kernel headers and unrelated headers such as X11's, this is my
best guess.
See:
alx@asus5775:/usr/include$ grepc -k MAXHOSTNAMELEN
./X11/Xtrans/Xtranssock.c:225:#define MAXHOSTNAMELEN 255
./asm-generic/param.h:17:#define MAXHOSTNAMELEN 64 /* max length of hostname */
./protocols/timed.h:44:#define MAXHOSTNAMELEN 64
./x86_64-linux-gnu/ruby-3.0.0/rb_mjit_min_header-3.0.4.h:24134:#define MAXHOSTNAMELEN 64
./x86_64-linux-gnu/sys/param.h:54:# define MAXHOSTNAMELEN HOST_NAME_MAX
alx@asus5775:~/src/gnu/glibc$ grepc -kx '\.h$' MAXHOSTNAMELEN
./inet/protocols/timed.h:44:#define MAXHOSTNAMELEN 64
./misc/sys/param.h:54:# define MAXHOSTNAMELEN HOST_NAME_MAX
./sunrpc/rpc/types.h:102:#define MAXHOSTNAMELEN 64
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
The reason is that
1) enumerators led to much noise in explanatory comments
(the idea is similar to cedf9d6984323a0a68847d), and
2) without this change, EnumClass::Item is reported separately
as fwd-decl use of EnumClass along with the full use
of EnumClass::Item.
Unnamed enums are an exception.
This is preparation for adding suggestions for enumeration opaque
(forward) declarations. Enums should be treated almost similar
to classes and structs, so clang::RecordDecl should be replaced
by clang::TagDecl, which is a superclass for RecordDecl and EnumDecl,
in many places.
We used to ignore all analysis of AST nodes inside a `typedef`, but that
caused us to miss author-intent analysis of nested typedefs.
Remove the special casing for member-of-typedef now that reporting as a
whole is less granular (we now report only the parent type instead of
all nested components).
Add test cases to demonstrate that nested typedefs observe
the author-intent rules.
In addition to C++ methods, silence reports of all declarations inside a
class (data members, types, etc.) if the parent type has already been
reported.
Non-template code only allows the null decl pointer to be ignored.
For instantiated templates, CanIgnoreDecl is quite sophisticated and uses a
set to ignore subtrees we've visited before, but it doesn't explicitly ignore
the null decl.
There are cases in templated code where the decl can be null as well -- most
prominently for builtin types.
With this test input:
$ cat t.cc
#include <algorithm>
#include <cassert>
#include <vector>
void f() {
std::vector<int> v;
assert(std::none_of(v.cbegin(), v.cend(),
[](auto value) { return value == 100; }));
}
$ include-what-you-use -stdlib=libc++ t.cc
(note the explicit use of libc++)
std::vector<int>::const_iterator collapses to a 'const int *', which has no
declaration, and so yields a null decl. Prior to this fix, that would lead to a
cast assertion or segfault attempting to cast the resulting null pointer to a
FunctionDecl in GetCanonicalUseLocation.
Add an assertion for non-null to GetCanonicalUseLocation to clarify that
null filtering must happen before canonicalizing the use-location.
I have not found a way to capture this in a reduced testcase.
Fixes#989.
In [=N] only N is a non-terminal, the = is a terminal and [] is neither.
When referring to another man page, only the name should be bold, not
the number in parentheses.
For referring to the example we don't need special fonts. The order and
naming of sections in a man page is standardized and examples are always
under this heading towards the end.
Update incidental use of htons(3) to use a private name to avoid influence of
the default mappings on test output.
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
Before, this would segfault attempting to print e.g. null decls.
These printers are predominantly used for logging, and it seems like a shame for
debug logging to crash on a null pointer if the code around it does not.
Remove now-unnecessary null-checks in logging.
Clang itself prints invalid locations as "<invalid loc>", which is better for
consistency with other tools, and easier to spot in logs as something out of the
ordinary.
This makes it possible to build IWYU as part of LLVM using the
LLVM_EXTERNAL_PROJECTS feature of the LLVM build system.
Add separate instructions for this build mode to README.
Based on original patch from @bc-lee:
https://github.com/include-what-you-use/include-what-you-use/pull/994
This is the same kind of activity as looking for LLVM/Clang packages, and
synthesizing targets, so let's do it up-front.
Move the compile-option setting together with the others.