Commit Graph

115 Commits

Author SHA1 Message Date
Kim Gräsman 81ee985377 Ignore uses of declarations from inside of functions
Using type deduction, a function can define a local type and return it:

    auto func() {
      struct X {};
      return X();
    }

Before this change, IWYU would register X as a use for callers of func.

In certain situations (union inside lambda inside macro) this would lead
to a forward-declare use trying to format a forward-declaration of the
type local to the function in PrintForwardDeclare. This led to a crash
since the lambda was unnamed, but there's really no point trying to
forward-declare a type that is private to a function.

Generalize this so we ignore all uses of symbols declared inside a
function. In order to get in contact with that symbol, we must already
have access to the function, so the containing header must already be
included.

Fixes issue: 795
2023-01-22 20:35:42 +01:00
Bolshakov f7c5a795ab Desugar UsingType among others
`clang::UsingType` denotes a sugar type which is introduced by a using-
declaration (e.g., `using ns::SomeType;`). It has not such a special
meaning in IWYU as `TypedefType` or `TemplateSpecializationType`.

No functional change is expected.
2023-01-22 20:22:59 +01:00
Kim Gräsman 35effcf918 Add GetKindName AST util
The core AST nodes (Decl, Stmt, Type, TypeLoc) all have a kind denoting
their specific derived type, and a corresponding function to get a
printable string for the kind.

Implement a polymorphic GetKindName that calls the right function
depending on type, and also adds a suffix to mirror the clang class
name.

Make all uses of the get...Name functions call these wrappers instead.

No visible change intended.
2023-01-07 18:12:43 +01:00
Kim Gräsman b65c4b63a7 Format all lines with leading =
This is the unadorned output of:

    git grep -En "^\s*=" -- ':!tests/*' | grep-format

There are some examples with comments between the variable name and the
'=' that clang-format left unchanged.

No functional change.
2023-01-07 12:27:16 +01:00
Bolshakov c3bcb661f6 Handle sugared template specs in template args
Non-sugared template specialization type template arguments are already
analyzed due to 'TraverseType' call inside
'InstantiatedTemplateVisitor::TraverseSubstTemplateTypeParmTypeHelper'
and subsequent 'TraverseTemplateSpecializationTypeHelper' call.
Components of sugared template specialization types are added into
resugar_map, otherwise their template arguments would not be reported.
Test case has been extended.
2022-12-16 22:22:31 +01:00
Kim Gräsman 109fdb4cdd Revert "See through C++20 consteval for conversion functions"
A proper fix is now available in LLVM as of
https://github.com/llvm/llvm-project/commit/403d7d8d7093d6637a006f8b3f7538

This reverts commit 7d7fd80da7.
2022-11-01 19:18:17 +01:00
Daniel Hannon f20eadd206 [clang compat] Use TemplateSpecializationType ArrayRef APIS
clang 1acffe81ee9117691812b9bf8747c03354177d15 changed the API for
clang::TemplateSpecializationType to no longer have getArgs() or getNumArgs()
This change replaces them with template_args() and retains the previous logic
2022-10-30 20:29:59 +01: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 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 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 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
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 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
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
Kim Gräsman f8c76cf633 Remove special printing of invalid locations
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.
2022-05-19 21:41:34 +02:00
Kim Gräsman 5191af9e6c Clarify that Print... functions are intended for debugger use
Group them together and apart from Printable... functions.
2022-05-19 21:41:34 +02:00
Kim Gräsman 7d7fd80da7 See through C++20 consteval for conversion functions
When a consteval function is called, its call-expression is wrapped in a
ConstantExpr in the Clang AST. There's an upstream bug [1] where Clang
doesn't account for that when searching the AST for a cast-expression's
potential user-defined conversion function, leading to an assertion
failure or a crash.

Reimplement GetConversionFunction so it works in this case. This can
safely be reverted when the upstream bug is fixed.

[1] https://github.com/llvm/llvm-project/issues/53044
2022-02-27 20:40:05 +01:00
Kim Grasman c311760516 Improve detection of builtin functions
The technique used before relied on linear search of all builtins by
name. This did not work with qualified C++ names of C library names such
as std::pow and std::round.

Use ASTContext to get to BuiltinInfo, and in turn use that to check more
specific traits of the builtin by ID instead of name.

Add distinct tests for C and C++ to cover both <math.h> and <cmath>.

Fixes issue #776.
2021-06-05 11:13:26 +02:00
Alexey Storozhev 93cbdce97b Use SourceLocation::printToString 2021-04-25 17:18:22 +02:00
Alexey Storozhev 56d20af4c7 Delete unused using declarations 2020-11-28 16:32:50 +01:00
Kim Grasman fbffd6e3be Remove source manager from ASTNode constructor
ASTNode was consistently instantiated using GlobalSourceManager(). The
passed-in source manager was only used in ASTNode::GetLocation().

Use GlobalSourceManager() there directly instead to keep the constructor
interface simpler.

No functional change.
2020-09-22 20:18:35 +02:00
Kim Grasman 30549c6931 Implement Stmt printing with ASTDumper
The Clang API changed in commit 473fbc90d1fbf17e so that Stmt::dump
takes an ASTContext instead of a SourceManager.

Rather than wire a global ASTContext, reimplement PrintableStmt and
PrintStmt to duplicate the most trivial implementations not requiring
ASTContext.

No functional change.
2020-07-12 16:46:30 +02:00
John Bytheway df077d5c71 Expand more templates during visitation
In walking the AST there were various places where types were only
expanded if !CanIgnoreType.  But the criteria were wrong

The CanIgnoreType is suitable for determining whether a type was
reportable, but not whether it was expansion-worthy.

Add a new parameter to CanIgnoreType to distinguish the two use cases,
and pass it in a couple of cases.

Also, tweak the resugar map construction code.  Now it is capable of
handling template aliases as well as template classes and functions.

Add a new test that now passes with these changes.

This also resolves a couple of TODOs in an existing test, so update that
accordingly.
2020-07-05 12:28:47 +02:00
John Bytheway cb37578f8b Fix use of aliases of elaborated types.
The previous code to catch aliases of template parameters would not
catch the case where the template parameter was elaborated.  Walk past
the relevant ASTNodes to catch such cases.
2020-07-05 12:28:47 +02:00
John Bytheway b4838853e5 Remove trailing whitespace from source files 2020-05-24 14:14:59 +02:00
Kim Grasman a85cea1b30 Improve handling of placement new
Instead of 'IsDefaultNewOrDelete' which uses heuristics and string
parsing, use FunctionDecl::isReplaceableGlobalAllocationFunction from
the Clang API. It returns true for any replaceable allocation function,
which happens to coincide nicely with all allocation functions except
placement new.

Fixes #777 and improves behavior for the modern allocation functions:

- Sized deallocation in C++14
- Aligned allocation in C++17

This small improvement fixes a number of TODOs in the new placement_new
testcase, and makes it possible to add a testcase for implicit aligned
allocation in operator_new, as aligned allocation no longer requires
<new>.

Patch based on work and lots of good input from Adar Dembo.
2020-05-02 11:42:24 +02:00
John Bytheway b8682077c7 Fix handling of alias templates
When an alias template was used, IWYU would resolve it to the underlying
aliased type rather than the template for the purposes of determining
what header was required.  This led to incorrect header removals in some
cases.

Fix that by splitting the TypeToDeclAsWritten into two functions:
TypeToDeclAsWritten and TypeToDeclForContent.  The former is used for
determining uses of the Decl itself, the latter is used for determining
uses of the arguments passed to the template.
2020-03-22 20:43:11 +01:00
Kim Grasman a40a28740c Improve resugaring of function template argument types
Clang commit 3ced23976aa8a86a17017c87821c873b4ca80bc2 removed sugar from
ImplicitCastExprs in certain situations.

The sugar still seems to be available from the DeclRefExpr used for
function arguments, so use a RAV to find the first ImplicitCastExpr or
DeclRefExpr that provides a sugared type.

This loses one diagnostic in badinc.cc. I haven't been able to form a
story around why it disappears, but it doesn't look critically useful,
so I removed it.
2020-01-07 23:17:41 +01:00
Kim Grasman c193125761 Fix comment typo 2019-12-26 16:41:52 +01:00
Kim Grasman 7c2ec8f05b Rename port.h -> iwyu_port.h 2019-12-26 16:12:02 +01:00
Kim Grasman 613efed42e Disable forward-declares for decls in inline namespaces
Technically users can forward-declare inline namespaces, e.g.

  namespace std {
  inline namespace __1 {

  template <class T>
  struct hash;

  }
  }

but that would be both confusing and problematic:

1) The symbol is referred to as std::hash, but declared here with a name
   nobody should ever see.
2) When a new ABI version is added for std::hash, a new internal
   namespace -- e.g. __2 -- will be added, and std::hash and
   std::__1::hash no longer refer to the same symbol.

As inline namespaces are intended primarily as a versioning feature for
library authors, avoid trying to second-guess them and just require a
full use for any decl inside an inline namespace.

This fixes issue #713.
2019-11-09 16:23:08 +01:00
Kim Grasman 8b0e2bcec9 Let C structs be potential forward-declarations
Commit 0d0832fee7 accidentally constrained
IsForwardDecl to CXXRecordDecls, i.e. C++ structs/classes.

This led to forward-declarations being missed when source files were
parsed in C mode.

Issue #682 captures this nicely -- fix by allowing all RecordDecls to be
potential forward-declarations and add a test.
2019-11-03 21:31:06 +01:00
Kim Grasman effce1a37c Fix typo in comment
The synthetic filename "<built_in>" is actually spelled "<built-in>".

No functional change.
2019-03-18 21:20:32 +01:00
Kim Grasman 452aeefb6e Remove now-unused IsCastToReferenceType 2019-03-14 17:00:29 +01:00
John Bytheway 33b7ce7500 Refactor check for builtin function
Create a new function to test whether a decl is a builtin function.
2019-03-08 08:54:37 +01:00
Kim Grasman 155c3a5673 Remove now-unused function PrintableSourceRange 2019-01-19 11:13:41 +01:00
J.Ru 0d0832fee7 Treat explicit template instantiations as full uses
Teach IsFowardDecl() to not confuse an explicit template instantiation
with a forward declaration.

Also make sure to report explicit instantiations (declaration or
definition) as full uses during visitation.

Fixes #558
2018-12-07 09:12:01 +01:00
J.Ru 2a2d15cf8a Replace remaining dyn_cast_or_null with DynCastFrom 2018-08-11 16:39:58 +02:00
Kim Grasman 2406addcc7 Count free function definitions as uses
Now that we can provide context for uses with use flags, we can tweak
IWYU behavior when a function is being defined.

This allows us to treat a function definition as a use of all
previously-seen declarations.

Fixes #179, #491 and #441.
2018-03-09 20:37:52 +01:00
Kim Grasman aa2bc1f9e0 Replace in_cxx_method_body with an extensible use-flag
This makes it possible to pass more context information about a use
from the detection phase to later IWYU analysis phases.
2018-03-09 20:37:52 +01:00
Kim Grasman c182d6a45e Update to reflect changes in Clang
The utility methods for printing template argument lists moved from
static member functions to free functions in Clang r319178.

No functional change, as far as I can tell.

Fix issue #503.
2017-11-29 22:37:54 +01:00
Kim Grasman 3a921410f4 Pick up more sugar for function arguments
Type sugar (typedefs, more specifically) were previously lost for
arguments passed by value.

Introduce a new helper function to glean sugared type info from
ImplicitCastExpr nodes in the AST, as present in later revs of Clang.

Fixes a TODO in derived_function_tpl_args.
2017-02-21 10:43:48 +01:00
Kim Grasman 8065e52a31 Add optional terse flag to PrintableDecl
Make terse printing the default.
2017-02-21 10:40:54 +01:00
Volodymyr Sapsai 4e957bf33a Fix GetFirstClassArgument.
Check function parameters types instead of types of arguments at call
site. This way we are able to detect template substitutions for the
function itself, not for the caller.

PR https://github.com/include-what-you-use/include-what-you-use/pull/399
2017-01-28 16:52:02 -08:00