@@ -39,6 +39,8 @@ STATISTIC(FailInferFunction, "# of functions unable to infer");
39
39
// Specifically skipped/avoided
40
40
STATISTIC (SkipLeadingUnderscore,
41
41
" # of globals skipped due to leading underscore" );
42
+ STATISTIC (SkipCFMemoryManagement,
43
+ " # of CF memory management globals skipped" );
42
44
43
45
// Success statistics
44
46
STATISTIC (SuccessImportAsTypeID, " # imported as 'typeID'" );
@@ -176,6 +178,7 @@ class IAMInference {
176
178
}
177
179
178
180
IAMResult infer (const clang::NamedDecl *);
181
+ IAMResult inferVar (const clang::VarDecl *);
179
182
180
183
private:
181
184
// typeID
@@ -617,39 +620,43 @@ bool IAMInference::validToImportAsProperty(
617
620
return isValidAsInstanceProperty (getterDecl, setterDecl);
618
621
}
619
622
620
- IAMResult IAMInference::infer (const clang::NamedDecl *clangDecl) {
621
- if (clangDecl->getName ().startswith (" _" )) {
622
- ++SkipLeadingUnderscore;
623
+ IAMResult IAMInference::inferVar (const clang::VarDecl *varDecl) {
624
+ auto fail = [varDecl]() -> IAMResult {
625
+ DEBUG (llvm::dbgs () << " failed to infer variable: " );
626
+ DEBUG (varDecl->print (llvm::dbgs ()));
627
+ DEBUG (llvm::dbgs () << " \n " );
628
+ ++FailInferVar;
623
629
return {};
624
- }
630
+ };
625
631
626
- if (auto varDecl = dyn_cast<clang::VarDecl>(clangDecl)) {
627
- auto fail = [varDecl]() -> IAMResult {
628
- DEBUG (llvm::dbgs () << " failed to infer variable: " );
629
- DEBUG (varDecl->print (llvm::dbgs ()));
630
- DEBUG (llvm::dbgs () << " \n " );
631
- ++FailInferVar;
632
- return {};
633
- };
632
+ // Try to find a type to add this as a static property to
633
+ StringRef workingName = varDecl->getName ();
634
+ if (workingName.empty ())
635
+ return fail ();
634
636
635
- // Try to find a type to add this as a static property to
636
- StringRef workingName = varDecl-> getName ();
637
- if (workingName. empty () )
638
- return fail ( );
637
+ // Special pattern: constants of the form "kFooBarBaz", extend "FooBar" with
638
+ // property "Baz"
639
+ if (* camel_case::getWords ( workingName). begin () == " k " )
640
+ workingName = workingName. drop_front ( 1 );
639
641
640
- // Special pattern: constants of the form "kFooBarBaz", extend "FooBar" with
641
- // property "Baz"
642
- if (*camel_case::getWords (workingName).begin () == " k" )
643
- workingName = workingName.drop_front (1 );
642
+ NameBuffer remainingName;
643
+ if (auto effectiveDC = findTypeAndMatch (workingName, remainingName))
644
644
645
- NameBuffer remainingName;
646
- if (auto effectiveDC = findTypeAndMatch (workingName, remainingName))
645
+ return importAsStaticProperty (remainingName, effectiveDC);
647
646
648
- return importAsStaticProperty (remainingName, effectiveDC);
647
+ return fail ();
648
+ }
649
649
650
- return fail ();
650
+ IAMResult IAMInference::infer (const clang::NamedDecl *clangDecl) {
651
+ if (clangDecl->getName ().startswith (" _" )) {
652
+ ++SkipLeadingUnderscore;
653
+ return {};
651
654
}
652
655
656
+ // Try to infer a member variable
657
+ if (auto varDecl = dyn_cast<clang::VarDecl>(clangDecl))
658
+ return inferVar (varDecl);
659
+
653
660
// Try to infer a member function
654
661
auto funcDecl = dyn_cast<clang::FunctionDecl>(clangDecl);
655
662
if (!funcDecl) {
@@ -675,9 +682,11 @@ IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) {
675
682
auto retTy = funcDecl->getReturnType ();
676
683
unsigned numParams = funcDecl->getNumParams ();
677
684
678
- // 0) Special cases are specially handled: *GetTypeID()
685
+ // 0) Special cases are specially handled
679
686
//
680
687
StringRef getTypeID = " GetTypeID" ;
688
+ StringRef cfSpecials[] = {" Release" , " Retain" , " Autorelease" };
689
+ // *GetTypeID
681
690
if (numParams == 0 && workingName.endswith (getTypeID)) {
682
691
NameBuffer remainingName;
683
692
if (auto effectiveDC = findTypeAndMatch (
@@ -688,6 +697,19 @@ IAMResult IAMInference::infer(const clang::NamedDecl *clangDecl) {
688
697
return importAsTypeID (retTy, effectiveDC);
689
698
}
690
699
}
700
+ // *Release/*Retain/*Autorelease
701
+ } else if (numParams == 1 &&
702
+ std::any_of (std::begin (cfSpecials), std::end (cfSpecials),
703
+ [workingName](StringRef suffix) {
704
+ return workingName.endswith (suffix);
705
+ })) {
706
+ if (auto type =
707
+ funcDecl->getParamDecl (0 )->getType ()->getAs <clang::TypedefType>()) {
708
+ if (CFPointeeInfo::classifyTypedef (type->getDecl ())) {
709
+ ++SkipCFMemoryManagement;
710
+ return {};
711
+ }
712
+ }
691
713
}
692
714
693
715
// 1) If we find an init specifier and our name matches the return type, we
0 commit comments