Author: Kadir Cetinkaya Date: 2023-04-03T15:49:28+02:00 New Revision: 26ff268b80c589fd9f71c1c214af77cd972642ca
URL: https://github.com/llvm/llvm-project/commit/26ff268b80c589fd9f71c1c214af77cd972642ca DIFF: https://github.com/llvm/llvm-project/commit/26ff268b80c589fd9f71c1c214af77cd972642ca.diff LOG: [include-cleaner] Report references to operator calls as implicit Missing these references can result in false negatives in the used-ness analysis and break builds. Differential Revision: https://reviews.llvm.org/D147144 Added: Modified: clang-tools-extra/include-cleaner/lib/WalkAST.cpp clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp index b10c722b6653a..8a1dd77176cdf 100644 --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -91,14 +91,23 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> { public: ASTWalker(DeclCallback Callback) : Callback(Callback) {} + // Operators are almost always ADL extension points and by design references + // to them doesn't count as uses (generally the type should provide them, so + // ignore them). + // Unless we're using an operator defined as a member, in such cases treat + // this as a regular reference. bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *S) { if (!WalkUpFromCXXOperatorCallExpr(S)) return false; - - // Operators are always ADL extension points, by design references to them - // doesn't count as uses (generally the type should provide them). - // Don't traverse the callee. - + if (auto *CD = S->getCalleeDecl()) { + if (llvm::isa<CXXMethodDecl>(CD)) { + // Treat this as a regular member reference. + report(S->getOperatorLoc(), getMemberProvider(S->getArg(0)->getType())); + } else { + report(S->getOperatorLoc(), llvm::dyn_cast<NamedDecl>(CD), + RefType::Implicit); + } + } for (auto *Arg : S->arguments()) if (!TraverseStmt(Arg)) return false; diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp index fd6c6da9d5509..fceec670076c9 100644 --- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp @@ -291,13 +291,18 @@ TEST(WalkAST, ConstructExprs) { } TEST(WalkAST, Operator) { - // References to operators are not counted as uses. - testWalk("struct string {}; int operator+(string, string);", - "int k = string() ^+ string();"); - testWalk("struct string {int operator+(string); }; ", - "int k = string() ^+ string();"); - testWalk("struct string { friend int operator+(string, string); }; ", + // Operator calls are marked as implicit references as they're ADL-used and + // type should be providing them. + testWalk( + "struct string { friend int $implicit^operator+(string, string); }; ", + "int k = string() ^+ string();"); + // Unless they're members, we treat them as regular member expr calls. + testWalk("struct $explicit^string {int operator+(string); }; ", "int k = string() ^+ string();"); + // Make sure usage is attributed to the alias. + testWalk( + "struct string {int operator+(string); }; using $explicit^foo = string;", + "int k = foo() ^+ string();"); } TEST(WalkAST, VarDecls) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits