diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index e8309c68b7fca..cad6b456fc268 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -117,6 +117,7 @@ clang_target_link_libraries(clangTidyBugproneModule clangASTMatchers clangBasic clangLex + clangSema clangTooling clangTransformer ) diff --git a/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp index 2bce72cca98c6..a1d7b9931e419 100644 --- a/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" +#include "clang/Sema/HeuristicResolver.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" @@ -125,8 +126,8 @@ void StandaloneEmptyCheck::check(const MatchFinder::MatchResult &Result) { DeclarationName Name = Context.DeclarationNames.getIdentifier(&Context.Idents.get("clear")); - auto Candidates = MemberCall->getRecordDecl()->lookupDependentName( - Name, [](const NamedDecl *ND) { + auto Candidates = HeuristicResolver(Context).lookupDependentName( + MemberCall->getRecordDecl(), Name, [](const NamedDecl *ND) { return isa(ND) && llvm::cast(ND)->getMinRequiredArguments() == 0 && @@ -174,8 +175,8 @@ void StandaloneEmptyCheck::check(const MatchFinder::MatchResult &Result) { DeclarationName Name = Context.DeclarationNames.getIdentifier(&Context.Idents.get("clear")); - auto Candidates = - ArgRecordDecl->lookupDependentName(Name, [](const NamedDecl *ND) { + auto Candidates = HeuristicResolver(Context).lookupDependentName( + ArgRecordDecl, Name, [](const NamedDecl *ND) { return isa(ND) && llvm::cast(ND)->getMinRequiredArguments() == 0 && diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 266b93a64a390..dbd02ef7f8011 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1720,14 +1720,6 @@ class CXXRecordDecl : public RecordDecl { /// static analysis, or similar. bool hasMemberName(DeclarationName N) const; - /// Performs an imprecise lookup of a dependent name in this class. - /// - /// This function does not follow strict semantic rules and should be used - /// only when lookup rules can be relaxed, e.g. indexing. - std::vector - lookupDependentName(DeclarationName Name, - llvm::function_ref Filter); - /// Renders and displays an inheritance diagram /// for this C++ class and all of its base classes (transitively) using /// GraphViz. diff --git a/clang/include/clang/Sema/HeuristicResolver.h b/clang/include/clang/Sema/HeuristicResolver.h index 3760003aab89f..f511815b40199 100644 --- a/clang/include/clang/Sema/HeuristicResolver.h +++ b/clang/include/clang/Sema/HeuristicResolver.h @@ -69,6 +69,13 @@ class HeuristicResolver { QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const; + // Perform an imprecise lookup of a dependent name in `RD`. + // This function does not follow strict semantic rules and should be used + // only when lookup rules can be relaxed, e.g. indexing. + std::vector + lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, + llvm::function_ref Filter); + // Given the type T of a dependent expression that appears of the LHS of a // "->", heuristically find a corresponding pointee type in whose scope we // could look up the name appearing on the RHS. diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index ee5775837d535..ab862d57eae89 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -411,59 +411,6 @@ bool CXXRecordDecl::hasMemberName(DeclarationName Name) const { Paths); } -static bool -findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, DeclarationName Name) { - const TemplateSpecializationType *TST = - Specifier->getType()->getAs(); - if (!TST) { - auto *RT = Specifier->getType()->getAs(); - if (!RT) - return false; - return findOrdinaryMember(cast(RT->getDecl()), Path, Name); - } - TemplateName TN = TST->getTemplateName(); - const auto *TD = dyn_cast_or_null(TN.getAsTemplateDecl()); - if (!TD) - return false; - CXXRecordDecl *RD = TD->getTemplatedDecl(); - if (!RD) - return false; - return findOrdinaryMember(RD, Path, Name); -} - -std::vector CXXRecordDecl::lookupDependentName( - DeclarationName Name, - llvm::function_ref Filter) { - std::vector Results; - // Lookup in the class. - bool AnyOrdinaryMembers = false; - for (const NamedDecl *ND : lookup(Name)) { - if (isOrdinaryMember(ND)) - AnyOrdinaryMembers = true; - if (Filter(ND)) - Results.push_back(ND); - } - if (AnyOrdinaryMembers) - return Results; - - // Perform lookup into our base classes. - CXXBasePaths Paths; - Paths.setOrigin(this); - if (!lookupInBases( - [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { - return findOrdinaryMemberInDependentClasses(Specifier, Path, Name); - }, - Paths, /*LookupInDependent=*/true)) - return Results; - for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end(); - I != E; ++I) { - if (isOrdinaryMember(*I) && Filter(*I)) - Results.push_back(*I); - } - return Results; -} - void OverridingMethods::add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding) { SmallVectorImpl &SubobjectOverrides diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp index 3af4d001d6c1a..7aecd2a73b539 100644 --- a/clang/lib/Sema/HeuristicResolver.cpp +++ b/clang/lib/Sema/HeuristicResolver.cpp @@ -44,6 +44,9 @@ class HeuristicResolverImpl { const DependentTemplateSpecializationType *DTST); QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS); QualType getPointeeType(QualType T); + std::vector + lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, + llvm::function_ref Filter); private: ASTContext &Ctx; @@ -83,16 +86,6 @@ class HeuristicResolverImpl { // during simplification, and the operation fails if no pointer type is found. QualType simplifyType(QualType Type, const Expr *E, bool UnwrapPointer); - // This is a reimplementation of CXXRecordDecl::lookupDependentName() - // so that the implementation can call into other HeuristicResolver helpers. - // FIXME: Once HeuristicResolver is upstreamed to the clang libraries - // (https://github.com/clangd/clangd/discussions/1662), - // CXXRecordDecl::lookupDepenedentName() can be removed, and its call sites - // can be modified to benefit from the more comprehensive heuristics offered - // by HeuristicResolver instead. - std::vector - lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, - llvm::function_ref Filter); bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name); @@ -539,6 +532,11 @@ QualType HeuristicResolver::resolveNestedNameSpecifierToType( const NestedNameSpecifier *NNS) const { return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS); } +std::vector HeuristicResolver::lookupDependentName( + CXXRecordDecl *RD, DeclarationName Name, + llvm::function_ref Filter) { + return HeuristicResolverImpl(Ctx).lookupDependentName(RD, Name, Filter); +} const QualType HeuristicResolver::getPointeeType(QualType T) const { return HeuristicResolverImpl(Ctx).getPointeeType(T); }