Commit Graph

1189 Commits

Author SHA1 Message Date
Boleyn Su 6f772242cf Add mapping of bits/utility.h for gcc.stl.headers 2022-09-01 19:50:08 +02:00
Alejandro Colomar 75623bce3b Fix mapping for <bits/syscall.h>
SYS_xxx macros, which are implemented in glibc in
<bits/syscall.h>, are intended to be included from
<sys/syscall.h>.  See syscall(2), amd also see the following:

$ grepc -k 'SYS_[a-z]\w+' /usr/include | head
/usr/include/x86_64-linux-gnu/bits/syscall.h:35:# define SYS_accept __NR_accept
/usr/include/x86_64-linux-gnu/bits/syscall.h:39:# define SYS_accept4 __NR_accept4
/usr/include/x86_64-linux-gnu/bits/syscall.h:43:# define SYS_access __NR_access
/usr/include/x86_64-linux-gnu/bits/syscall.h:47:# define SYS_acct __NR_acct
/usr/include/x86_64-linux-gnu/bits/syscall.h:51:# define SYS_acl_get __NR_acl_get
/usr/include/x86_64-linux-gnu/bits/syscall.h:55:# define SYS_acl_set __NR_acl_set
/usr/include/x86_64-linux-gnu/bits/syscall.h:59:# define SYS_add_key __NR_add_key
/usr/include/x86_64-linux-gnu/bits/syscall.h:63:# define SYS_adjtimex __NR_adjtimex
/usr/include/x86_64-linux-gnu/bits/syscall.h:67:# define SYS_afs_syscall __NR_afs_syscall
/usr/include/x86_64-linux-gnu/bits/syscall.h:71:# define SYS_alarm __NR_alarm
$ grep -rn bits/syscall.h /usr/include
/usr/include/x86_64-linux-gnu/bits/syscall.h:5:# error "Never use <bits/syscall.h> directly; include <sys/syscall.h> instead."
/usr/include/x86_64-linux-gnu/sys/syscall.h:27:   programs expect the traditional form SYS_*.  <bits/syscall.h>
/usr/include/x86_64-linux-gnu/sys/syscall.h:29:#include <bits/syscall.h>

I removed duplicate mappings, and also removed the mapping for
<syscall.h>, which is an undocumented feature of glibc.  Portable
programs should stick to <sys/syscall.h> (and unportable ones
too, since there's no gain apart from those 4 bytes).

Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
2022-09-01 19:44:29 +02:00
Kim Gräsman 4ad1d428ff Refactor CanForwardDeclareType for better sugar tolerance
These changes have no effect on the current test suite, but there are
obvious weaknesses when sugared types are taken into account.

The way CanForwardDeclareType asks if the parent is-a particular AST
node type is generally unsound in the presence of sugar, such as
ElaboratedType, which may show up above any Type in the tree.

An example:

  class C {};
  typedef C FooBar;

produces:

  `-TypedefDecl 0x559e505c6e30
    `-ElaboratedType 0x559e505c6df0 'C' sugar
      `-RecordType 0x559e505c6cc0 'C'
        `-CXXRecord 0x559e505c6c30 'C'

If we were to call CanForwardDeclare for the type C, it would not
classify as part of a TypedefDecl, because its parent is-a
ElaboratedType.

Therefore, delay any parent type checking until we've rewinded the
current AST node using MostElaboratedAncestor (there's a case to be made
that we should add a more general MostSugaredAncestor to walk _up_ the
tree until a desugared node is reached, much the same way as Desugar
will walk _down_ the tree. But that's good idea for a separate project.)

This was inspired by Clang 15f3cd6bfc670ba6106184a903eb04be059e5977,
which wraps the majority of Type nodes in an additional ElaboratedType
node.
2022-08-31 22:30:12 +02:00
Kim Gräsman ce63c68ed2 [clang compat] Back up through sugar before parent type check
This is kind-of the inverse of desugaring -- walk up the ancestor chain until
we're at the most elaborated (should really be "sugared") ancestor. Then we can
make assumptions about parent types again.

Clang 15f3cd6bfc670ba6106184a903eb04be059e5977 made this necessary, because many
more type nodes are now wrapped in ElaboratedType, which breaks naive parent
type checking.
2022-08-31 22:24:54 +02:00
Kim Gräsman 18a331be38 [clang compat] Canonicalize template args before identity comparison
Clang 15f3cd6bfc670ba6106184a903eb04be059e5977 made this necessary, because many
more type nodes are now wrapped in ElaboratedType, which makes it more risky to
compare non-canonical types for identity.
2022-08-31 22:24:54 +02:00
Kim Gräsman ed7860fa6f [clang compat] Desugar types before author-intent analysis
We already did desugaring (or, historically, RemoveElaboration) before
insertion or lookup in responsibility maps -- e.g.
GetCallerResponsibleTypesForAutocast and
GetCallerResponsibleTypesForFnReturn -- in most cases.

Clang after 15f3cd6bfc670ba6106184a903eb04be059e5977 wraps many more
type nodes in ElaboratedType, so we need to be even more diligent about
this.
2022-08-31 22:24:54 +02:00
Kim Gräsman af050f9d44 Only desugar type once in IsClassType
Now that we're using Desugar, which handles null pointers, we can desugar once
and reuse the result for both type checks.
2022-08-31 22:16:16 +02:00
Kim Gräsman 45e8234da9 Remove double desugar and clarify comment
The mechanical replacements caused some strange end result for functions with
both RemoveSubstTemplateTypeParm and RemoveElaboration. Clarify.
2022-08-31 22:16:16 +02:00
Kim Gräsman 7fd6c9f798 Replace all uses of RemoveSubstTemplateTypeParm with Desugar
No visible functional change, but we now desugar more aggressively.

This patch is the result of:

  git grep -l "RemoveSubstTemplateTypeParm" | xargs sed -i -e 's/RemoveSubstTemplateTypeParam/Desugar/'
2022-08-31 22:16:16 +02:00
Kim Gräsman 77e9128cba Replace all uses of RemoveElaboration with Desugar
Desugar performs the same desugaring as RemoveElaboration, and more.

This patch is a straight:

  git grep -l "RemoveElaboration" | xargs sed -i -e 's/RemoveElaboration/Desugar/'

followed by a test cleanup in badinc.cc, where Desugar sees through more sugar
than RemoveElaboration, and actually produces better results.
2022-08-31 22:16:16 +02:00
Kim Gräsman 73845f5cf9 Add new Desugar utility function
Desugar is a primitive for removing sugar from a Type node until a non-sugar
Type is reached. Type::getAs<> has similar semantics, but it requires a known
end-state; Desugar keeps going until there's no more sugar left.

Clang already has a plethora of functionality for this, most notably
Type::getUnqualifiedType. But IWYU can't use it, because we don't consider
TypedefType and UsingType sugar -- they're critical to correct
analysis. Similarly we have a lot of special-casing around
TemplateSpecializationType (which is conditionally sugar in Clang).

So, Desugar has desugaring semantics, but stops at TypedefType, UsingType and
TemplateSpecializationType if they are seen before we run out of sugar.

This is designed to be used instead of Type::getAs<> when the target type isn't
known and we just want to shave off sugar.

The sugar types most commonly seen are ElaboratedType and
SubstTemplateTypeParmType, but there are likely others that will be handled
automagically here.
2022-08-31 22:16:16 +02:00
Kim Gräsman f0eb46972a Check for SubstTemplateTypeParmType before desugaring
RemovePointersAndReferencesAsWritten should be allowed to return a
desugared type, so typecheck for SubstTemplateTypeParmType on the type
before pointers/refs (and any sugar) have been removed.
2022-08-31 22:16:16 +02:00
Kim Gräsman 204ebafb22 [clang compat] Use getAs<> instead of dynamic cast for Types
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.
2022-08-28 16:55:43 +02:00
Kim Gräsman 78a4fe951a [clang compat] Use elaborated type specifier in CanForwardDeclareType
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.
2022-08-28 16:16:04 +02:00
Kim Gräsman 0be9166fe6 Rename IsElaborationNode to IsElaboratedTypeSpecifier
'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.
2022-08-28 16:16:04 +02:00
Kim Gräsman 941fc19785 Add 'printtypeclass' debug flag
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.
2022-08-28 14:58:49 +02:00
Kim Gräsman 4217b5a20e Add --debug argument for disposable debug flags
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.
2022-08-28 14:58:49 +02:00
Kim Gräsman e94a78b3a5 [cmake] Require C++17 as does LLVM 2022-08-28 14:52:23 +02:00
Kim Gräsman 39e45aa453 [ci] Work around missing libclang-16.so.1 2022-08-28 14:52:23 +02:00
Kim Gräsman 8e65d9cf4a [ci] Remove llvm-15 packaging workarounds
Snapshot packages are now llvm-16.
2022-08-09 22:47:36 +02:00
Alejandro Colomar 983fe5a8fb Add another mapping for NULL
POSIX defines NULL in <unistd.h> too.

Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
2022-08-01 20:10:27 +02:00
Kim Gräsman bfe1909a9c Remove fruitless Base::Visit calls
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.
2022-07-24 22:15:58 +02:00
Kim Gräsman d2d4d15d8d Allow forward-declaration of elaborated types in type decls
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.
2022-07-24 22:02:19 +02:00
Bolshakov 0f7a7aba8c Report aliased template parameter
Template-nested typedef can't be responsible for any parameter
of the template, because an exact type is known only on template
specialization.
2022-07-23 13:18:27 +02:00
Bolshakov e0ae900e84 Improve template typedef test
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.
2022-07-23 13:18:27 +02:00
Bolshakov 57b812bf35 Report C++20 concept declaration use 2022-07-23 10:31:48 +02:00
Bolshakov b46a96e5a6 Fix autocast to reference
CastExpr for constructor conversion is absent in the AST in such a case
2022-07-16 18:30:23 +02:00
Kim Gräsman bab51b55ab Mark std::less<> specializations in tests const
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).
2022-07-16 15:47:43 +02:00
Kim Gräsman 7ca0a75b85 [clang compat] Harden handling of 'final' specifier
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.
2022-07-16 15:43:31 +02:00
Alejandro Colomar 979002bf8e Add mappings for SIGABRT
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
2022-07-09 21:59:46 +02:00
Alejandro Colomar fdca99fcd2 Add mappings for 'struct iovec'
As recently documented in iovec(3type).

Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
2022-07-09 21:59:46 +02:00
Alejandro Colomar ec625ea9db Add mappings for 'MAP_POPULATE'
It's not in POSIX, so I found it experimentally.

$ grepc -k MAP_POPULATE
./asm-generic/mman-common.h:26:#define MAP_POPULATE		0x008000	/* populate (prefault) pagetables */
./x86_64-linux-gnu/bits/mman-map-flags-generic.h:34:# define MAP_POPULATE	0x08000		/* Populate (prefault) pagetables.  */

$ grep -r '<bits/mman-map-flags-generic.h>'
x86_64-linux-gnu/bits/mman.h:#include <bits/mman-map-flags-generic.h>
x86_64-linux-gnu/bits/mman-map-flags-generic.h:# error "Never use <bits/mman-map-flags-generic.h> directly; include <sys/mman.h> instead."

So glibc defines it in <sys/mman.h>.

$ grep -r '<asm-generic/mman-common.h>'
asm-generic/mman.h:#include <asm-generic/mman-common.h>
$ grep -r '<asm-generic/mman.h>'
x86_64-linux-gnu/asm/mman.h:#include <asm-generic/mman.h>
$ grep -r '<asm/mman.h>'
linux/mman.h:#include <asm/mman.h>

And the kernel in <linux/mman.h>.

Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
2022-07-09 21:59:46 +02:00
Alejandro Colomar a7d6088546 Add mappings for 'MAXHOSTNAMELEN'
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>
2022-07-09 21:59:46 +02:00
Alejandro Colomar 21d4c7d2df Add mappings for 'struct tm'
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
2022-07-09 21:59:46 +02:00
Bolshakov 4c0f396159 Tests on enum opaque declarations 2022-06-13 07:47:21 +02:00
Bolshakov 12d2c18fa6 Report enum type name instead of constant name
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.
2022-06-13 07:47:21 +02:00
Bolshakov fb41044b9f Suggest enumeration opaque declarations
Opaque (i.e., in fact, forward) declarations are allowed for scoped
enumerations and unscoped ones with underlying type explicitly
specified.
2022-06-13 07:47:21 +02:00
Bolshakov 799a8ef1b5 Replace RecordDecl by TagDecl
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.
2022-06-13 07:47:21 +02:00
Bolshakov 8e6c16dbb5 Maintenance: formatting 2022-05-28 22:54:19 +02:00
Bolshakov db69a0c4d3 Perform full analysis of typedef components
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.
2022-05-28 22:54:19 +02:00
Bolshakov 496d200ce0 Avoid double reporting of all class members
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.
2022-05-28 22:54:19 +02:00
Daniel Hannon 3f456f66c2 add --comment_style option with tests 2022-05-28 11:03:47 +02:00
Daniel Hannon 67942da411 clarify purpose of --update_comments in help screen and manpages 2022-05-28 11:03:40 +02:00
Kim Gräsman 1375e56503 Consider all null decls ignorable
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.
2022-05-27 18:11:55 +02:00
Aaron Puchert 5f38c0dd36 Minor improvements to man page formatting
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.
2022-05-27 14:57:31 +02:00
Kim Gräsman cb4d34477a [fix_includes] Recognize namespace aliases
... as different from Allman-style namespace definitions.

Fixes #1022.
2022-05-24 06:17:30 +02:00
Kim Gräsman da6064016e [ci] Add workaround for missing libMLIRSupportIndentedOstream.a 2022-05-22 12:23:03 +02:00
Alejandro Colomar fb7f8557a1 Add mappings for byteorder(3) functions
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>
2022-05-21 10:49:29 +02:00
Kim Gräsman 9dee4b779b Print space between pointer and decl
This avoids confusing log output like "0x00405028void x();".
2022-05-19 21:41:34 +02:00
Kim Gräsman 14551a7126 Allow printing of null AST entities
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.
2022-05-19 21:41:34 +02:00