/// Returns true if the given C++ class is a container. /// /// Our heuristic for this is whether it contains a method named 'begin()' or a /// nested type named 'iterator'. static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD) { // Don't record any path information. CXXBasePaths Paths(false, false, false); const IdentifierInfo &BeginII = Ctx.Idents.get("begin"); DeclarationName BeginName = Ctx.DeclarationNames.getIdentifier(&BeginII); DeclContext::lookup_const_result BeginDecls = RD->lookup(BeginName); if (!BeginDecls.empty()) return true; if (RD->lookupInBases(&CXXRecordDecl::FindOrdinaryMember, BeginName.getAsOpaquePtr(), Paths)) return true; const IdentifierInfo &IterII = Ctx.Idents.get("iterator"); DeclarationName IteratorName = Ctx.DeclarationNames.getIdentifier(&IterII); DeclContext::lookup_const_result IterDecls = RD->lookup(IteratorName); if (!IterDecls.empty()) return true; if (RD->lookupInBases(&CXXRecordDecl::FindOrdinaryMember, IteratorName.getAsOpaquePtr(), Paths)) return true; return false; }
/// Returns true if the given C++ class contains a member with the given name. static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD, StringRef Name) { const IdentifierInfo &II = Ctx.Idents.get(Name); DeclarationName DeclName = Ctx.DeclarationNames.getIdentifier(&II); if (!RD->lookup(DeclName).empty()) return true; CXXBasePaths Paths(false, false, false); if (RD->lookupInBases(&CXXRecordDecl::FindOrdinaryMember, DeclName.getAsOpaquePtr(), Paths)) return true; return false; }
void StmtProfiler::VisitName(DeclarationName Name) { ID.AddPointer(Name.getAsOpaquePtr()); }