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
`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.
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.
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.
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.
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
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.
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/'
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.
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.
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.
'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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
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.