676
676
return CIP_Allowed;
679
/// Returns true if the given C++ class is a container.
679
/// Returns true if the given C++ class contains a member with the given name.
680
static bool hasMember(const ASTContext &Ctx, const CXXRecordDecl *RD,
682
const IdentifierInfo &II = Ctx.Idents.get(Name);
683
DeclarationName DeclName = Ctx.DeclarationNames.getIdentifier(&II);
684
if (!RD->lookup(DeclName).empty())
687
CXXBasePaths Paths(false, false, false);
688
if (RD->lookupInBases(&CXXRecordDecl::FindOrdinaryMember,
689
DeclName.getAsOpaquePtr(),
696
/// Returns true if the given C++ class is a container or iterator.
681
698
/// Our heuristic for this is whether it contains a method named 'begin()' or a
682
/// nested type named 'iterator'.
699
/// nested type named 'iterator' or 'iterator_category'.
683
700
static bool isContainerClass(const ASTContext &Ctx, const CXXRecordDecl *RD) {
684
// Don't record any path information.
685
CXXBasePaths Paths(false, false, false);
687
const IdentifierInfo &BeginII = Ctx.Idents.get("begin");
688
DeclarationName BeginName = Ctx.DeclarationNames.getIdentifier(&BeginII);
689
DeclContext::lookup_const_result BeginDecls = RD->lookup(BeginName);
690
if (!BeginDecls.empty())
692
if (RD->lookupInBases(&CXXRecordDecl::FindOrdinaryMember,
693
BeginName.getAsOpaquePtr(),
697
const IdentifierInfo &IterII = Ctx.Idents.get("iterator");
698
DeclarationName IteratorName = Ctx.DeclarationNames.getIdentifier(&IterII);
699
DeclContext::lookup_const_result IterDecls = RD->lookup(IteratorName);
700
if (!IterDecls.empty())
702
if (RD->lookupInBases(&CXXRecordDecl::FindOrdinaryMember,
703
IteratorName.getAsOpaquePtr(),
701
return hasMember(Ctx, RD, "begin") ||
702
hasMember(Ctx, RD, "iterator") ||
703
hasMember(Ctx, RD, "iterator_category");
710
706
/// Returns true if the given function refers to a constructor or destructor of
707
/// a C++ container or iterator.
713
709
/// We generally do a poor job modeling most containers right now, and would
714
/// prefer not to inline their methods.
710
/// prefer not to inline their setup and teardown.
715
711
static bool isContainerCtorOrDtor(const ASTContext &Ctx,
716
712
const FunctionDecl *FD) {
717
// Heuristic: a type is a container if it contains a "begin()" method
718
// or a type named "iterator".
719
713
if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)))
723
717
return isContainerClass(Ctx, RD);
720
/// Returns true if the given function is the destructor of a class named
722
static bool isCXXSharedPtrDtor(const FunctionDecl *FD) {
723
const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(FD);
727
const CXXRecordDecl *RD = Dtor->getParent();
728
if (const IdentifierInfo *II = RD->getDeclName().getAsIdentifierInfo())
729
if (II->isStr("shared_ptr"))
726
735
/// Returns true if the function in \p CalleeADC may be inlined in general.
728
737
/// This checks static properties of the function, such as its signature and
755
764
if (!Ctx.getSourceManager().isFromMainFile(FD->getLocation()))
756
765
if (isContainerCtorOrDtor(Ctx, FD))
768
// Conditionally control the inlining of the destructor of C++ shared_ptr.
769
// We don't currently do a good job modeling shared_ptr because we can't
770
// see the reference count, so treating as opaque is probably the best
772
if (!Opts.mayInlineCXXSharedPtrDtor())
773
if (isCXXSharedPtrDtor(FD))