diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -51,6 +51,10 @@ return TT->getDecl(); if (const auto *UT = dyn_cast(Base)) return UT->getFoundDecl(); + // Don't consider the underlying type of the decltype as a use (generally + // the argument of decltype should provide them). + if (const auto *DT = dyn_cast(Base)) + return nullptr; // A heuristic: to resolve a template type to **only** its template name. // We're only using this method for the base type of MemberExpr, in general // the template provides the member, and the critical case `unique_ptr` diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp --- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp @@ -229,6 +229,7 @@ namespace ns { template struct Foo { int a; }; } using ns::$implicit^Foo;)cpp", "void k(Foo b) { b.^a; }"); + testWalk("struct Foo { int a; };", "void test(decltype(Foo()) b) { b.^a; }"); // Test the dependent-type case (CXXDependentScopeMemberExpr) testWalk("template struct $implicit^Base { void method(); };", "template void k(Base t) { t.^method(); }");