Include-cleaner is a library that uses the clang AST and preprocessor to determine which headers are used. It will be used in clang-tidy, in clangd, in a standalone tool at least for testing, and in out-of-tree tools. Roughly, it walks the AST, finds referenced decls, maps these to used sourcelocations, then to FileEntrys, then matching these against #includes. However there are many wrinkles: dealing with macros, standard library symbols, umbrella headers, IWYU directives etc. It is not built on the C++20 modules concept of usage, to allow: - use with existing non-modules codebases - a flexible API embeddable in clang-tidy, clangd, and other tools - avoiding a chicken-and-egg problem where include cleanups are needed before modules can be adopted This library is based on existing functionality in clangd that provides an unused-include warning. However it has design changes: - it accommodates diagnosing missing includes too (this means tracking where references come from, not just the set of targets) - it more clearly separates the different mappings (symbol => location => header => include) for better testing - it handles special cases like standard library symbols and IWYU directives more elegantly by adding unified Location and Header types instead of side-tables - it will support some customization of policy where necessary (e.g. for style questions of what constitutes a use, or to allow both missing-include and unused-include modes to be conservative) This patch adds the basic directory structure under clang-tools-extra and a skeleton version of the AST traversal, which will be the central piece. A more end-to-end prototype is in https://reviews.llvm.org/D122677 RFC: https://discourse.llvm.org/t/rfc-lifting-include-cleaner-missing-unused-include-detection-out-of-clangd/61228 Differential Revision: https://reviews.llvm.org/D124164
48 lines
1.3 KiB
C++
48 lines
1.3 KiB
C++
//===--- WalkAST.cpp - Find declaration references in the AST -------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "AnalysisInternal.h"
|
|
#include "clang/AST/RecursiveASTVisitor.h"
|
|
|
|
namespace clang {
|
|
namespace include_cleaner {
|
|
namespace {
|
|
using DeclCallback = llvm::function_ref<void(SourceLocation, NamedDecl &)>;
|
|
|
|
class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
|
|
DeclCallback Callback;
|
|
|
|
void report(SourceLocation Loc, NamedDecl *ND) {
|
|
if (!ND || Loc.isInvalid())
|
|
return;
|
|
Callback(Loc, *cast<NamedDecl>(ND->getCanonicalDecl()));
|
|
}
|
|
|
|
public:
|
|
ASTWalker(DeclCallback Callback) : Callback(Callback) {}
|
|
|
|
bool VisitTagTypeLoc(TagTypeLoc TTL) {
|
|
report(TTL.getNameLoc(), TTL.getDecl());
|
|
return true;
|
|
}
|
|
|
|
bool VisitDeclRefExpr(DeclRefExpr *DRE) {
|
|
report(DRE->getLocation(), DRE->getFoundDecl());
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
void walkAST(Decl &Root, DeclCallback Callback) {
|
|
ASTWalker(Callback).TraverseDecl(&Root);
|
|
}
|
|
|
|
} // namespace include_cleaner
|
|
} // namespace clang
|