23 #include "clang/Config/config.h" 26 #include "llvm/ADT/DenseSet.h" 27 #include "llvm/ADT/SmallPtrSet.h" 28 #include "llvm/ADT/StringExtras.h" 29 #include "llvm/Support/MemoryBuffer.h" 30 #include "llvm/Support/raw_ostream.h" 33 #if CLANG_ENABLE_OBJC_REWRITER 35 using namespace clang;
55 BLOCK_NEEDS_FREE = (1 << 24),
58 BLOCK_IS_GC = (1 << 27),
60 BLOCK_HAS_DESCRIPTOR = (1 << 29)
62 static const int OBJC_ABI_VERSION = 7;
71 const char *MainFileStart, *MainFileEnd;
74 std::string InFileName;
75 std::unique_ptr<raw_ostream> OutFile;
80 unsigned RewriteFailedDiag;
82 unsigned NumObjCStringLiterals;
83 VarDecl *ConstantStringClassReference;
89 unsigned TryFinallyContainsReturnDiag;
112 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
113 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
114 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
115 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
119 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
132 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
134 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
135 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
136 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
137 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
139 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
144 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
148 bool SilenceRewriteMacroWarning;
149 bool objc_impl_method;
151 bool DisableReplaceStmt;
152 class DisableReplaceStmtScope {
158 : R(R), SavedValue(R.DisableReplaceStmt) {
159 R.DisableReplaceStmt =
true;
162 ~DisableReplaceStmtScope() {
163 R.DisableReplaceStmt = SavedValue;
174 if (!
Class->isThisDeclarationADefinition()) {
175 RewriteForwardClassDecl(D);
181 if (!Proto->isThisDeclarationADefinition()) {
182 RewriteForwardProtocolDecl(D);
187 HandleTopLevelSingleDecl(*I);
192 void HandleTopLevelSingleDecl(
Decl *D);
193 void HandleDeclInMainFile(
Decl *D);
194 RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
196 bool silenceMacroWarn);
200 void HandleTranslationUnit(
ASTContext &
C)
override;
202 void ReplaceStmt(
Stmt *Old,
Stmt *New) {
207 assert(Old !=
nullptr && New !=
nullptr &&
"Expected non-null Stmt's");
209 Stmt *ReplacingStmt = ReplacedNodes[Old];
213 if (DisableReplaceStmt)
225 llvm::raw_string_ostream S(SStr);
227 const std::string &Str = S.str();
231 ReplacedNodes[Old] = New;
234 if (SilenceRewriteMacroWarning)
241 bool InsertAfter =
true) {
243 if (!Rewrite.
InsertText(Loc, Str, InsertAfter) ||
244 SilenceRewriteMacroWarning)
253 if (!Rewrite.
ReplaceText(Start, OrigLength, Str) ||
254 SilenceRewriteMacroWarning)
262 void RewriteInclude();
266 const std::string &typedefString);
267 void RewriteImplementations();
272 void RewriteImplementationDecl(
Decl *Dcl);
275 void RewriteTypeIntoString(
QualType T, std::string &ResultStr,
277 void RewriteByRefString(std::string &ResultStr,
const std::string &Name,
286 void RewriteBlockPointerType(std::string& Str,
QualType Type);
287 void RewriteBlockPointerTypeVariable(std::string& Str,
ValueDecl *VD);
289 void RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl);
290 void RewriteTypeOfDecl(
VarDecl *VD);
291 void RewriteObjCQualifiedInterfaceTypes(
Expr *E);
294 Stmt *RewriteFunctionBodyOrGlobalInitializer(
Stmt *S);
302 void RewriteTryReturnStmts(
Stmt *S);
303 void RewriteSyncReturnStmts(
Stmt *S, std::string buf);
317 void RewriteBlockPointerDecl(
NamedDecl *VD);
318 void RewriteByRefVar(
VarDecl *VD);
326 void Initialize(
ASTContext &context)
override = 0;
329 virtual void RewriteMetaDataIntoBuffer(std::string &
Result) = 0;
345 virtual void RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
364 void SynthCountByEnumWithState(std::string &buf);
365 void SynthMsgSendFunctionDecl();
366 void SynthMsgSendSuperFunctionDecl();
367 void SynthMsgSendStretFunctionDecl();
368 void SynthMsgSendFpretFunctionDecl();
369 void SynthMsgSendSuperStretFunctionDecl();
370 void SynthGetClassFunctionDecl();
371 void SynthGetMetaClassFunctionDecl();
372 void SynthGetSuperClassFunctionDecl();
373 void SynthSelGetUidFunctionDecl();
374 void SynthSuperConstructorFunctionDecl();
376 std::string SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
int flag);
377 std::string SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
378 StringRef funcName, std::string Tag);
379 std::string SynthesizeBlockFunc(
BlockExpr *CE,
int i,
380 StringRef funcName, std::string Tag);
381 std::string SynthesizeBlockImpl(
BlockExpr *CE,
382 std::string Tag, std::string Desc);
383 std::string SynthesizeBlockDescriptor(std::string DescTag,
385 int i, StringRef funcName,
390 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
396 void WarnAboutReturnGotoStmts(
Stmt *S);
397 void HasReturnStmts(
Stmt *S,
bool &hasReturns);
399 void InsertBlockLiteralsWithinFunction(
FunctionDecl *FD);
402 bool IsDeclStmtInForeachHeader(
DeclStmt *DS);
403 void CollectBlockDeclRefInfo(
BlockExpr *Exp);
404 void GetBlockDeclRefExprs(
Stmt *S);
405 void GetInnerBlockDeclRefExprs(
Stmt *S,
407 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
411 bool isTopLevelBlockPointerType(
QualType T) {
412 return isa<BlockPointerType>(T);
418 bool convertBlockPointerToFunctionPointer(
QualType &T) {
419 if (isTopLevelBlockPointerType(T)) {
427 bool needToScanForQualifiers(
QualType T);
429 QualType getConstantStringStructType();
431 bool BufferContainsPPDirectives(
const char *startBuf,
const char *endBuf);
433 void convertToUnqualifiedObjCType(
QualType &T) {
451 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
461 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
462 PT->getPointeeType()->isObjCQualifiedIdType())
467 bool PointerTypeTakesAnyBlockArguments(
QualType QT);
468 bool PointerTypeTakesAnyObjCQualifiedType(
QualType QT);
469 void GetExtentOfArgList(
const char *Name,
const char *&LParen,
470 const char *&RParen);
472 void QuoteDoublequotes(std::string &From, std::string &To) {
473 for (
unsigned i = 0; i < From.length(); i++) {
483 bool variadic =
false) {
510 RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
512 bool silenceMacroWarn)
513 :
RewriteObjC(inFile,
std::move(OS), D, LOpts, silenceMacroWarn) {}
515 ~RewriteObjCFragileABI()
override {}
516 void Initialize(
ASTContext &context)
override;
519 template<
typename MethodIterator>
520 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
521 MethodIterator MethodEnd,
522 bool IsInstanceMethod,
527 StringRef prefix, StringRef ClassName,
528 std::string &
Result)
override;
529 void RewriteObjCProtocolListMetaData(
531 StringRef prefix, StringRef ClassName, std::string &
Result)
override;
533 std::string &
Result)
override;
534 void RewriteMetaDataIntoBuffer(std::string &
Result)
override;
536 std::string &
Result)
override;
540 std::string &
Result)
override;
545 void RewriteObjC::RewriteBlocksInFunctionProtoType(
QualType funcType,
548 = dyn_cast<FunctionProtoType>(funcType.
IgnoreParens())) {
549 for (
const auto &I : fproto->param_types())
550 if (isTopLevelBlockPointerType(I)) {
552 RewriteBlockPointerDecl(D);
560 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
565 std::string::size_type DotPos = Filename.rfind(
'.');
567 if (DotPos == std::string::npos) {
572 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
575 return Ext ==
"h" || Ext ==
"hh" || Ext ==
"H";
580 bool silenceMacroWarn)
581 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
582 SilenceRewriteMacroWarning(silenceMacroWarn) {
585 "rewriting sub-expression within a macro (may not be correct)");
588 "rewriter doesn't support user-specified control flow semantics " 589 "for @try/@finally (code may not execute properly)");
592 std::unique_ptr<ASTConsumer>
594 std::unique_ptr<raw_ostream> OS,
596 bool SilenceRewriteMacroWarning) {
597 return llvm::make_unique<RewriteObjCFragileABI>(
598 InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);
601 void RewriteObjC::InitializeCommon(
ASTContext &context) {
605 MsgSendFunctionDecl =
nullptr;
606 MsgSendSuperFunctionDecl =
nullptr;
607 MsgSendStretFunctionDecl =
nullptr;
608 MsgSendSuperStretFunctionDecl =
nullptr;
609 MsgSendFpretFunctionDecl =
nullptr;
610 GetClassFunctionDecl =
nullptr;
611 GetMetaClassFunctionDecl =
nullptr;
612 GetSuperClassFunctionDecl =
nullptr;
613 SelGetUidFunctionDecl =
nullptr;
614 CFStringFunctionDecl =
nullptr;
615 ConstantStringClassReference =
nullptr;
616 NSStringRecord =
nullptr;
617 CurMethodDef =
nullptr;
618 CurFunctionDef =
nullptr;
619 CurFunctionDeclToDeclareForBlock =
nullptr;
620 GlobalVarDecl =
nullptr;
621 SuperStructDecl =
nullptr;
622 ProtocolTypeDecl =
nullptr;
623 ConstantStringDecl =
nullptr;
625 SuperConstructorFunctionDecl =
nullptr;
626 NumObjCStringLiterals = 0;
627 PropParentMap =
nullptr;
628 CurrentBody =
nullptr;
629 DisableReplaceStmt =
false;
630 objc_impl_method =
false;
634 const llvm::MemoryBuffer *MainBuf = SM->
getBuffer(MainFileID);
635 MainFileStart = MainBuf->getBufferStart();
636 MainFileEnd = MainBuf->getBufferEnd();
645 void RewriteObjC::HandleTopLevelSingleDecl(
Decl *D) {
660 RewriteFunctionDecl(FD);
661 }
else if (
VarDecl *FVD = dyn_cast<VarDecl>(D)) {
663 if (FVD->getName() ==
"_NSConstantStringClassReference") {
664 ConstantStringClassReference = FVD;
668 if (
ID->isThisDeclarationADefinition())
669 RewriteInterfaceDecl(
ID);
671 RewriteCategoryDecl(CD);
673 if (PD->isThisDeclarationADefinition())
674 RewriteProtocolDecl(PD);
678 DIEnd = LSD->decls_end();
681 if (!IFace->isThisDeclarationADefinition()) {
685 if (isa<ObjCInterfaceDecl>(*DI) &&
686 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
687 StartLoc == (*DI)->getLocStart())
693 }
while (DI != DIEnd);
694 RewriteForwardClassDecl(DG);
700 if (!Proto->isThisDeclarationADefinition()) {
704 if (isa<ObjCProtocolDecl>(*DI) &&
705 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
706 StartLoc == (*DI)->getLocStart())
712 }
while (DI != DIEnd);
713 RewriteForwardProtocolDecl(DG);
718 HandleTopLevelSingleDecl(*DI);
724 return HandleDeclInMainFile(D);
731 void RewriteObjC::RewriteInclude() {
734 const char *MainBufStart = MainBuf.begin();
735 const char *MainBufEnd = MainBuf.end();
736 size_t ImportLen = strlen(
"import");
739 for (
const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
740 if (*BufPtr ==
'#') {
741 if (++BufPtr == MainBufEnd)
743 while (*BufPtr ==
' ' || *BufPtr ==
'\t')
744 if (++BufPtr == MainBufEnd)
746 if (!strncmp(BufPtr,
"import", ImportLen)) {
750 ReplaceText(ImportLoc, ImportLen,
"include");
762 S +=
"_IMPL *)self)->";
770 static bool objcGetPropertyDefined =
false;
771 static bool objcSetPropertyDefined =
false;
773 InsertText(startLoc,
"// ");
775 assert((*startBuf ==
'@') &&
"bogus @synthesize location");
776 const char *semiBuf = strchr(startBuf,
';');
777 assert((*semiBuf ==
';') &&
"@synthesize: can't find ';'");
796 if (GenGetProperty && !objcGetPropertyDefined) {
797 objcGetPropertyDefined =
true;
799 Getr =
"\nextern \"C\" __declspec(dllimport) " 800 "id objc_getProperty(id, SEL, long, bool);\n";
807 if (GenGetProperty) {
820 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
822 std::string ParamStr =
826 if (FT->isVariadic()) {
827 if (FT->getNumParams())
836 Getr +=
"return (_TYPE)";
837 Getr +=
"objc_getProperty(self, _cmd, ";
838 RewriteIvarOffsetComputation(OID, Getr);
844 InsertText(onePastSemiLoc, Getr);
854 if (GenSetProperty && !objcSetPropertyDefined) {
855 objcSetPropertyDefined =
true;
857 Setr =
"\nextern \"C\" __declspec(dllimport) " 858 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
866 if (GenSetProperty) {
867 Setr +=
"objc_setProperty (self, _cmd, ";
868 RewriteIvarOffsetComputation(OID, Setr);
886 InsertText(onePastSemiLoc, Setr);
890 std::string &typedefString) {
891 typedefString +=
"#ifndef _REWRITER_typedef_";
893 typedefString +=
"\n";
894 typedefString +=
"#define _REWRITER_typedef_";
896 typedefString +=
"\n";
897 typedefString +=
"typedef struct objc_object ";
899 typedefString +=
";\n#endif\n";
903 const std::string &typedefString) {
906 const char *semiPtr = strchr(startBuf,
';');
908 ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
911 void RewriteObjC::RewriteForwardClassDecl(
DeclGroupRef D) {
912 std::string typedefString;
915 if (I == D.
begin()) {
919 typedefString +=
"// @class ";
921 typedefString +=
";\n";
926 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
930 std::string typedefString;
931 for (
unsigned i = 0; i < D.size(); i++) {
934 typedefString +=
"// @class ";
936 typedefString +=
";\n";
940 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
943 void RewriteObjC::RewriteMethodDeclaration(
ObjCMethodDecl *Method) {
953 InsertText(LocStart,
"#if 0\n");
954 ReplaceText(LocEnd, 1,
";\n#endif\n");
956 InsertText(LocStart,
"// ");
963 ReplaceText(Loc, 0,
"// ");
971 ReplaceText(LocStart, 0,
"// ");
976 RewriteMethodDeclaration(I);
978 RewriteMethodDeclaration(I);
982 strlen(
"@end"),
"/* @end */");
990 ReplaceText(LocStart, 0,
"// ");
993 RewriteMethodDeclaration(I);
995 RewriteMethodDeclaration(I);
1001 ReplaceText(LocEnd, strlen(
"@end"),
"/* @end */");
1006 for (
const char *p = startBuf; p < endBuf; p++) {
1007 if (*p ==
'@' && !strncmp(p+1,
"optional", strlen(
"optional"))) {
1009 ReplaceText(OptionalLoc, strlen(
"@optional"),
"/* @optional */");
1012 else if (*p ==
'@' && !strncmp(p+1,
"required", strlen(
"required"))) {
1014 ReplaceText(OptionalLoc, strlen(
"@required"),
"/* @required */");
1020 void RewriteObjC::RewriteForwardProtocolDecl(
DeclGroupRef D) {
1023 llvm_unreachable(
"Invalid SourceLocation");
1025 ReplaceText(LocStart, 0,
"// ");
1032 llvm_unreachable(
"Invalid SourceLocation");
1034 ReplaceText(LocStart, 0,
"// ");
1037 void RewriteObjC::RewriteTypeIntoString(
QualType T, std::string &ResultStr,
1062 std::string &ResultStr) {
1065 ResultStr +=
"\nstatic ";
1066 RewriteTypeIntoString(OMD->
getReturnType(), ResultStr, FPRetType);
1070 std::string NameStr;
1088 int len = selString.size();
1089 for (
int i = 0; i < len; i++)
1090 if (selString[i] ==
':')
1092 NameStr += selString;
1095 MethodInternalNames[OMD] = NameStr;
1096 ResultStr += NameStr;
1105 if (!LangOpts.MicrosoftExt) {
1106 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
1107 ResultStr +=
"struct ";
1117 ResultStr +=
" self, ";
1119 ResultStr +=
" _cmd";
1122 for (
const auto *PDecl : OMD->
parameters()) {
1124 if (PDecl->getType()->isObjCQualifiedIdType()) {
1131 (void)convertBlockPointerToFunctionPointer(QT);
1137 ResultStr +=
", ...";
1146 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
1147 if (i) ResultStr +=
", ";
1148 std::string ParamStr =
1150 ResultStr += ParamStr;
1152 if (FT->isVariadic()) {
1153 if (FT->getNumParams())
1164 void RewriteObjC::RewriteImplementationDecl(
Decl *OID) {
1168 InsertText(IMD ? IMD->
getLocStart() : CID->getLocStart(),
"// ");
1170 for (
auto *OMD : IMD ? IMD->
instance_methods() : CID->instance_methods()) {
1171 std::string ResultStr;
1178 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1181 for (
auto *OMD : IMD ? IMD->
class_methods() : CID->class_methods()) {
1182 std::string ResultStr;
1189 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1191 for (
auto *I : IMD ? IMD->
property_impls() : CID->property_impls())
1192 RewritePropertyImplDecl(I, IMD, CID);
1194 InsertText(IMD ? IMD->
getLocEnd() : CID->getLocEnd(),
"// ");
1198 std::string ResultStr;
1201 ResultStr =
"#ifndef _REWRITER_typedef_";
1204 ResultStr +=
"#define _REWRITER_typedef_";
1207 ResultStr +=
"typedef struct objc_object ";
1209 ResultStr +=
";\n#endif\n";
1213 RewriteObjCInternalStruct(ClassDecl, ResultStr);
1218 RewriteMethodDeclaration(I);
1220 RewriteMethodDeclaration(I);
1240 DisableReplaceStmtScope S(*
this);
1246 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1247 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1252 RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
1253 RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1306 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1322 DisableReplaceStmtScope S(*
this);
1327 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1328 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1382 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1395 void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1396 buf +=
"((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 1397 "id *, unsigned int))(void *)objc_msgSend)";
1399 buf +=
"((id)l_collection,\n\t\t";
1400 buf +=
"sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1402 buf +=
"&enumState, " 1403 "(id *)__rw_items, (unsigned int)16)";
1410 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1416 buf =
"goto __break_label_";
1417 buf += utostr(ObjCBcLabelNo.back());
1418 ReplaceText(startLoc, strlen(
"break"), buf);
1427 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1433 buf =
"goto __continue_label_";
1434 buf += utostr(ObjCBcLabelNo.back());
1435 ReplaceText(startLoc, strlen(
"continue"), buf);
1474 assert(!Stmts.empty() &&
"ObjCForCollectionStmt - Statement stack empty");
1475 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1476 "ObjCForCollectionStmt Statement stack mismatch");
1477 assert(!ObjCBcLabelNo.empty() &&
1478 "ObjCForCollectionStmt - Label No stack empty");
1482 StringRef elementName;
1483 std::string elementTypeAsString;
1488 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1489 QualType ElementType = cast<ValueDecl>(D)->getType();
1490 if (ElementType->isObjCQualifiedIdType() ||
1491 ElementType->isObjCQualifiedInterfaceType())
1493 elementTypeAsString =
"id";
1496 buf += elementTypeAsString;
1509 elementTypeAsString =
"id";
1515 buf +=
"struct __objcFastEnumerationState enumState = { 0 };\n\t";
1517 buf +=
"id __rw_items[16];\n\t";
1519 buf +=
"id l_collection = (id)";
1521 const char *startCollectionBuf = startBuf;
1522 startCollectionBuf += 3;
1523 startCollectionBuf = strchr(startCollectionBuf,
'(');
1524 startCollectionBuf++;
1526 while (*startCollectionBuf !=
' ' ||
1527 *(startCollectionBuf+1) !=
'i' || *(startCollectionBuf+2) !=
'n' ||
1528 (*(startCollectionBuf+3) !=
' ' &&
1529 *(startCollectionBuf+3) !=
'[' && *(startCollectionBuf+3) !=
'('))
1530 startCollectionBuf++;
1531 startCollectionBuf += 3;
1534 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1552 buf +=
"unsigned long limit =\n\t\t";
1553 SynthCountByEnumWithState(buf);
1563 buf +=
"if (limit) {\n\t";
1564 buf +=
"unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1565 buf +=
"do {\n\t\t";
1566 buf +=
"unsigned long counter = 0;\n\t\t";
1567 buf +=
"do {\n\t\t\t";
1568 buf +=
"if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1569 buf +=
"objc_enumerationMutation(l_collection);\n\t\t\t";
1572 buf += elementTypeAsString;
1573 buf +=
")enumState.itemsPtr[counter++];";
1575 ReplaceText(lparenLoc, 1, buf);
1589 buf +=
"__continue_label_";
1590 buf += utostr(ObjCBcLabelNo.back());
1593 buf +=
"} while (counter < limit);\n\t";
1594 buf +=
"} while (limit = ";
1595 SynthCountByEnumWithState(buf);
1599 buf += elementTypeAsString;
1601 buf +=
"__break_label_";
1602 buf += utostr(ObjCBcLabelNo.back());
1605 buf +=
"else\n\t\t";
1608 buf += elementTypeAsString;
1614 if (isa<CompoundStmt>(S->
getBody())) {
1616 InsertText(endBodyLoc, buf);
1626 const char *semiBuf = strchr(stmtBuf,
';');
1627 assert(semiBuf &&
"Can't find ';'");
1629 InsertText(endBodyLoc, buf);
1632 ObjCBcLabelNo.pop_back();
1647 assert((*startBuf ==
'@') &&
"bogus @synchronized location");
1650 buf =
"objc_sync_enter((id)";
1651 const char *lparenBuf = startBuf;
1652 while (*lparenBuf !=
'(') lparenBuf++;
1653 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1659 while (*endBuf !=
')') endBuf--;
1663 buf +=
"/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1664 buf +=
"int buf[18/*32-bit i386*/];\n";
1665 buf +=
"char *pointers[4];} _stack;\n";
1666 buf +=
"id volatile _rethrow = 0;\n";
1667 buf +=
"objc_exception_try_enter(&_stack);\n";
1668 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1669 ReplaceText(rparenLoc, 1, buf);
1673 assert((*startBuf ==
'}') &&
"bogus @synchronized block");
1675 buf =
"}\nelse {\n";
1676 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1678 buf +=
"{ /* implicit finally clause */\n";
1679 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1681 std::string syncBuf;
1682 syncBuf +=
" objc_sync_exit(";
1688 ? CK_BlockPointerToObjCPointerCast
1689 : CK_CPointerToObjCPointerCast;
1690 syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
1692 std::string syncExprBufS;
1693 llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1694 assert(syncExpr !=
nullptr &&
"Expected non-null Expr");
1696 syncBuf += syncExprBuf.str();
1700 buf +=
"\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1704 ReplaceText(lastCurlyLoc, 1, buf);
1706 bool hasReturns =
false;
1714 void RewriteObjC::WarnAboutReturnGotoStmts(
Stmt *S)
1719 WarnAboutReturnGotoStmts(SubStmt);
1721 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1723 TryFinallyContainsReturnDiag);
1727 void RewriteObjC::HasReturnStmts(
Stmt *S,
bool &hasReturns)
1732 HasReturnStmts(SubStmt, hasReturns);
1734 if (isa<ReturnStmt>(S))
1738 void RewriteObjC::RewriteTryReturnStmts(
Stmt *S) {
1742 RewriteTryReturnStmts(SubStmt);
1744 if (isa<ReturnStmt>(S)) {
1747 const char *semiBuf = strchr(startBuf,
';');
1748 assert((*semiBuf ==
';') &&
"RewriteTryReturnStmts: can't find ';'");
1752 buf =
"{ objc_exception_try_exit(&_stack); return";
1754 ReplaceText(startLoc, 6, buf);
1755 InsertText(onePastSemiLoc,
"}");
1759 void RewriteObjC::RewriteSyncReturnStmts(
Stmt *S, std::string syncExitBuf) {
1763 RewriteSyncReturnStmts(SubStmt, syncExitBuf);
1765 if (isa<ReturnStmt>(S)) {
1769 const char *semiBuf = strchr(startBuf,
';');
1770 assert((*semiBuf ==
';') &&
"RewriteSyncReturnStmts: can't find ';'");
1774 buf =
"{ objc_exception_try_exit(&_stack);";
1778 ReplaceText(startLoc, 6, buf);
1779 InsertText(onePastSemiLoc,
"}");
1788 assert((*startBuf ==
'@') &&
"bogus @try location");
1792 buf =
"/* @try scope begin */ { struct _objc_exception_data {\n";
1793 buf +=
"int buf[18/*32-bit i386*/];\n";
1794 buf +=
"char *pointers[4];} _stack;\n";
1795 buf +=
"id volatile _rethrow = 0;\n";
1796 buf +=
"objc_exception_try_enter(&_stack);\n";
1797 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1799 ReplaceText(startLoc, 4, buf);
1804 assert((*startBuf ==
'}') &&
"bogus @try block");
1809 buf =
" /* @catch begin */ else {\n";
1810 buf +=
" id _caught = objc_exception_extract(&_stack);\n";
1811 buf +=
" objc_exception_try_enter (&_stack);\n";
1812 buf +=
" if (_setjmp(_stack.buf))\n";
1813 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1814 buf +=
" else { /* @catch continue */";
1816 InsertText(startLoc, buf);
1818 buf =
"}\nelse {\n";
1819 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1821 ReplaceText(lastCurlyLoc, 1, buf);
1823 Stmt *lastCatchBody =
nullptr;
1835 assert((*startBuf ==
'@') &&
"bogus @catch location");
1837 const char *lParenLoc = strchr(startBuf,
'(');
1845 "bogus @catch paren location");
1846 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1848 buf +=
"1) { id _tmp = _caught;";
1849 Rewrite.
ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
1850 }
else if (catchDecl) {
1854 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1860 buf +=
"objc_exception_match((struct objc_class *)objc_getClass(\"";
1862 buf +=
"\"), (struct objc_object *)_caught)) { ";
1863 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1872 assert((*rParenBuf ==
')') &&
"bogus @catch paren location");
1873 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1877 ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
" = _caught;");
1879 llvm_unreachable(
"@catch rewrite bug");
1883 if (lastCatchBody) {
1886 "bogus @catch body location");
1890 buf =
"} /* last catch end */\n";
1892 buf +=
" _rethrow = _caught;\n";
1893 buf +=
" objc_exception_try_exit(&_stack);\n";
1894 buf +=
"} } /* @catch end */\n";
1897 InsertText(bodyLoc, buf);
1900 lastCurlyLoc = lastCatchBody->
getLocEnd();
1903 startLoc = finalStmt->getLocStart();
1905 assert((*startBuf ==
'@') &&
"bogus @finally start");
1907 ReplaceText(startLoc, 8,
"/* @finally */");
1909 Stmt *body = finalStmt->getFinallyBody();
1913 "bogus @finally body location");
1915 "bogus @finally body location");
1918 InsertText(startLoc,
" if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1920 InsertText(endLoc,
" if (_rethrow) objc_exception_throw(_rethrow);\n");
1928 buf =
"{ /* implicit finally clause */\n";
1929 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1930 buf +=
" if (_rethrow) objc_exception_throw(_rethrow);\n";
1932 ReplaceText(lastCurlyLoc, 1, buf);
1937 bool hasReturns =
false;
1944 InsertText(lastCurlyLoc,
" } /* @try scope end */\n");
1956 assert((*startBuf ==
'@') &&
"bogus @throw location");
1961 buf =
"objc_exception_throw(";
1963 buf =
"objc_exception_throw(_caught";
1966 const char *wBuf = strchr(startBuf,
'w');
1967 assert((*wBuf ==
'w') &&
"@throw: can't find 'w'");
1968 ReplaceText(startLoc, wBuf-startBuf+1, buf);
1970 const char *semiBuf = strchr(startBuf,
';');
1971 assert((*semiBuf ==
';') &&
"@throw: can't find ';'");
1973 ReplaceText(semiLoc, 1,
");");
1979 std::string StrEncoding;
1982 ReplaceStmt(Exp, Replacement);
1990 if (!SelGetUidFunctionDecl)
1991 SynthSelGetUidFunctionDecl();
1992 assert(SelGetUidFunctionDecl &&
"Can't find sel_registerName() decl");
1996 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
1998 ReplaceStmt(Exp, SelExp);
2004 RewriteObjC::SynthesizeCallToFunctionDecl(
FunctionDecl *FD,
2030 const char *&startRef,
const char *&endRef) {
2031 while (startBuf < endBuf) {
2032 if (*startBuf ==
'<')
2033 startRef = startBuf;
2034 if (*startBuf ==
'>') {
2035 if (startRef && *startRef ==
'<') {
2048 while (*argRef !=
')' && (*argRef !=
',' || angle > 0)) {
2051 else if (*argRef ==
'>')
2055 assert(angle == 0 &&
"scanToNextArgument - bad protocol type syntax");
2058 bool RewriteObjC::needToScanForQualifiers(
QualType T) {
2071 return needToScanForQualifiers(ElemTy);
2076 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Expr *E) {
2078 if (needToScanForQualifiers(Type)) {
2082 Loc = ECE->getLParenLoc();
2083 EndLoc = ECE->getRParenLoc();
2094 const char *startRef =
nullptr, *endRef =
nullptr;
2100 InsertText(LessLoc,
"/*");
2101 InsertText(GreaterLoc,
"*/");
2106 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl) {
2110 if (
VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2111 Loc = VD->getLocation();
2112 Type = VD->getType();
2114 else if (
FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2119 assert(funcType &&
"missing function type");
2125 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2132 if (needToScanForQualifiers(Type)) {
2136 const char *startBuf = endBuf;
2137 while (*startBuf !=
';' && *startBuf !=
'<' && startBuf != MainFileStart)
2139 const char *startRef =
nullptr, *endRef =
nullptr;
2145 InsertText(LessLoc,
"/*");
2146 InsertText(GreaterLoc,
"*/");
2153 const char *startFuncBuf = startBuf;
2158 const char *endBuf = startBuf;
2161 const char *startRef =
nullptr, *endRef =
nullptr;
2169 InsertText(LessLoc,
"/*");
2170 InsertText(GreaterLoc,
"*/");
2172 startBuf = ++endBuf;
2177 while (*startBuf && *startBuf !=
')' && *startBuf !=
',')
2184 void RewriteObjC::RewriteTypeOfDecl(
VarDecl *ND) {
2187 if (!isa<TypeOfExprType>(TypePtr))
2189 while (isa<TypeOfExprType>(TypePtr)) {
2190 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2201 TypeAsString +=
" " + Name +
" = ";
2205 startLoc = ECE->getLParenLoc();
2210 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2216 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2221 void RewriteObjC::SynthSelGetUidFunctionDecl() {
2230 SelGetUidIdent, getFuncType,
2234 void RewriteObjC::RewriteFunctionDecl(
FunctionDecl *FD) {
2237 FD->
getName() ==
"sel_registerName") {
2238 SelGetUidFunctionDecl = FD;
2241 RewriteObjCQualifiedInterfaceTypes(FD);
2244 void RewriteObjC::RewriteBlockPointerType(std::string& Str,
QualType Type) {
2246 const char *argPtr = TypeString.c_str();
2247 if (!strchr(argPtr,
'^')) {
2252 Str += (*argPtr ==
'^' ?
'*' : *argPtr);
2258 void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2262 const char *argPtr = TypeString.c_str();
2287 void RewriteObjC::RewriteBlockLiteralFunctionDecl(
FunctionDecl *FD) {
2293 QualType Type = proto->getReturnType();
2298 unsigned numArgs = proto->getNumParams();
2299 for (
unsigned i = 0; i < numArgs; i++) {
2300 QualType ArgType = proto->getParamType(i);
2301 RewriteBlockPointerType(FdStr, ArgType);
2306 InsertText(FunLocStart, FdStr);
2307 CurFunctionDeclToDeclareForBlock =
nullptr;
2311 void RewriteObjC::SynthSuperConstructorFunctionDecl() {
2312 if (SuperConstructorFunctionDecl)
2317 assert(!argT.
isNull() &&
"Can't find 'id' type");
2318 ArgTys.push_back(argT);
2319 ArgTys.push_back(argT);
2325 msgSendIdent, msgSendType,
2330 void RewriteObjC::SynthMsgSendFunctionDecl() {
2334 assert(!argT.
isNull() &&
"Can't find 'id' type");
2335 ArgTys.push_back(argT);
2337 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2338 ArgTys.push_back(argT);
2344 msgSendIdent, msgSendType,
2349 void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2356 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2357 ArgTys.push_back(argT);
2359 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2360 ArgTys.push_back(argT);
2366 msgSendIdent, msgSendType,
2371 void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2375 assert(!argT.
isNull() &&
"Can't find 'id' type");
2376 ArgTys.push_back(argT);
2378 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2379 ArgTys.push_back(argT);
2385 msgSendIdent, msgSendType,
2391 void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2393 &Context->
Idents.
get(
"objc_msgSendSuper_stret");
2399 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2400 ArgTys.push_back(argT);
2402 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2403 ArgTys.push_back(argT);
2410 msgSendType,
nullptr,
2415 void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2419 assert(!argT.
isNull() &&
"Can't find 'id' type");
2420 ArgTys.push_back(argT);
2422 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2423 ArgTys.push_back(argT);
2429 msgSendIdent, msgSendType,
2434 void RewriteObjC::SynthGetClassFunctionDecl() {
2443 getClassIdent, getClassType,
2448 void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2450 &Context->
Idents.
get(
"class_getSuperclass");
2459 getClassType,
nullptr,
2464 void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2473 getClassIdent, getClassType,
2478 assert(Exp !=
nullptr &&
"Expected non-null ObjCStringLiteral");
2479 QualType strType = getConstantStringStructType();
2481 std::string S =
"__NSConstantStringImpl_";
2483 std::string tmpName = InFileName;
2485 for (i=0; i < tmpName.length(); i++) {
2486 char c = tmpName.at(i);
2493 S += utostr(NumObjCStringLiterals++);
2495 Preamble +=
"static __NSConstantStringImpl " + S;
2496 Preamble +=
" __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2497 Preamble +=
"0x000007c8,";
2499 std::string prettyBufS;
2500 llvm::raw_string_ostream prettyBuf(prettyBufS);
2502 Preamble += prettyBuf.str();
2517 CK_CPointerToObjCPointerCast, Unop);
2518 ReplaceStmt(Exp, cast);
2524 QualType RewriteObjC::getSuperStructType() {
2525 if (!SuperStructDecl) {
2537 for (
unsigned i = 0; i < 2; ++i) {
2541 FieldTypes[i],
nullptr,
2552 QualType RewriteObjC::getConstantStringStructType() {
2553 if (!ConstantStringDecl) {
2556 &Context->
Idents.
get(
"__NSConstantStringImpl"));
2562 FieldTypes[1] = Context->
IntTy;
2566 FieldTypes[3] = Context->
LongTy;
2569 for (
unsigned i = 0; i < 4; ++i) {
2574 FieldTypes[i],
nullptr,
2600 QualType castType = getSimpleFunctionType(returnType, ArgTypes,
2604 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2619 if (!SelGetUidFunctionDecl)
2620 SynthSelGetUidFunctionDecl();
2621 if (!MsgSendFunctionDecl)
2622 SynthMsgSendFunctionDecl();
2623 if (!MsgSendSuperFunctionDecl)
2624 SynthMsgSendSuperFunctionDecl();
2625 if (!MsgSendStretFunctionDecl)
2626 SynthMsgSendStretFunctionDecl();
2627 if (!MsgSendSuperStretFunctionDecl)
2628 SynthMsgSendSuperStretFunctionDecl();
2629 if (!MsgSendFpretFunctionDecl)
2630 SynthMsgSendFpretFunctionDecl();
2631 if (!GetClassFunctionDecl)
2632 SynthGetClassFunctionDecl();
2633 if (!GetSuperClassFunctionDecl)
2634 SynthGetSuperClassFunctionDecl();
2635 if (!GetMetaClassFunctionDecl)
2636 SynthGetMetaClassFunctionDecl();
2643 QualType resultType = mDecl->getReturnType();
2645 MsgSendStretFlavor = MsgSendStretFunctionDecl;
2647 MsgSendFlavor = MsgSendFpretFunctionDecl;
2654 MsgSendFlavor = MsgSendSuperFunctionDecl;
2655 if (MsgSendStretFlavor)
2656 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2657 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2664 InitExprs.push_back(
2677 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2678 ClsExprs, StartLoc, EndLoc);
2680 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2684 ClsExprs.push_back(ArgExpr);
2685 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2689 InitExprs.push_back(
2690 NoTypeInfoCStyleCastExpr(Context,
2694 QualType superType = getSuperStructType();
2697 if (LangOpts.MicrosoftExt) {
2698 SynthSuperConstructorFunctionDecl();
2703 SuperRep =
new (Context)
CallExpr(*Context, DRE, InitExprs,
2716 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2718 CK_BitCast, SuperRep);
2735 MsgExprs.push_back(SuperRep);
2744 ClsExprs.push_back(getStringLiteral(clsName->
getName()));
2745 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2747 MsgExprs.push_back(Cls);
2752 MsgSendFlavor = MsgSendSuperFunctionDecl;
2753 if (MsgSendStretFlavor)
2754 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2755 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2759 InitExprs.push_back(
2771 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2774 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2778 ClsExprs.push_back(ArgExpr);
2779 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2784 InitExprs.push_back(
2789 QualType superType = getSuperStructType();
2792 if (LangOpts.MicrosoftExt) {
2793 SynthSuperConstructorFunctionDecl();
2798 SuperRep =
new (Context)
CallExpr(*Context, DRE, InitExprs,
2810 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2812 CK_BitCast, SuperRep);
2824 MsgExprs.push_back(SuperRep);
2833 recExpr = CE->getSubExpr();
2836 ? CK_BlockPointerToObjCPointerCast
2837 : CK_CPointerToObjCPointerCast;
2839 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
2841 MsgExprs.push_back(recExpr);
2849 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2850 SelExprs, StartLoc, EndLoc);
2851 MsgExprs.push_back(SelExp);
2854 for (
unsigned i = 0; i < Exp->
getNumArgs(); i++) {
2860 if (needToScanForQualifiers(type))
2863 (void)convertBlockPointerToFunctionPointer(type);
2868 CK = CK_IntegralToBoolean;
2871 CK = CK_BlockPointerToObjCPointerCast;
2873 CK = CK_CPointerToObjCPointerCast;
2881 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2884 else if (
CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2885 if (CE->getType()->isObjCQualifiedIdType()) {
2886 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2887 userExpr = CE->getSubExpr();
2890 CK = CK_IntegralToPointer;
2892 CK = CK_BlockPointerToObjCPointerCast;
2894 CK = CK_CPointerToObjCPointerCast;
2898 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
2902 MsgExprs.push_back(userExpr);
2914 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2915 ArgTypes.push_back(Context->
getPointerType(getSuperStructType()));
2926 (void)convertBlockPointerToFunctionPointer(t);
2927 ArgTypes.push_back(t);
2930 convertToUnqualifiedObjCType(returnType);
2931 (void)convertBlockPointerToFunctionPointer(returnType);
2946 cast = NoTypeInfoCStyleCastExpr(Context,
2954 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() :
true);
2956 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2965 Stmt *ReplacingStmt = CE;
2966 if (MsgSendStretFlavor) {
2972 CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
2973 msgSendType, returnType,
2990 llvm::APInt(IntSize, 8),
3007 return ReplacingStmt;
3015 ReplaceStmt(Exp, ReplacingStmt);
3018 return ReplacingStmt;
3022 QualType RewriteObjC::getProtocolType() {
3023 if (!ProtocolTypeDecl) {
3052 ReplaceStmt(Exp, castExpr);
3058 bool RewriteObjC::BufferContainsPPDirectives(
const char *startBuf,
3059 const char *endBuf) {
3060 while (startBuf < endBuf) {
3061 if (*startBuf ==
'#') {
3063 for (++startBuf; startBuf[0] ==
' ' || startBuf[0] ==
'\t'; ++startBuf)
3065 if (!strncmp(startBuf,
"if", strlen(
"if")) ||
3066 !strncmp(startBuf,
"ifdef", strlen(
"ifdef")) ||
3067 !strncmp(startBuf,
"ifndef", strlen(
"ifndef")) ||
3068 !strncmp(startBuf,
"define", strlen(
"define")) ||
3069 !strncmp(startBuf,
"undef", strlen(
"undef")) ||
3070 !strncmp(startBuf,
"else", strlen(
"else")) ||
3071 !strncmp(startBuf,
"elif", strlen(
"elif")) ||
3072 !strncmp(startBuf,
"endif", strlen(
"endif")) ||
3073 !strncmp(startBuf,
"pragma", strlen(
"pragma")) ||
3074 !strncmp(startBuf,
"include", strlen(
"include")) ||
3075 !strncmp(startBuf,
"import", strlen(
"import")) ||
3076 !strncmp(startBuf,
"include_next", strlen(
"include_next")))
3088 assert(CDecl &&
"Class missing in SynthesizeObjCInternalStruct");
3089 assert(CDecl->
getName() !=
"" &&
3090 "Name missing in SynthesizeObjCInternalStruct");
3092 if (ObjCSynthesizedStructs.count(CDecl))
3105 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3107 ReplaceText(LocStart, endBuf-startBuf, Result);
3113 Result +=
"\nstruct ";
3115 if (LangOpts.MicrosoftExt)
3119 const char *cursor = strchr(startBuf,
'{');
3120 assert((cursor && endBuf)
3121 &&
"SynthesizeObjCInternalStruct - malformed @interface");
3137 if (BufferContainsPPDirectives(startBuf, cursor)) {
3145 while (endHeader < cursor && *endHeader != '>
') endHeader++; 3148 // rewrite the original header 3149 ReplaceText(LocStart, endHeader-startBuf, Result); 3151 // rewrite the original header *without* disturbing the '{
' 3152 ReplaceText(LocStart, cursor-startBuf, Result); 3154 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 3155 Result = "\n struct "; 3156 Result += RCDecl->getNameAsString(); 3158 Result += RCDecl->getNameAsString(); 3159 Result += "_IVARS;\n"; 3161 // insert the super class structure definition. 3162 SourceLocation OnePastCurly = 3163 LocStart.getLocWithOffset(cursor-startBuf+1); 3164 InsertText(OnePastCurly, Result); 3166 cursor++; // past '{
' 3168 // Now comment out any visibility specifiers. 3169 while (cursor < endBuf) { 3170 if (*cursor == '@
') { 3171 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3173 for (++cursor; cursor[0] == ' ' || cursor[0] == '\t
'; ++cursor) 3176 // FIXME: presence of @public, etc. inside comment results in 3177 // this transformation as well, which is still correct c-code. 3178 if (!strncmp(cursor, "public", strlen("public")) || 3179 !strncmp(cursor, "private", strlen("private")) || 3180 !strncmp(cursor, "package", strlen("package")) || 3181 !strncmp(cursor, "protected", strlen("protected"))) 3182 InsertText(atLoc, "// "); 3184 // FIXME: If there are cases where '<
' is used in ivar declaration part 3185 // of user code, then scan the ivar list and use needToScanForQualifiers 3186 // for type checking. 3187 else if (*cursor == '<
') { 3188 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3189 InsertText(atLoc, "/* "); 3190 cursor = strchr(cursor, '>
'); 3192 atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3193 InsertText(atLoc, " */"); 3194 } else if (*cursor == '^
') { // rewrite block specifier. 3195 SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf); 3196 ReplaceText(caretLoc, 1, "*"); 3200 // Don't forget to add a
';'!!
3204 Result +=
" {\n struct ";
3208 Result +=
"_IVARS;\n};\n";
3209 ReplaceText(LocStart, endBuf-startBuf, Result);
3212 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3213 llvm_unreachable(
"struct already synthesize- SynthesizeObjCInternalStruct");
3223 void RewriteObjC::RewriteImplementations() {
3224 int ClsDefCount = ClassImplementation.size();
3225 int CatDefCount = CategoryImplementation.size();
3228 for (
int i = 0; i < ClsDefCount; i++)
3229 RewriteImplementationDecl(ClassImplementation[i]);
3231 for (
int i = 0; i < CatDefCount; i++)
3232 RewriteImplementationDecl(CategoryImplementation[i]);
3235 void RewriteObjC::RewriteByRefString(std::string &ResultStr,
3236 const std::string &Name,
3238 assert(BlockByRefDeclNo.count(VD) &&
3239 "RewriteByRefString: ByRef decl missing");
3241 ResultStr +=
"struct ";
3242 ResultStr +=
"__Block_byref_" + Name +
3243 "_" + utostr(BlockByRefDeclNo[VD]) ;
3247 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3248 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3252 std::string RewriteObjC::SynthesizeBlockFunc(
BlockExpr *CE,
int i,
3257 std::string StructRef =
"struct " + Tag;
3259 funcName.str() +
"_" +
"block_func_" + utostr(i);
3263 if (isa<FunctionNoProtoType>(AFT)) {
3266 S +=
"(" + StructRef +
" *__cself)";
3268 S +=
"(" + StructRef +
" *__cself)";
3271 assert(FT &&
"SynthesizeBlockFunc: No function proto");
3274 S += StructRef +
" *__cself, ";
3275 std::string ParamStr;
3279 ParamStr = (*AI)->getNameAsString();
3281 (void)convertBlockPointerToFunctionPointer(QT);
3296 E = BlockByRefDecls.end(); I != E; ++I) {
3298 std::string Name = (*I)->getNameAsString();
3299 std::string TypeString;
3300 RewriteByRefString(TypeString, Name, (*I));
3302 Name = TypeString + Name;
3303 S += Name +
" = __cself->" + (*I)->getNameAsString() +
"; // bound by ref\n";
3307 E = BlockByCopyDecls.end(); I != E; ++I) {
3319 if (isTopLevelBlockPointerType((*I)->getType())) {
3320 RewriteBlockPointerTypeVariable(S, (*I));
3322 RewriteBlockPointerType(S, (*I)->getType());
3324 S +=
"__cself->" + (*I)->getNameAsString() +
"; // bound by copy\n";
3327 std::string Name = (*I)->getNameAsString();
3332 S += Name +
" = __cself->" +
3333 (*I)->getNameAsString() +
"; // bound by copy\n";
3336 std::string RewrittenStr = RewrittenBlockExprs[CE];
3337 const char *cstr = RewrittenStr.c_str();
3338 while (*cstr++ !=
'{') ;
3344 std::string RewriteObjC::SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
3347 std::string StructRef =
"struct " + Tag;
3348 std::string S =
"static void __";
3351 S +=
"_block_copy_" + utostr(i);
3352 S +=
"(" + StructRef;
3353 S +=
"*dst, " + StructRef;
3355 for (
ValueDecl *VD : ImportedBlockDecls) {
3356 S +=
"_Block_object_assign((void*)&dst->";
3358 S +=
", (void*)src->";
3360 if (BlockByRefDeclsPtrSet.count(VD))
3369 S +=
"\nstatic void __";
3371 S +=
"_block_dispose_" + utostr(i);
3372 S +=
"(" + StructRef;
3374 for (
ValueDecl *VD : ImportedBlockDecls) {
3375 S +=
"_Block_object_dispose((void*)src->";
3377 if (BlockByRefDeclsPtrSet.count(VD))
3388 std::string RewriteObjC::SynthesizeBlockImpl(
BlockExpr *CE, std::string Tag,
3390 std::string S =
"\nstruct " + Tag;
3391 std::string Constructor =
" " + Tag;
3393 S +=
" {\n struct __block_impl impl;\n";
3394 S +=
" struct " + Desc;
3397 Constructor +=
"(void *fp, ";
3398 Constructor +=
"struct " + Desc;
3399 Constructor +=
" *desc";
3401 if (BlockDeclRefs.size()) {
3404 E = BlockByCopyDecls.end(); I != E; ++I) {
3406 std::string FieldName = (*I)->getNameAsString();
3407 std::string ArgName =
"_" + FieldName;
3418 if (isTopLevelBlockPointerType((*I)->getType())) {
3419 S +=
"struct __block_impl *";
3420 Constructor +=
", void *" + ArgName;
3427 Constructor +=
", " + ArgName;
3429 S += FieldName +
";\n";
3433 E = BlockByRefDecls.end(); I != E; ++I) {
3435 std::string FieldName = (*I)->getNameAsString();
3436 std::string ArgName =
"_" + FieldName;
3438 std::string TypeString;
3439 RewriteByRefString(TypeString, FieldName, (*I));
3441 FieldName = TypeString + FieldName;
3442 ArgName = TypeString + ArgName;
3443 Constructor +=
", " + ArgName;
3445 S += FieldName +
"; // by ref\n";
3448 Constructor +=
", int flags=0)";
3450 bool firsTime =
true;
3452 E = BlockByCopyDecls.end(); I != E; ++I) {
3453 std::string Name = (*I)->getNameAsString();
3455 Constructor +=
" : ";
3459 Constructor +=
", ";
3460 if (isTopLevelBlockPointerType((*I)->getType()))
3461 Constructor += Name +
"((struct __block_impl *)_" + Name +
")";
3463 Constructor += Name +
"(_" + Name +
")";
3467 E = BlockByRefDecls.end(); I != E; ++I) {
3468 std::string Name = (*I)->getNameAsString();
3470 Constructor +=
" : ";
3474 Constructor +=
", ";
3475 Constructor += Name +
"(_" + Name +
"->__forwarding)";
3478 Constructor +=
" {\n";
3480 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3482 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3483 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3485 Constructor +=
" Desc = desc;\n";
3488 Constructor +=
", int flags=0) {\n";
3490 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3492 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3493 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3494 Constructor +=
" Desc = desc;\n";
3497 Constructor +=
"}\n";
3503 std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
3504 std::string ImplTag,
int i,
3507 std::string S =
"\nstatic struct " + DescTag;
3509 S +=
" {\n unsigned long reserved;\n";
3510 S +=
" unsigned long Block_size;\n";
3512 S +=
" void (*copy)(struct ";
3513 S += ImplTag; S +=
"*, struct ";
3514 S += ImplTag; S +=
"*);\n";
3516 S +=
" void (*dispose)(struct ";
3517 S += ImplTag; S +=
"*);\n";
3521 S += DescTag +
"_DATA = { 0, sizeof(struct ";
3524 S +=
", __" + FunName.str() +
"_block_copy_" + utostr(i);
3525 S +=
", __" + FunName.str() +
"_block_dispose_" + utostr(i);
3531 void RewriteObjC::SynthesizeBlockLiterals(
SourceLocation FunLocStart,
3532 StringRef FunName) {
3534 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3535 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3536 bool RewriteSC = (GlobalVarDecl &&
3541 std::string SC(
" void __");
3544 InsertText(FunLocStart, SC);
3548 for (
unsigned i = 0, count=0; i < Blocks.size(); i++) {
3549 CollectBlockDeclRefInfo(Blocks[i]);
3552 for (
int j = 0; j < InnerDeclRefsCount[i]; j++) {
3555 BlockDeclRefs.push_back(Exp);
3556 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
3557 BlockByCopyDeclsPtrSet.insert(VD);
3558 BlockByCopyDecls.push_back(VD);
3560 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
3561 BlockByRefDeclsPtrSet.insert(VD);
3562 BlockByRefDecls.push_back(VD);
3566 if (VD->
hasAttr<BlocksAttr>() ||
3569 ImportedBlockDecls.insert(VD);
3572 std::string ImplTag =
"__" + FunName.str() +
"_block_impl_" + utostr(i);
3573 std::string DescTag =
"__" + FunName.str() +
"_block_desc_" + utostr(i);
3575 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3577 InsertText(FunLocStart, CI);
3579 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3581 InsertText(FunLocStart, CF);
3583 if (ImportedBlockDecls.size()) {
3584 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3585 InsertText(FunLocStart, HF);
3587 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3588 ImportedBlockDecls.size() > 0);
3589 InsertText(FunLocStart, BD);
3591 BlockDeclRefs.clear();
3592 BlockByRefDecls.clear();
3593 BlockByRefDeclsPtrSet.clear();
3594 BlockByCopyDecls.clear();
3595 BlockByCopyDeclsPtrSet.clear();
3596 ImportedBlockDecls.clear();
3610 InsertText(FunLocStart, SC);
3614 InnerDeclRefsCount.clear();
3615 InnerDeclRefs.clear();
3616 RewrittenBlockExprs.clear();
3619 void RewriteObjC::InsertBlockLiteralsWithinFunction(
FunctionDecl *FD) {
3621 StringRef FuncName = FD->
getName();
3623 SynthesizeBlockLiterals(FunLocStart, FuncName);
3632 std::string::size_type loc = 0;
3633 while ((loc = Name.find(
':', loc)) != std::string::npos)
3634 Name.replace(loc, 1,
"_");
3637 void RewriteObjC::InsertBlockLiteralsWithinMethod(
ObjCMethodDecl *MD) {
3641 std::string FuncName;
3643 SynthesizeBlockLiterals(FunLocStart, FuncName);
3646 void RewriteObjC::GetBlockDeclRefExprs(
Stmt *S) {
3649 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
3650 GetBlockDeclRefExprs(CBE->getBody());
3652 GetBlockDeclRefExprs(SubStmt);
3656 if (DRE->refersToEnclosingVariableOrCapture() ||
3659 BlockDeclRefs.push_back(DRE);
3662 void RewriteObjC::GetInnerBlockDeclRefExprs(
Stmt *S,
3664 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
3667 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
3668 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
3669 GetInnerBlockDeclRefExprs(CBE->getBody(),
3674 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
3677 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3678 if (DRE->refersToEnclosingVariableOrCapture() ||
3680 if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
3681 InnerBlockDeclRefs.push_back(DRE);
3682 if (
VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
3683 if (Var->isFunctionOrMethodVarDecl())
3684 ImportedLocalExternalDecls.insert(Var);
3699 bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
3705 if (convertBlockPointerToFunctionPointer(t))
3706 HasBlockType =
true;
3707 ArgTypes.push_back(t);
3714 FuncType = getSimpleFunctionType(Res, ArgTypes);
3719 Stmt *RewriteObjC::SynthesizeBlockCall(
CallExpr *Exp,
const Expr *BlockExp) {
3723 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3725 }
else if (
const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3728 else if (
const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3729 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3731 else if (
const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3734 dyn_cast<ConditionalOperator>(BlockExp)) {
3735 Expr *LHSExp = CEXPR->getLHS();
3736 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3737 Expr *RHSExp = CEXPR->getRHS();
3738 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3739 Expr *CONDExp = CEXPR->getCond();
3746 }
else if (
const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3749 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
3752 assert(
false &&
"RewriteBlockClass: Bad type");
3754 assert(CPT &&
"RewriteBlockClass: Bad type");
3756 assert(FT &&
"RewriteBlockClass: Bad type");
3769 ArgTypes.push_back(PtrBlock);
3774 if (!convertBlockPointerToFunctionPointer(t))
3775 convertToUnqualifiedObjCType(t);
3776 ArgTypes.push_back(t);
3780 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->
getType(), ArgTypes);
3784 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
3786 const_cast<Expr*>(BlockExp));
3802 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
3808 BlkExprs.push_back(BlkCast);
3811 E = Exp->
arg_end(); I != E; ++I) {
3812 BlkExprs.push_back(*I);
3850 StringRef Name = VD->
getName();
3864 ReplaceStmt(DeclRefExp, PE);
3871 Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(
DeclRefExpr *DRE) {
3873 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3874 if (!ImportedLocalExternalDecls.count(Var))
3882 ReplaceStmt(DRE, PE);
3900 const Type* TypePtr = QT->
getAs<Type>();
3901 if (isa<TypeOfExprType>(TypePtr)) {
3902 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
3904 std::string TypeAsString =
"(";
3905 RewriteBlockPointerType(TypeAsString, QT);
3906 TypeAsString +=
")";
3907 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
3911 const char *argPtr = startBuf;
3913 while (*argPtr++ && (argPtr < endBuf)) {
3918 ReplaceText(LocStart, 1,
"*");
3924 void RewriteObjC::RewriteBlockPointerFunctionArgs(
FunctionDecl *FD) {
3926 unsigned parenCount = 0;
3930 const char *startArgList = strchr(startBuf,
'(');
3932 assert((*startArgList ==
'(') &&
"Rewriter fuzzy parser confused");
3937 assert((DeclLoc.
isValid()) &&
"Invalid DeclLoc");
3939 const char *argPtr = startArgList;
3941 while (*argPtr++ && parenCount) {
3946 ReplaceText(DeclLoc, 1,
"*");
3958 bool RewriteObjC::PointerTypeTakesAnyBlockArguments(
QualType QT) {
3965 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3970 if (isTopLevelBlockPointerType(I))
3976 bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(
QualType QT) {
3983 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3988 if (I->isObjCQualifiedIdType())
3990 if (I->isObjCObjectPointerType() &&
3991 I->getPointeeType()->isObjCQualifiedInterfaceType())
3999 void RewriteObjC::GetExtentOfArgList(
const char *Name,
const char *&LParen,
4000 const char *&RParen) {
4001 const char *argPtr = strchr(Name,
'(');
4002 assert((*argPtr ==
'(') &&
"Rewriter fuzzy parser confused");
4006 unsigned parenCount = 1;
4008 while (*argPtr && parenCount) {
4010 case '(': parenCount++;
break;
4011 case ')': parenCount--;
break;
4014 if (parenCount) argPtr++;
4016 assert((*argPtr ==
')') &&
"Rewriter fuzzy parser confused");
4020 void RewriteObjC::RewriteBlockPointerDecl(
NamedDecl *ND) {
4022 RewriteBlockPointerFunctionArgs(FD);
4028 if (
VarDecl *VD = dyn_cast<VarDecl>(ND))
4031 DeclT = TDD->getUnderlyingType();
4032 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4035 llvm_unreachable(
"RewriteBlockPointerDecl(): Decl type not yet handled");
4038 const char *endBuf = startBuf;
4040 while (*startBuf !=
'^' && *startBuf !=
';' && startBuf != MainFileStart)
4044 unsigned OrigLength=0;
4047 if (*startBuf ==
'^') {
4053 while (*startBuf !=
')') {
4061 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4062 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4067 const char *argListBegin, *argListEnd;
4068 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4069 while (argListBegin < argListEnd) {
4070 if (*argListBegin ==
'^')
4072 else if (*argListBegin ==
'<') {
4074 buf += *argListBegin++;
4076 while (*argListBegin !=
'>') {
4077 buf += *argListBegin++;
4080 buf += *argListBegin;
4084 buf += *argListBegin;
4091 ReplaceText(Start, OrigLength, buf);
4114 std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
4117 if (CopyDestroyCache.count(flag))
4119 CopyDestroyCache.insert(flag);
4120 S =
"static void __Block_byref_id_object_copy_";
4122 S +=
"(void *dst, void *src) {\n";
4128 unsigned VoidPtrSize =
4131 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->
getCharWidth();
4132 S +=
" _Block_object_assign((char*)dst + ";
4133 S += utostr(offset);
4134 S +=
", *(void * *) ((char*)src + ";
4135 S += utostr(offset);
4140 S +=
"static void __Block_byref_id_object_dispose_";
4142 S +=
"(void *src) {\n";
4143 S +=
" _Block_object_dispose(*(void * *) ((char*)src + ";
4144 S += utostr(offset);
4169 void RewriteObjC::RewriteByRefVar(
VarDecl *ND) {
4172 if (CurFunctionDeclToDeclareForBlock)
4173 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4186 std::string ByrefType;
4187 RewriteByRefString(ByrefType, Name, ND,
true);
4188 ByrefType +=
" {\n";
4189 ByrefType +=
" void *__isa;\n";
4190 RewriteByRefString(ByrefType, Name, ND);
4191 ByrefType +=
" *__forwarding;\n";
4192 ByrefType +=
" int __flags;\n";
4193 ByrefType +=
" int __size;\n";
4198 if (HasCopyAndDispose) {
4199 ByrefType +=
" void (*__Block_byref_id_object_copy)(void*, void*);\n";
4200 ByrefType +=
" void (*__Block_byref_id_object_dispose)(void*);\n";
4204 (void)convertBlockPointerToFunctionPointer(T);
4207 ByrefType +=
" " + Name +
";\n";
4208 ByrefType +=
"};\n";
4214 assert(CurMethodDef &&
"RewriteByRefVar - CurMethodDef is null");
4217 InsertText(FunLocStart, ByrefType);
4223 if (HasCopyAndDispose) {
4231 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4233 InsertText(FunLocStart, HF);
4239 bool hasInit = (ND->
getInit() !=
nullptr);
4241 if (HasCopyAndDispose)
4245 RewriteByRefString(ByrefType, Name, ND);
4246 std::string ForwardingCastType(
"(");
4247 ForwardingCastType += ByrefType +
" *)";
4249 ByrefType +=
" " + Name +
" = {(void*)";
4250 ByrefType += utostr(isa);
4251 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4252 ByrefType += utostr(flags);
4254 ByrefType +=
"sizeof(";
4255 RewriteByRefString(ByrefType, Name, ND);
4257 if (HasCopyAndDispose) {
4258 ByrefType +=
", __Block_byref_id_object_copy_";
4259 ByrefType += utostr(flag);
4260 ByrefType +=
", __Block_byref_id_object_dispose_";
4261 ByrefType += utostr(flag);
4263 ByrefType +=
"};\n";
4264 unsigned nameSize = Name.size();
4269 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4275 startLoc = ECE->getLParenLoc();
4280 ByrefType +=
" " + Name;
4281 ByrefType +=
" = {(void*)";
4282 ByrefType += utostr(isa);
4283 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4284 ByrefType += utostr(flags);
4286 ByrefType +=
"sizeof(";
4287 RewriteByRefString(ByrefType, Name, ND);
4289 if (HasCopyAndDispose) {
4290 ByrefType +=
"__Block_byref_id_object_copy_";
4291 ByrefType += utostr(flag);
4292 ByrefType +=
", __Block_byref_id_object_dispose_";
4293 ByrefType += utostr(flag);
4296 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4307 const char *semiBuf = strchr(startInitializerBuf,
';');
4308 assert((*semiBuf ==
';') &&
"RewriteByRefVar: can't find ';'");
4312 InsertText(semiLoc,
"}");
4316 void RewriteObjC::CollectBlockDeclRefInfo(
BlockExpr *Exp) {
4318 GetBlockDeclRefExprs(Exp->
getBody());
4319 if (BlockDeclRefs.size()) {
4321 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4322 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4323 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4324 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4325 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
4329 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4330 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4331 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4332 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4333 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
4337 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4338 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4339 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4340 BlockDeclRefs[i]->getType()->isBlockPointerType())
4341 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4345 FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
4356 Blocks.push_back(Exp);
4358 CollectBlockDeclRefInfo(Exp);
4361 int countOfInnerDecls = 0;
4362 if (!InnerBlockDeclRefs.empty()) {
4363 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
4366 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
4370 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4371 BlockDeclRefs.push_back(Exp);
4372 BlockByCopyDeclsPtrSet.insert(VD);
4373 BlockByCopyDecls.push_back(VD);
4375 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
4376 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4377 BlockDeclRefs.push_back(Exp);
4378 BlockByRefDeclsPtrSet.insert(VD);
4379 BlockByRefDecls.push_back(VD);
4383 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
4384 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4385 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4386 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
4387 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4389 InnerDeclRefsCount.push_back(countOfInnerDecls);
4391 std::string FuncName;
4395 else if (CurMethodDef)
4397 else if (GlobalVarDecl)
4400 std::string BlockNumber = utostr(Blocks.size()-1);
4402 std::string Tag =
"__" + FuncName +
"_block_impl_" + BlockNumber;
4403 std::string Func =
"__" + FuncName +
"_block_func_" + BlockNumber;
4413 FD = SynthBlockInitFunctionDecl(Tag);
4420 FD = SynthBlockInitFunctionDecl(Func);
4425 InitExprs.push_back(castExpr);
4428 std::string DescData =
"__" + FuncName +
"_block_desc_" + BlockNumber +
"_DATA";
4442 InitExprs.push_back(DescRefExpr);
4445 if (BlockDeclRefs.size()) {
4449 E = BlockByCopyDecls.end(); I != E; ++I) {
4450 if (isObjCType((*I)->getType())) {
4452 FD = SynthBlockInitFunctionDecl((*I)->getName());
4462 }
else if (isTopLevelBlockPointerType((*I)->getType())) {
4463 FD = SynthBlockInitFunctionDecl((*I)->getName());
4466 Exp = NoTypeInfoCStyleCastExpr(Context, Context->
VoidPtrTy,
4469 FD = SynthBlockInitFunctionDecl((*I)->getName());
4480 InitExprs.push_back(Exp);
4484 E = BlockByRefDecls.end(); I != E; ++I) {
4487 std::string RecName;
4488 RewriteByRefString(RecName, Name, ND,
true);
4490 +
sizeof(
"struct"));
4494 assert(RD &&
"SynthBlockInitExpr(): Can't find RecordDecl");
4497 FD = SynthBlockInitFunctionDecl((*I)->getName());
4500 bool isNestedCapturedVar =
false;
4502 for (
const auto &CI : block->
captures()) {
4503 const VarDecl *variable = CI.getVariable();
4504 if (variable == ND && CI.isNested()) {
4505 assert (CI.isByRef() &&
4506 "SynthBlockInitExpr - captured block variable is not byref");
4507 isNestedCapturedVar =
true;
4513 if (!isNestedCapturedVar)
4517 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
4518 InitExprs.push_back(Exp);
4521 if (ImportedBlockDecls.size()) {
4528 InitExprs.push_back(FlagExp);
4530 NewRep =
new (Context)
CallExpr(*Context, DRE, InitExprs,
4535 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
4537 BlockDeclRefs.clear();
4538 BlockByRefDecls.clear();
4539 BlockByRefDeclsPtrSet.clear();
4540 BlockByCopyDecls.clear();
4541 BlockByCopyDeclsPtrSet.clear();
4542 ImportedBlockDecls.clear();
4546 bool RewriteObjC::IsDeclStmtInForeachHeader(
DeclStmt *DS) {
4548 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4549 return CS->getElement() == DS;
4557 Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(
Stmt *S) {
4558 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4559 isa<DoStmt>(S) || isa<ForStmt>(S))
4561 else if (isa<ObjCForCollectionStmt>(S)) {
4563 ObjCBcLabelNo.push_back(++BcLabelCount);
4570 return RewritePropertyOrImplicitSetter(PseudoOp);
4572 return RewritePropertyOrImplicitGetter(PseudoOp);
4574 }
else if (
ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4575 return RewriteObjCIvarRefExpr(IvarRefExpr);
4583 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4585 childStmt = newStmt;
4589 if (
BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
4591 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
4592 InnerContexts.insert(BE->getBlockDecl());
4593 ImportedLocalExternalDecls.clear();
4594 GetInnerBlockDeclRefExprs(BE->getBody(),
4595 InnerBlockDeclRefs, InnerContexts);
4597 Stmt *SaveCurrentBody = CurrentBody;
4598 CurrentBody = BE->getBody();
4599 PropParentMap =
nullptr;
4605 bool saveDisableReplaceStmt = DisableReplaceStmt;
4606 DisableReplaceStmt =
false;
4607 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4608 DisableReplaceStmt = saveDisableReplaceStmt;
4609 CurrentBody = SaveCurrentBody;
4610 PropParentMap =
nullptr;
4611 ImportedLocalExternalDecls.clear();
4614 RewrittenBlockExprs[BE] = Str;
4616 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4619 ReplaceStmt(S, blockTranscribed);
4620 return blockTranscribed;
4624 return RewriteAtEncode(AtEncode);
4627 return RewriteAtSelector(AtSelector);
4630 return RewriteObjCStringLiteral(AtString);
4641 std::string messString;
4642 messString +=
"// ";
4643 messString.append(startBuf, endBuf-startBuf+1);
4652 return RewriteMessageExpr(MessExpr);
4656 return RewriteObjCTryStmt(StmtTry);
4659 return RewriteObjCSynchronizedStmt(StmtTry);
4662 return RewriteObjCThrowStmt(StmtThrow);
4665 return RewriteObjCProtocolExpr(ProtocolExp);
4668 dyn_cast<ObjCForCollectionStmt>(S))
4669 return RewriteObjCForCollectionStmt(StmtForCollection,
4672 dyn_cast<BreakStmt>(S))
4673 return RewriteBreakStmt(StmtBreakStmt);
4675 dyn_cast<ContinueStmt>(S))
4676 return RewriteContinueStmt(StmtContinueStmt);
4680 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4690 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4691 RewriteObjCQualifiedInterfaceTypes(*DS->
decl_begin());
4694 for (
auto *SD : DS->
decls()) {
4695 if (
ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4696 if (isTopLevelBlockPointerType(ND->
getType()))
4697 RewriteBlockPointerDecl(ND);
4699 CheckFunctionPointerDecl(ND->
getType(), ND);
4700 if (
VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4701 if (VD->
hasAttr<BlocksAttr>()) {
4702 static unsigned uniqueByrefDeclCount = 0;
4703 assert(!BlockByRefDeclNo.count(ND) &&
4704 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4705 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4706 RewriteByRefVar(VD);
4709 RewriteTypeOfDecl(VD);
4713 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4714 RewriteBlockPointerDecl(TD);
4715 else if (TD->getUnderlyingType()->isFunctionPointerType())
4716 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4722 RewriteObjCQualifiedInterfaceTypes(CE);
4724 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4725 isa<DoStmt>(S) || isa<ForStmt>(S)) {
4726 assert(!Stmts.empty() &&
"Statement stack is empty");
4727 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
4728 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
4729 &&
"Statement stack mismatch");
4733 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4735 if (VD->
hasAttr<BlocksAttr>())
4736 return RewriteBlockDeclRefExpr(DRE);
4738 return RewriteLocalVariableExternalStorage(DRE);
4741 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
4744 ReplaceStmt(S, BlockCall);
4749 RewriteCastExpr(CE);
4758 llvm::raw_string_ostream Buf(SStr);
4760 const std::string &Str = Buf.str();
4762 printf(
"CAST = %s\n", &Str[0]);
4763 InsertText(ICE->getSubExpr()->getLocStart(), Str);
4772 void RewriteObjC::RewriteRecordBody(
RecordDecl *RD) {
4773 for (
auto *FD : RD->
fields()) {
4774 if (isTopLevelBlockPointerType(FD->
getType()))
4775 RewriteBlockPointerDecl(FD);
4778 RewriteObjCQualifiedInterfaceTypes(FD);
4784 void RewriteObjC::HandleDeclInMainFile(
Decl *D) {
4794 RewriteBlocksInFunctionProtoType(FD->
getType(), FD);
4801 CurFunctionDef = FD;
4802 CurFunctionDeclToDeclareForBlock = FD;
4805 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4807 CurrentBody =
nullptr;
4808 if (PropParentMap) {
4809 delete PropParentMap;
4810 PropParentMap =
nullptr;
4814 InsertBlockLiteralsWithinFunction(FD);
4815 CurFunctionDef =
nullptr;
4816 CurFunctionDeclToDeclareForBlock =
nullptr;
4820 case Decl::ObjCMethod: {
4826 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4828 CurrentBody =
nullptr;
4829 if (PropParentMap) {
4830 delete PropParentMap;
4831 PropParentMap =
nullptr;
4833 InsertBlockLiteralsWithinMethod(MD);
4834 CurMethodDef =
nullptr;
4838 case Decl::ObjCImplementation: {
4840 ClassImplementation.push_back(CI);
4843 case Decl::ObjCCategoryImpl: {
4845 CategoryImplementation.push_back(CI);
4849 VarDecl *VD = cast<VarDecl>(D);
4850 RewriteObjCQualifiedInterfaceTypes(VD);
4851 if (isTopLevelBlockPointerType(VD->
getType()))
4852 RewriteBlockPointerDecl(VD);
4854 CheckFunctionPointerDecl(VD->
getType(), VD);
4857 RewriteCastExpr(CE);
4863 RewriteRecordBody(RD);
4868 RewriteFunctionBodyOrGlobalInitializer(VD->
getInit());
4869 CurrentBody =
nullptr;
4870 if (PropParentMap) {
4871 delete PropParentMap;
4872 PropParentMap =
nullptr;
4875 GlobalVarDecl =
nullptr;
4879 RewriteCastExpr(CE);
4884 case Decl::TypeAlias:
4885 case Decl::Typedef: {
4887 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4888 RewriteBlockPointerDecl(TD);
4889 else if (TD->getUnderlyingType()->isFunctionPointerType())
4890 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4894 case Decl::CXXRecord:
4895 case Decl::Record: {
4898 RewriteRecordBody(RD);
4907 void RewriteObjC::HandleTranslationUnit(
ASTContext &
C) {
4916 RewriteObjCProtocolMetaData(ProtDecl,
"",
"", Preamble);
4919 if (ClassImplementation.size() || CategoryImplementation.size())
4920 RewriteImplementations();
4927 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
4929 llvm::errs() <<
"No changes\n";
4932 if (ClassImplementation.size() || CategoryImplementation.size() ||
4933 ProtocolExprDecls.size()) {
4935 std::string ResultStr;
4936 RewriteMetaDataIntoBuffer(ResultStr);
4938 *OutFile << ResultStr;
4943 void RewriteObjCFragileABI::Initialize(
ASTContext &context) {
4944 InitializeCommon(context);
4949 Preamble =
"#pragma once\n";
4950 Preamble +=
"struct objc_selector; struct objc_class;\n";
4951 Preamble +=
"struct __rw_objc_super { struct objc_object *object; ";
4952 Preamble +=
"struct objc_object *superClass; ";
4953 if (LangOpts.MicrosoftExt) {
4955 Preamble +=
"__rw_objc_super(struct objc_object *o, struct objc_object *s) " 4957 Preamble +=
"object(o), superClass(s) {} ";
4960 Preamble +=
"#ifndef _REWRITER_typedef_Protocol\n";
4961 Preamble +=
"typedef struct objc_object Protocol;\n";
4962 Preamble +=
"#define _REWRITER_typedef_Protocol\n";
4963 Preamble +=
"#endif\n";
4964 if (LangOpts.MicrosoftExt) {
4965 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
4966 Preamble +=
"#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
4968 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern\n";
4969 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
4970 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4971 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
4972 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4973 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
4974 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4975 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
4976 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4977 Preamble +=
"__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
4978 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4979 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
4980 Preamble +=
"(const char *);\n";
4981 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
4982 Preamble +=
"(struct objc_class *);\n";
4983 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
4984 Preamble +=
"(const char *);\n";
4985 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
4986 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
4987 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
4988 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
4989 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_exception_match";
4990 Preamble +=
"(struct objc_class *, struct objc_object *);\n";
4992 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
4993 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
4994 Preamble +=
"__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
4995 Preamble +=
"#ifndef __FASTENUMERATIONSTATE\n";
4996 Preamble +=
"struct __objcFastEnumerationState {\n\t";
4997 Preamble +=
"unsigned long state;\n\t";
4998 Preamble +=
"void **itemsPtr;\n\t";
4999 Preamble +=
"unsigned long *mutationsPtr;\n\t";
5000 Preamble +=
"unsigned long extra[5];\n};\n";
5001 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
5002 Preamble +=
"#define __FASTENUMERATIONSTATE\n";
5003 Preamble +=
"#endif\n";
5004 Preamble +=
"#ifndef __NSCONSTANTSTRINGIMPL\n";
5005 Preamble +=
"struct __NSConstantStringImpl {\n";
5006 Preamble +=
" int *isa;\n";
5007 Preamble +=
" int flags;\n";
5008 Preamble +=
" char *str;\n";
5009 Preamble +=
" long length;\n";
5011 Preamble +=
"#ifdef CF_EXPORT_CONSTANT_STRING\n";
5012 Preamble +=
"extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5013 Preamble +=
"#else\n";
5014 Preamble +=
"__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5015 Preamble +=
"#endif\n";
5016 Preamble +=
"#define __NSCONSTANTSTRINGIMPL\n";
5017 Preamble +=
"#endif\n";
5019 Preamble +=
"#ifndef BLOCK_IMPL\n";
5020 Preamble +=
"#define BLOCK_IMPL\n";
5021 Preamble +=
"struct __block_impl {\n";
5022 Preamble +=
" void *isa;\n";
5023 Preamble +=
" int Flags;\n";
5024 Preamble +=
" int Reserved;\n";
5025 Preamble +=
" void *FuncPtr;\n";
5027 Preamble +=
"// Runtime copy/destroy helper functions (from Block_private.h)\n";
5028 Preamble +=
"#ifdef __OBJC_EXPORT_BLOCKS\n";
5029 Preamble +=
"extern \"C\" __declspec(dllexport) " 5030 "void _Block_object_assign(void *, const void *, const int);\n";
5031 Preamble +=
"extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5032 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5033 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5034 Preamble +=
"#else\n";
5035 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5036 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5037 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5038 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5039 Preamble +=
"#endif\n";
5040 Preamble +=
"#endif\n";
5041 if (LangOpts.MicrosoftExt) {
5042 Preamble +=
"#undef __OBJC_RW_DLLIMPORT\n";
5043 Preamble +=
"#undef __OBJC_RW_STATICIMPORT\n";
5044 Preamble +=
"#ifndef KEEP_ATTRIBUTES\n";
5045 Preamble +=
"#define __attribute__(X)\n";
5046 Preamble +=
"#endif\n";
5047 Preamble +=
"#define __weak\n";
5050 Preamble +=
"#define __block\n";
5051 Preamble +=
"#define __weak\n";
5055 Preamble +=
"\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5060 void RewriteObjCFragileABI::RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
5061 std::string &Result) {
5067 Result +=
"__OFFSETOFIVAR__(struct ";
5069 if (LangOpts.MicrosoftExt)
5078 void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
5080 StringRef ClassName, std::string &Result) {
5081 static bool objc_protocol_methods =
false;
5090 Result +=
"\nstruct _protocol_methods {\n";
5091 Result +=
"\tstruct objc_selector *_cmd;\n";
5092 Result +=
"\tchar *method_types;\n";
5095 objc_protocol_methods =
true;
5112 Result +=
"\nstatic struct {\n";
5113 Result +=
"\tint protocol_method_count;\n";
5114 Result +=
"\tstruct _protocol_methods protocol_methods[";
5115 Result += utostr(NumMethods);
5116 Result +=
"];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
5118 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 5119 "{\n\t" + utostr(NumMethods) +
"\n";
5126 Result +=
"\t ,{{(struct objc_selector *)\"";
5128 Result +=
"\t ,{(struct objc_selector *)\"";
5129 Result += (*I)->getSelector().getAsString();
5132 Result += MethodTypeString;
5135 Result +=
"\t }\n};\n";
5141 if (NumMethods > 0) {
5147 Result +=
"\nstatic struct {\n";
5148 Result +=
"\tint protocol_method_count;\n";
5149 Result +=
"\tstruct _protocol_methods protocol_methods[";
5150 Result += utostr(NumMethods);
5151 Result +=
"];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
5153 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5155 Result += utostr(NumMethods);
5163 Result +=
"\t ,{{(struct objc_selector *)\"";
5165 Result +=
"\t ,{(struct objc_selector *)\"";
5166 Result += (*I)->getSelector().getAsString();
5169 Result += MethodTypeString;
5172 Result +=
"\t }\n};\n";
5185 static bool objc_protocol =
false;
5186 if (!objc_protocol) {
5187 Result +=
"\nstruct _objc_protocol {\n";
5188 Result +=
"\tstruct _objc_protocol_extension *isa;\n";
5189 Result +=
"\tchar *protocol_name;\n";
5190 Result +=
"\tstruct _objc_protocol **protocol_list;\n";
5191 Result +=
"\tstruct _objc_protocol_method_list *instance_methods;\n";
5192 Result +=
"\tstruct _objc_protocol_method_list *class_methods;\n";
5195 objc_protocol =
true;
5198 Result +=
"\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
5200 Result +=
" __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 5203 Result +=
"\", 0, ";
5205 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
5212 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
5222 llvm_unreachable(
"protocol already synthesized");
5225 void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
5227 StringRef prefix, StringRef ClassName,
5228 std::string &Result) {
5229 if (Protocols.
empty())
return;
5231 for (
unsigned i = 0; i != Protocols.
size(); i++)
5232 RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
5241 Result +=
"\nstatic struct {\n";
5242 Result +=
"\tstruct _objc_protocol_list *next;\n";
5243 Result +=
"\tint protocol_count;\n";
5244 Result +=
"\tstruct _objc_protocol *class_protocols[";
5245 Result += utostr(Protocols.
size());
5246 Result +=
"];\n} _OBJC_";
5248 Result +=
"_PROTOCOLS_";
5249 Result += ClassName;
5250 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5252 Result += utostr(Protocols.
size());
5255 Result +=
"\t,{&_OBJC_PROTOCOL_";
5256 Result += Protocols[0]->getNameAsString();
5259 for (
unsigned i = 1; i != Protocols.
size(); i++) {
5260 Result +=
"\t ,&_OBJC_PROTOCOL_";
5261 Result += Protocols[i]->getNameAsString();
5264 Result +=
"\t }\n};\n";
5268 std::string &Result) {
5275 RewriteObjCInternalStruct(CDecl, Result);
5283 static bool objc_ivar =
false;
5291 Result +=
"\nstruct _objc_ivar {\n";
5292 Result +=
"\tchar *ivar_name;\n";
5293 Result +=
"\tchar *ivar_type;\n";
5294 Result +=
"\tint ivar_offset;\n";
5305 Result +=
"\nstatic struct {\n";
5306 Result +=
"\tint ivar_count;\n";
5307 Result +=
"\tstruct _objc_ivar ivar_list[";
5308 Result += utostr(NumIvars);
5309 Result +=
"];\n} _OBJC_INSTANCE_VARIABLES_";
5311 Result +=
" __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 5313 Result += utostr(NumIvars);
5319 for (
auto *IV : IDecl->
ivars())
5320 IVars.push_back(IV);
5327 Result +=
"\t,{{\"";
5328 Result += IVI->getNameAsString();
5330 std::string TmpString, StrEncoding;
5332 QuoteDoublequotes(TmpString, StrEncoding);
5333 Result += StrEncoding;
5335 RewriteIvarOffsetComputation(*IVI, Result);
5337 for (++IVI; IVI != IVE; ++IVI) {
5338 Result +=
"\t ,{\"";
5339 Result += IVI->getNameAsString();
5341 std::string TmpString, StrEncoding;
5343 QuoteDoublequotes(TmpString, StrEncoding);
5344 Result += StrEncoding;
5346 RewriteIvarOffsetComputation(*IVI, Result);
5350 Result +=
"\t }\n};\n";
5361 if (!Prop->getPropertyIvarDecl())
5367 if (!Getter->isDefined())
5368 InstanceMethods.push_back(Getter);
5372 if (!Setter->isDefined())
5373 InstanceMethods.push_back(Setter);
5375 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5402 static bool objc_class =
false;
5404 Result +=
"\nstruct _objc_class {\n";
5405 Result +=
"\tstruct _objc_class *isa;\n";
5406 Result +=
"\tconst char *super_class_name;\n";
5407 Result +=
"\tchar *name;\n";
5408 Result +=
"\tlong version;\n";
5409 Result +=
"\tlong info;\n";
5410 Result +=
"\tlong instance_size;\n";
5411 Result +=
"\tstruct _objc_ivar_list *ivars;\n";
5412 Result +=
"\tstruct _objc_method_list *methods;\n";
5413 Result +=
"\tstruct objc_cache *cache;\n";
5414 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5415 Result +=
"\tconst char *ivar_layout;\n";
5416 Result +=
"\tstruct _objc_class_ext *ext;\n";
5424 while (SuperClass) {
5425 RootClass = SuperClass;
5430 Result +=
"\nstatic struct _objc_class _OBJC_METACLASS_";
5432 Result +=
" __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 5433 "{\n\t(struct _objc_class *)\"";
5445 Result +=
", 0, \"";
5451 Result +=
", 0,2, sizeof(struct _objc_class), 0";
5453 Result +=
"\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
5460 Result +=
"\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
5465 Result +=
"\t,0,0,0,0\n";
5469 Result +=
"\nstatic struct _objc_class _OBJC_CLASS_";
5471 Result +=
" __attribute__ ((used, section (\"__OBJC, __class\")))= " 5472 "{\n\t&_OBJC_METACLASS_";
5482 Result +=
", 0, \"";
5488 if (!ObjCSynthesizedStructs.count(CDecl))
5492 Result +=
",sizeof(struct ";
5494 if (LangOpts.MicrosoftExt)
5499 Result +=
", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
5506 Result +=
", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
5508 Result +=
", 0\n\t";
5513 Result +=
", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
5515 Result +=
", 0,0\n";
5518 Result +=
",0,0,0\n";
5522 void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
5523 int ClsDefCount = ClassImplementation.size();
5524 int CatDefCount = CategoryImplementation.size();
5527 for (
int i = 0; i < ClsDefCount; i++)
5528 RewriteObjCClassMetaData(ClassImplementation[i], Result);
5531 for (
int i = 0; i < CatDefCount; i++)
5532 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
5546 Result +=
"\nstruct _objc_symtab {\n";
5547 Result +=
"\tlong sel_ref_cnt;\n";
5548 Result +=
"\tSEL *refs;\n";
5549 Result +=
"\tshort cls_def_cnt;\n";
5550 Result +=
"\tshort cat_def_cnt;\n";
5551 Result +=
"\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+
"];\n";
5554 Result +=
"static struct _objc_symtab " 5555 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
5556 Result +=
"\t0, 0, " + utostr(ClsDefCount)
5557 +
", " + utostr(CatDefCount) +
"\n";
5558 for (
int i = 0; i < ClsDefCount; i++) {
5559 Result +=
"\t,&_OBJC_CLASS_";
5560 Result += ClassImplementation[i]->getNameAsString();
5564 for (
int i = 0; i < CatDefCount; i++) {
5565 Result +=
"\t,&_OBJC_CATEGORY_";
5566 Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
5568 Result += CategoryImplementation[i]->getNameAsString();
5585 Result +=
"\nstruct _objc_module {\n";
5586 Result +=
"\tlong version;\n";
5587 Result +=
"\tlong size;\n";
5588 Result +=
"\tconst char *name;\n";
5589 Result +=
"\tstruct _objc_symtab *symtab;\n";
5591 Result +=
"static struct _objc_module " 5592 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
5593 Result +=
"\t" + utostr(OBJC_ABI_VERSION) +
5594 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
5597 if (LangOpts.MicrosoftExt) {
5598 if (ProtocolExprDecls.size()) {
5599 Result +=
"#pragma section(\".objc_protocol$B\",long,read,write)\n";
5600 Result +=
"#pragma data_seg(push, \".objc_protocol$B\")\n";
5602 Result +=
"static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
5603 Result += ProtDecl->getNameAsString();
5604 Result +=
" = &_OBJC_PROTOCOL_";
5605 Result += ProtDecl->getNameAsString();
5608 Result +=
"#pragma data_seg(pop)\n\n";
5610 Result +=
"#pragma section(\".objc_module_info$B\",long,read,write)\n";
5611 Result +=
"#pragma data_seg(push, \".objc_module_info$B\")\n";
5612 Result +=
"static struct _objc_module *_POINTER_OBJC_MODULES = ";
5613 Result +=
"&_OBJC_MODULES;\n";
5614 Result +=
"#pragma data_seg(pop)\n\n";
5621 std::string &Result) {
5628 FullCategoryName +=
'_';
5639 if (!Prop->getPropertyIvarDecl())
5645 InstanceMethods.push_back(Getter);
5649 InstanceMethods.push_back(Setter);
5651 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5652 true,
"CATEGORY_", FullCategoryName,
Result);
5656 false,
"CATEGORY_", FullCategoryName,
Result);
5662 FullCategoryName,
Result);
5676 static bool objc_category =
false;
5677 if (!objc_category) {
5678 Result +=
"\nstruct _objc_category {\n";
5679 Result +=
"\tchar *category_name;\n";
5680 Result +=
"\tchar *class_name;\n";
5681 Result +=
"\tstruct _objc_method_list *instance_methods;\n";
5682 Result +=
"\tstruct _objc_method_list *class_methods;\n";
5683 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5684 Result +=
"\tunsigned int size;\n";
5685 Result +=
"\tstruct _objc_property_list *instance_properties;\n";
5687 objc_category =
true;
5689 Result +=
"\nstatic struct _objc_category _OBJC_CATEGORY_";
5690 Result += FullCategoryName;
5691 Result +=
" __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
5693 Result +=
"\"\n\t, \"";
5698 Result +=
"\t, (struct _objc_method_list *)" 5699 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
5700 Result += FullCategoryName;
5704 Result +=
"\t, 0\n";
5706 Result +=
"\t, (struct _objc_method_list *)" 5707 "&_OBJC_CATEGORY_CLASS_METHODS_";
5708 Result += FullCategoryName;
5712 Result +=
"\t, 0\n";
5715 Result +=
"\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
5716 Result += FullCategoryName;
5720 Result +=
"\t, 0\n";
5721 Result +=
"\t, sizeof(struct _objc_category), 0\n};\n";
5726 template<
typename MethodIterator>
5727 void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5728 MethodIterator MethodEnd,
5729 bool IsInstanceMethod,
5731 StringRef ClassName,
5732 std::string &Result) {
5733 if (MethodBegin == MethodEnd)
return;
5735 if (!objc_impl_method) {
5742 Result +=
"\nstruct _objc_method {\n";
5743 Result +=
"\tSEL _cmd;\n";
5744 Result +=
"\tchar *method_types;\n";
5745 Result +=
"\tvoid *_imp;\n";
5748 objc_impl_method =
true;
5759 unsigned NumMethods =
std::distance(MethodBegin, MethodEnd);
5760 Result +=
"\nstatic struct {\n";
5761 Result +=
"\tstruct _objc_method_list *next_method;\n";
5762 Result +=
"\tint method_count;\n";
5763 Result +=
"\tstruct _objc_method method_list[";
5764 Result += utostr(NumMethods);
5765 Result +=
"];\n} _OBJC_";
5767 Result += IsInstanceMethod ?
"INSTANCE" :
"CLASS";
5768 Result +=
"_METHODS_";
5769 Result += ClassName;
5770 Result +=
" __attribute__ ((used, section (\"__OBJC, __";
5771 Result += IsInstanceMethod ?
"inst" :
"cls";
5772 Result +=
"_meth\")))= ";
5773 Result +=
"{\n\t0, " + utostr(NumMethods) +
"\n";
5775 Result +=
"\t,{{(SEL)\"";
5776 Result += (*MethodBegin)->getSelector().getAsString();
5777 std::string MethodTypeString =
5780 Result += MethodTypeString;
5781 Result +=
"\", (void *)";
5782 Result += MethodInternalNames[*MethodBegin];
5784 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
5785 Result +=
"\t ,{(SEL)\"";
5786 Result += (*MethodBegin)->getSelector().getAsString();
5787 std::string MethodTypeString =
5790 Result += MethodTypeString;
5791 Result +=
"\", (void *)";
5792 Result += MethodInternalNames[*MethodBegin];
5795 Result +=
"\t }\n};\n";
5804 DisableReplaceStmtScope S(*
this);
5805 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
5816 assert(iFaceDecl &&
"RewriteObjCIvarRefExpr - iFaceDecl is null");
5821 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5830 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5850 assert(!IV->
isFreeIvar() &&
"Cannot have a free standing ivar outside a method");
5861 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5864 std::string RecName = clsDeclared->getIdentifier()->getName();
5870 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5885 ReplaceStmtWithRange(IV, Replacement, OldRange);
5889 #endif // CLANG_ENABLE_OBJC_REWRITER unsigned getNumSemanticExprs() const
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
The receiver is the instance of the superclass object.
const BlockDecl * getBlockDecl() const
QualType withConst() const
Retrieves a version of this type with const applied.
Represents a function declaration or definition.
The receiver is an object instance.
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
bool hasErrorOccurred() const
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
const FunctionProtoType * getFunctionType() const
getFunctionType - Return the underlying function type for this block.
QualType getObjCIdType() const
Represents the Objective-CC id type.
SourceLocation getLocStart() const LLVM_READONLY
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isBlockPointerType() const
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Selector getSelector() const
ObjCInterfaceDecl * getClassInterface()
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
ObjCIvarDecl * getPropertyIvarDecl() const
SourceLocation getRParenLoc() const
ObjCProtocolDecl * getProtocol() const
Stmt - This represents one statement.
const ObjCProtocolList & getReferencedProtocols() const
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
bool isRealFloatingType() const
Floating point categories.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Defines the SourceManager interface.
bool isRecordType() const
Decl - This represents one declaration (or definition), e.g.
param_iterator param_end()
ParenExpr - This represents a parethesized expression, e.g.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
The base class of the type hierarchy.
Represents Objective-C's @throw statement.
static bool IsHeaderFile(const std::string &Filename)
SourceLocation getLocStart() const LLVM_READONLY
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
const ObjCObjectPointerType * getAsObjCInterfacePointerType() const
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
protocol_iterator protocol_begin() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
SourceLocation getLParenLoc() const
A container of type source information.
instmeth_iterator instmeth_end() const
Floating point control options.
constexpr XRayInstrMask Function
static StringLiteral * Create(const ASTContext &C, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumStrs)
This is the "fully general" constructor that allows representation of strings formed from multiple co...
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getLocEnd() const LLVM_READONLY
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
MutableArrayRef< ParmVarDecl * >::iterator param_iterator
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
Represents a variable declaration or definition.
CompoundLiteralExpr - [C99 6.5.2.5].
unsigned getNumParams() const
const T * getAs() const
Member-template getAs<specific type>'.
Extra information about a function prototype.
SourceLocation getLocStart() const LLVM_READONLY
ObjCMethodDecl - Represents an instance or class method declaration.
SourceLocation getLeftLoc() const
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
Expr * IgnoreImplicit() LLVM_READONLY
IgnoreImplicit - Skip past any implicit AST nodes which might surround this expression.
QualType getObjCClassType() const
Represents the Objective-C Class type.
Describes how types, statements, expressions, and declarations should be printed. ...
classmeth_range class_methods() const
std::string getRewrittenText(SourceRange Range) const
getRewrittenText - Return the rewritten form of the text in the specified range.
SourceLocation getLocStart() const LLVM_READONLY
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represents a struct/union/class.
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
instprop_range instance_properties() const
One of these records is kept for each identifier that is lexed.
QualType IgnoreParens() const
Returns the specified type after dropping any outer-level parentheses.
Represents a class type in Objective C.
static RecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl=nullptr)
QualType getPointeeType() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
field_range fields() const
Represents a member of a struct/union/class.
static ObjCMessageExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, ArrayRef< SourceLocation > SelLocs, ObjCMethodDecl *Method, ArrayRef< Expr *> Args, SourceLocation RBracLoc, bool isImplicit)
Create a message send to super.
instmeth_range instance_methods() const
StringLiteral * getString()
std::string getNameAsString() const
Get the name of the class associated with this interface.
SourceLocation getRParenLoc() const
ObjCMethodDecl * getSetterMethodDecl() const
protocol_iterator protocol_end() const
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isObjCQualifiedClassType() const
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
Selector getSelector() const
Represents Objective-C's @catch statement.
Describes an C or C++ initializer list.
bool isBitField() const
Determines whether this field is a bitfield.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
const Expr * getThrowExpr() const
filtered_decl_iterator< ObjCMethodDecl, &ObjCMethodDecl::isInstanceMethod > instmeth_iterator
unsigned ivar_size() const
SourceLocation getLocEnd() const LLVM_READONLY
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
PropertyAttributeKind getPropertyAttributes() const
Concrete class used by the front-end to report problems and issues.
Represents a typeof (or typeof) expression (a GCC extension).
const clang::PrintingPolicy & getPrintingPolicy() const
Represents a declaration of a type.
A builtin binary operation expression such as "x + y" or "x <= y".
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
std::unique_ptr< ASTConsumer > CreateObjCRewriter(const std::string &InFile, std::unique_ptr< raw_ostream > OS, DiagnosticsEngine &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning)
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
Defines the Diagnostic-related interfaces.
ObjCStringLiteral, used for Objective-C string literals i.e.
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, const ASTContext *Context=nullptr) const
void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CompoundStmt * getCompoundBody()
Represents an Objective-C protocol declaration.
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
SourceLocation getLocEnd() const LLVM_READONLY
An ordinary object is located at an address in memory.
Represents an ObjC class declaration.
Represents a linkage specification.
QualType getReturnType() const
SourceLocation getTypeSpecStartLoc() const
const Stmt * getBody() const
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified=false, bool hasWrittenPrototype=true, bool isConstexprSpecified=false)
SourceLocation getAtStartLoc() const
Iterator for iterating over Stmt * arrays that contain only Expr *.
std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended=false) const
Emit the encoded type for the method declaration Decl into S.
const ObjCAtCatchStmt * getCatchStmt(unsigned I) const
Retrieve a @catch statement.
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
ConditionalOperator - The ?: ternary operator.
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getLocEnd() const LLVM_READONLY
CompoundStmt - This represents a group of statements like { stmt stmt }.
Represents a prototype with parameter type info, e.g.
CastKind
CastKind - The kind of operation required for a conversion.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat)
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
SourceLocation getLocation() const
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location, which defaults to the empty location.
unsigned ivar_size() const
bool hasDefinition() const
Determine whether this protocol has a definition.
SourceLocation getLocStart() const LLVM_READONLY
Pepresents a block literal declaration, which is like an unnamed FunctionDecl.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Expr - This represents one expression.
ivar_iterator ivar_end() const
ivar_iterator ivar_begin() const
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
const T * castAs() const
Member-template castAs<specific type>.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration is also the definition.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
QualType getTagDeclType(const TagDecl *Decl) const
Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl...
const CompoundStmt * getSynchBody() const
DeclContext * getDeclContext()
bool isWrittenInMainFile(SourceLocation Loc) const
Returns true if the spelling location for the given location is in the main file buffer.
Represents Objective-C's @synchronized statement.
ObjCInterfaceDecl * getSuperClass() const
ObjCSelectorExpr used for @selector in Objective-C.
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
ObjCIvarDecl * lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared)
propimpl_range property_impls() const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type...
const Stmt * getTryBody() const
Retrieve the @try body.
QualType getEncodedType() const
bool isa(CodeGen::Address addr)
An expression that sends a message to the given Objective-C object or class.
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl...
SourceLocation getEnd() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
bool isInstanceMethod() const
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
int getRangeSize(SourceRange Range, RewriteOptions opts=RewriteOptions()) const
getRangeSize - Return the size in bytes of the specified range if they are in the same file...
Selector getSelector() const
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
The result type of a method or function.
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr.cast]), which uses the syntax (Type)expr.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
ImplicitParamDecl * getSelfDecl() const
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Expr * getUnderlyingExpr() const
unsigned getCVRQualifiers() const
Retrieve the set of CVR (const-volatile-restrict) qualifiers applied to this type.
static std::string getIvarAccessString(ObjCIvarDecl *OID)
bool isConstQualified() const
Determine whether this type is const-qualified.
param_iterator param_begin()
SourceLocation getLocStart() const LLVM_READONLY
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver. ...
std::string getAsString() const
Derive the full selector name (e.g.
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
void setSourceMgr(SourceManager &SM, const LangOptions &LO)
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
param_type_range param_types() const
ivar_iterator ivar_begin() const
classmeth_iterator classmeth_end() const
Encodes a location in the source.
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
QualType getReturnType() const
ivar_iterator ivar_end() const
const Stmt * getCatchBody() const
Interfaces are the core concept in Objective-C for object oriented design.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
SourceLocation getLocStart() const LLVM_READONLY
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
const RewriteBuffer * getRewriteBufferFor(FileID FID) const
getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
InsertText - Insert the specified string at the specified location in the original buffer...
SourceLocation getLocStart() const LLVM_READONLY
static bool HasLocalVariableExternalStorage(ValueDecl *VD)
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super', otherwise an invalid source location.
ObjCCategoryDecl - Represents a category declaration.
decl_iterator decl_begin()
ObjCProtocolExpr used for protocol expression in Objective-C.
bool isObjCObjectPointerType() const
Represents one property declaration in an Objective-C interface.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
SourceLocation getLocEnd() const LLVM_READONLY
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
bool isImplicitInterfaceDecl() const
isImplicitInterfaceDecl - check that this is an implicitly declared ObjCInterfaceDecl node...
const ObjCMethodDecl * getMethodDecl() const
classmeth_iterator classmeth_begin() const
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
StringRef getName() const
Return the actual identifier string.
decl_iterator - Iterates through the declarations stored within this context.
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
bool isObjCGCWeak() const
true when Type is objc's weak.
Base class for declarations which introduce a typedef-name.
Expr * getResultExpr()
Return the result-bearing expression, or null if there is none.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
const ObjCInterfaceDecl * getClassInterface() const
Dataflow Directional Tag Classes.
bool isObjCQualifiedInterfaceType() const
bool isValid() const
Return true if this is a valid SourceLocation object.
ArrayRef< Capture > captures() const
static void scanToNextArgument(const char *&argRef)
Kind getPropertyImplementation() const
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getAtLoc() const
QualType getSuperType() const
Retrieve the type referred to by 'super'.
static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, std::string &typedefString)
const ObjCProtocolList & getReferencedProtocols() const
const Expr * getInit() const
FileID getMainFileID() const
Returns the FileID of the main source file.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
bool isBooleanType() const
QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
U cast(CodeGen::Address addr)
int printf(__constant const char *st,...)
const Expr * getSynchExpr() const
const ObjCInterfaceDecl * getContainingInterface() const
Return the class interface that this ivar is logically contained in; this is either the interface whe...
QualType getCallResultType(const ASTContext &Context) const
Determine the type of an expression that calls a function of this type.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext, providing only those that are of type SpecificDecl (or a class derived from it).
static bool scanForProtocolRefs(const char *startBuf, const char *endBuf, const char *&startRef, const char *&endRef)
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
Represents a pointer to an Objective C object.
unsigned getByteLength() const
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
SourceLocation getRParenLoc() const
static void BuildUniqueMethodName(std::string &Name, ObjCMethodDecl *MD)
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Represents Objective-C's collection statement.
ObjCEncodeExpr, used for @encode in Objective-C.
static CStyleCastExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R)
SourceLocation getLocation() const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
protocol_iterator protocol_begin() const
void getObjCEncodingForType(QualType T, std::string &S, const FieldDecl *Field=nullptr, QualType *NotEncodedT=nullptr) const
Emit the Objective-CC type encoding for the given type T into S.
bool isObjCQualifiedIdType() const
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
Represents Objective-C's @finally statement.
void addDecl(Decl *D)
Add the declaration D into this context.
const Expr * getBase() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
SourceManager & getSourceManager()
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
SourceRange getAtEndRange() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Rewriter - This is the main interface to the rewrite buffers.
QualType getParamType(unsigned i) const
TranslationUnitDecl * getTranslationUnitDecl() const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ContinueStmt - This represents a continue.
filtered_decl_iterator< ObjCMethodDecl, &ObjCMethodDecl::isClassMethod > classmeth_iterator
ObjCIvarDecl - Represents an ObjC instance variable.
static bool isRewritable(SourceLocation Loc)
isRewritable - Return true if this location is a raw file location, which is rewritable.
static TypedefDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
Represents Objective-C's @try ... @catch ... @finally statement.
protocol_iterator protocol_end() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
unsigned getNumCatchStmts() const
Retrieve the number of @catch statements in this try-catch-finally block.
StringLiteral - This represents a string literal expression, e.g.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
StringRef getName() const
getName - Get the name of identifier for the class interface associated with this implementation as a...
The top declaration context.
A reference to a declared variable, function, enum, etc.
ObjCPropertyDecl * getPropertyDecl() const
bool isPointerType() const
BreakStmt - This represents a break.
Expr * getSemanticExpr(unsigned index)
const VarDecl * getCatchParamDecl() const
An l-value expression is a reference to an object with independent storage.
A trivial tuple used to represent a source range.
instmeth_iterator instmeth_begin() const
ObjCMethodDecl * getGetterMethodDecl() const
This represents a decl that may have a name.
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getEndOfDefinitionLoc() const
SourceLocation getRightLoc() const
bool isFunctionPointerType() const
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
The receiver is a superclass.
void getSelectorLocs(SmallVectorImpl< SourceLocation > &SelLocs) const
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
FullSourceLoc getFullLoc(SourceLocation Loc) const
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
This class handles loading and caching of source files into memory.
bool BlockRequiresCopying(QualType Ty, const VarDecl *D)
Returns true iff we need copy/dispose helpers for the given type.
SourceLocation getLocation() const
ArrayRef< ParmVarDecl * > parameters() const
TypeSourceInfo * getClassReceiverTypeInfo() const
Returns a type-source information of a class message send, or nullptr if the message is not a class m...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
ObjCCategoryDecl * FindCategoryDeclaration(IdentifierInfo *CategoryId) const
FindCategoryDeclaration - Finds category declaration in the list of categories for this class and ret...