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());
4461 }
else if (isTopLevelBlockPointerType((*I)->getType())) {
4462 FD = SynthBlockInitFunctionDecl((*I)->getName());
4465 Exp = NoTypeInfoCStyleCastExpr(Context, Context->
VoidPtrTy,
4468 FD = SynthBlockInitFunctionDecl((*I)->getName());
4478 InitExprs.push_back(Exp);
4482 E = BlockByRefDecls.end(); I != E; ++I) {
4485 std::string RecName;
4486 RewriteByRefString(RecName, Name, ND,
true);
4488 +
sizeof(
"struct"));
4492 assert(RD &&
"SynthBlockInitExpr(): Can't find RecordDecl");
4495 FD = SynthBlockInitFunctionDecl((*I)->getName());
4498 bool isNestedCapturedVar =
false;
4500 for (
const auto &CI : block->
captures()) {
4501 const VarDecl *variable = CI.getVariable();
4502 if (variable == ND && CI.isNested()) {
4503 assert (CI.isByRef() &&
4504 "SynthBlockInitExpr - captured block variable is not byref");
4505 isNestedCapturedVar =
true;
4511 if (!isNestedCapturedVar)
4515 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
4516 InitExprs.push_back(Exp);
4519 if (ImportedBlockDecls.size()) {
4526 InitExprs.push_back(FlagExp);
4528 NewRep =
new (Context)
CallExpr(*Context, DRE, InitExprs,
4533 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
4535 BlockDeclRefs.clear();
4536 BlockByRefDecls.clear();
4537 BlockByRefDeclsPtrSet.clear();
4538 BlockByCopyDecls.clear();
4539 BlockByCopyDeclsPtrSet.clear();
4540 ImportedBlockDecls.clear();
4544 bool RewriteObjC::IsDeclStmtInForeachHeader(
DeclStmt *DS) {
4546 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4547 return CS->getElement() == DS;
4555 Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(
Stmt *S) {
4556 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4557 isa<DoStmt>(S) || isa<ForStmt>(S))
4559 else if (isa<ObjCForCollectionStmt>(S)) {
4561 ObjCBcLabelNo.push_back(++BcLabelCount);
4568 return RewritePropertyOrImplicitSetter(PseudoOp);
4570 return RewritePropertyOrImplicitGetter(PseudoOp);
4572 }
else if (
ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4573 return RewriteObjCIvarRefExpr(IvarRefExpr);
4581 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4583 childStmt = newStmt;
4587 if (
BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
4589 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
4590 InnerContexts.insert(BE->getBlockDecl());
4591 ImportedLocalExternalDecls.clear();
4592 GetInnerBlockDeclRefExprs(BE->getBody(),
4593 InnerBlockDeclRefs, InnerContexts);
4595 Stmt *SaveCurrentBody = CurrentBody;
4596 CurrentBody = BE->getBody();
4597 PropParentMap =
nullptr;
4603 bool saveDisableReplaceStmt = DisableReplaceStmt;
4604 DisableReplaceStmt =
false;
4605 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4606 DisableReplaceStmt = saveDisableReplaceStmt;
4607 CurrentBody = SaveCurrentBody;
4608 PropParentMap =
nullptr;
4609 ImportedLocalExternalDecls.clear();
4612 RewrittenBlockExprs[BE] = Str;
4614 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4617 ReplaceStmt(S, blockTranscribed);
4618 return blockTranscribed;
4622 return RewriteAtEncode(AtEncode);
4625 return RewriteAtSelector(AtSelector);
4628 return RewriteObjCStringLiteral(AtString);
4639 std::string messString;
4640 messString +=
"// ";
4641 messString.append(startBuf, endBuf-startBuf+1);
4650 return RewriteMessageExpr(MessExpr);
4654 return RewriteObjCTryStmt(StmtTry);
4657 return RewriteObjCSynchronizedStmt(StmtTry);
4660 return RewriteObjCThrowStmt(StmtThrow);
4663 return RewriteObjCProtocolExpr(ProtocolExp);
4666 dyn_cast<ObjCForCollectionStmt>(S))
4667 return RewriteObjCForCollectionStmt(StmtForCollection,
4670 dyn_cast<BreakStmt>(S))
4671 return RewriteBreakStmt(StmtBreakStmt);
4673 dyn_cast<ContinueStmt>(S))
4674 return RewriteContinueStmt(StmtContinueStmt);
4678 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4688 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4689 RewriteObjCQualifiedInterfaceTypes(*DS->
decl_begin());
4692 for (
auto *SD : DS->
decls()) {
4693 if (
ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4694 if (isTopLevelBlockPointerType(ND->
getType()))
4695 RewriteBlockPointerDecl(ND);
4697 CheckFunctionPointerDecl(ND->
getType(), ND);
4698 if (
VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4699 if (VD->
hasAttr<BlocksAttr>()) {
4700 static unsigned uniqueByrefDeclCount = 0;
4701 assert(!BlockByRefDeclNo.count(ND) &&
4702 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4703 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4704 RewriteByRefVar(VD);
4707 RewriteTypeOfDecl(VD);
4711 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4712 RewriteBlockPointerDecl(TD);
4713 else if (TD->getUnderlyingType()->isFunctionPointerType())
4714 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4720 RewriteObjCQualifiedInterfaceTypes(CE);
4722 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4723 isa<DoStmt>(S) || isa<ForStmt>(S)) {
4724 assert(!Stmts.empty() &&
"Statement stack is empty");
4725 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
4726 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
4727 &&
"Statement stack mismatch");
4731 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4733 if (VD->
hasAttr<BlocksAttr>())
4734 return RewriteBlockDeclRefExpr(DRE);
4736 return RewriteLocalVariableExternalStorage(DRE);
4739 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
4742 ReplaceStmt(S, BlockCall);
4747 RewriteCastExpr(CE);
4756 llvm::raw_string_ostream Buf(SStr);
4758 const std::string &Str = Buf.str();
4760 printf(
"CAST = %s\n", &Str[0]);
4761 InsertText(ICE->getSubExpr()->getLocStart(), Str);
4770 void RewriteObjC::RewriteRecordBody(
RecordDecl *RD) {
4771 for (
auto *FD : RD->
fields()) {
4772 if (isTopLevelBlockPointerType(FD->
getType()))
4773 RewriteBlockPointerDecl(FD);
4776 RewriteObjCQualifiedInterfaceTypes(FD);
4782 void RewriteObjC::HandleDeclInMainFile(
Decl *D) {
4784 case Decl::Function: {
4792 RewriteBlocksInFunctionProtoType(FD->
getType(), FD);
4799 CurFunctionDef = FD;
4800 CurFunctionDeclToDeclareForBlock = FD;
4803 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4805 CurrentBody =
nullptr;
4806 if (PropParentMap) {
4807 delete PropParentMap;
4808 PropParentMap =
nullptr;
4812 InsertBlockLiteralsWithinFunction(FD);
4813 CurFunctionDef =
nullptr;
4814 CurFunctionDeclToDeclareForBlock =
nullptr;
4818 case Decl::ObjCMethod: {
4824 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4826 CurrentBody =
nullptr;
4827 if (PropParentMap) {
4828 delete PropParentMap;
4829 PropParentMap =
nullptr;
4831 InsertBlockLiteralsWithinMethod(MD);
4832 CurMethodDef =
nullptr;
4836 case Decl::ObjCImplementation: {
4838 ClassImplementation.push_back(CI);
4841 case Decl::ObjCCategoryImpl: {
4843 CategoryImplementation.push_back(CI);
4847 VarDecl *VD = cast<VarDecl>(D);
4848 RewriteObjCQualifiedInterfaceTypes(VD);
4849 if (isTopLevelBlockPointerType(VD->
getType()))
4850 RewriteBlockPointerDecl(VD);
4852 CheckFunctionPointerDecl(VD->
getType(), VD);
4855 RewriteCastExpr(CE);
4861 RewriteRecordBody(RD);
4866 RewriteFunctionBodyOrGlobalInitializer(VD->
getInit());
4867 CurrentBody =
nullptr;
4868 if (PropParentMap) {
4869 delete PropParentMap;
4870 PropParentMap =
nullptr;
4873 GlobalVarDecl =
nullptr;
4877 RewriteCastExpr(CE);
4882 case Decl::TypeAlias:
4883 case Decl::Typedef: {
4885 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4886 RewriteBlockPointerDecl(TD);
4887 else if (TD->getUnderlyingType()->isFunctionPointerType())
4888 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4892 case Decl::CXXRecord:
4893 case Decl::Record: {
4896 RewriteRecordBody(RD);
4905 void RewriteObjC::HandleTranslationUnit(
ASTContext &
C) {
4914 RewriteObjCProtocolMetaData(ProtDecl,
"",
"", Preamble);
4917 if (ClassImplementation.size() || CategoryImplementation.size())
4918 RewriteImplementations();
4925 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
4927 llvm::errs() <<
"No changes\n";
4930 if (ClassImplementation.size() || CategoryImplementation.size() ||
4931 ProtocolExprDecls.size()) {
4933 std::string ResultStr;
4934 RewriteMetaDataIntoBuffer(ResultStr);
4936 *OutFile << ResultStr;
4941 void RewriteObjCFragileABI::Initialize(
ASTContext &context) {
4942 InitializeCommon(context);
4947 Preamble =
"#pragma once\n";
4948 Preamble +=
"struct objc_selector; struct objc_class;\n";
4949 Preamble +=
"struct __rw_objc_super { struct objc_object *object; ";
4950 Preamble +=
"struct objc_object *superClass; ";
4951 if (LangOpts.MicrosoftExt) {
4953 Preamble +=
"__rw_objc_super(struct objc_object *o, struct objc_object *s) " 4955 Preamble +=
"object(o), superClass(s) {} ";
4958 Preamble +=
"#ifndef _REWRITER_typedef_Protocol\n";
4959 Preamble +=
"typedef struct objc_object Protocol;\n";
4960 Preamble +=
"#define _REWRITER_typedef_Protocol\n";
4961 Preamble +=
"#endif\n";
4962 if (LangOpts.MicrosoftExt) {
4963 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
4964 Preamble +=
"#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
4966 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern\n";
4967 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
4968 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4969 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
4970 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4971 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
4972 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4973 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
4974 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4975 Preamble +=
"__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
4976 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4977 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
4978 Preamble +=
"(const char *);\n";
4979 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
4980 Preamble +=
"(struct objc_class *);\n";
4981 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
4982 Preamble +=
"(const char *);\n";
4983 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
4984 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
4985 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
4986 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
4987 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_exception_match";
4988 Preamble +=
"(struct objc_class *, struct objc_object *);\n";
4990 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
4991 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
4992 Preamble +=
"__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
4993 Preamble +=
"#ifndef __FASTENUMERATIONSTATE\n";
4994 Preamble +=
"struct __objcFastEnumerationState {\n\t";
4995 Preamble +=
"unsigned long state;\n\t";
4996 Preamble +=
"void **itemsPtr;\n\t";
4997 Preamble +=
"unsigned long *mutationsPtr;\n\t";
4998 Preamble +=
"unsigned long extra[5];\n};\n";
4999 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
5000 Preamble +=
"#define __FASTENUMERATIONSTATE\n";
5001 Preamble +=
"#endif\n";
5002 Preamble +=
"#ifndef __NSCONSTANTSTRINGIMPL\n";
5003 Preamble +=
"struct __NSConstantStringImpl {\n";
5004 Preamble +=
" int *isa;\n";
5005 Preamble +=
" int flags;\n";
5006 Preamble +=
" char *str;\n";
5007 Preamble +=
" long length;\n";
5009 Preamble +=
"#ifdef CF_EXPORT_CONSTANT_STRING\n";
5010 Preamble +=
"extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5011 Preamble +=
"#else\n";
5012 Preamble +=
"__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5013 Preamble +=
"#endif\n";
5014 Preamble +=
"#define __NSCONSTANTSTRINGIMPL\n";
5015 Preamble +=
"#endif\n";
5017 Preamble +=
"#ifndef BLOCK_IMPL\n";
5018 Preamble +=
"#define BLOCK_IMPL\n";
5019 Preamble +=
"struct __block_impl {\n";
5020 Preamble +=
" void *isa;\n";
5021 Preamble +=
" int Flags;\n";
5022 Preamble +=
" int Reserved;\n";
5023 Preamble +=
" void *FuncPtr;\n";
5025 Preamble +=
"// Runtime copy/destroy helper functions (from Block_private.h)\n";
5026 Preamble +=
"#ifdef __OBJC_EXPORT_BLOCKS\n";
5027 Preamble +=
"extern \"C\" __declspec(dllexport) " 5028 "void _Block_object_assign(void *, const void *, const int);\n";
5029 Preamble +=
"extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5030 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5031 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5032 Preamble +=
"#else\n";
5033 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5034 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5035 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5036 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5037 Preamble +=
"#endif\n";
5038 Preamble +=
"#endif\n";
5039 if (LangOpts.MicrosoftExt) {
5040 Preamble +=
"#undef __OBJC_RW_DLLIMPORT\n";
5041 Preamble +=
"#undef __OBJC_RW_STATICIMPORT\n";
5042 Preamble +=
"#ifndef KEEP_ATTRIBUTES\n";
5043 Preamble +=
"#define __attribute__(X)\n";
5044 Preamble +=
"#endif\n";
5045 Preamble +=
"#define __weak\n";
5048 Preamble +=
"#define __block\n";
5049 Preamble +=
"#define __weak\n";
5053 Preamble +=
"\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5058 void RewriteObjCFragileABI::RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
5059 std::string &Result) {
5065 Result +=
"__OFFSETOFIVAR__(struct ";
5067 if (LangOpts.MicrosoftExt)
5076 void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
5078 StringRef ClassName, std::string &Result) {
5079 static bool objc_protocol_methods =
false;
5088 Result +=
"\nstruct _protocol_methods {\n";
5089 Result +=
"\tstruct objc_selector *_cmd;\n";
5090 Result +=
"\tchar *method_types;\n";
5093 objc_protocol_methods =
true;
5110 Result +=
"\nstatic struct {\n";
5111 Result +=
"\tint protocol_method_count;\n";
5112 Result +=
"\tstruct _protocol_methods protocol_methods[";
5113 Result += utostr(NumMethods);
5114 Result +=
"];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
5116 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 5117 "{\n\t" + utostr(NumMethods) +
"\n";
5124 Result +=
"\t ,{{(struct objc_selector *)\"";
5126 Result +=
"\t ,{(struct objc_selector *)\"";
5127 Result += (*I)->getSelector().getAsString();
5130 Result += MethodTypeString;
5133 Result +=
"\t }\n};\n";
5139 if (NumMethods > 0) {
5145 Result +=
"\nstatic struct {\n";
5146 Result +=
"\tint protocol_method_count;\n";
5147 Result +=
"\tstruct _protocol_methods protocol_methods[";
5148 Result += utostr(NumMethods);
5149 Result +=
"];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
5151 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5153 Result += utostr(NumMethods);
5161 Result +=
"\t ,{{(struct objc_selector *)\"";
5163 Result +=
"\t ,{(struct objc_selector *)\"";
5164 Result += (*I)->getSelector().getAsString();
5167 Result += MethodTypeString;
5170 Result +=
"\t }\n};\n";
5183 static bool objc_protocol =
false;
5184 if (!objc_protocol) {
5185 Result +=
"\nstruct _objc_protocol {\n";
5186 Result +=
"\tstruct _objc_protocol_extension *isa;\n";
5187 Result +=
"\tchar *protocol_name;\n";
5188 Result +=
"\tstruct _objc_protocol **protocol_list;\n";
5189 Result +=
"\tstruct _objc_protocol_method_list *instance_methods;\n";
5190 Result +=
"\tstruct _objc_protocol_method_list *class_methods;\n";
5193 objc_protocol =
true;
5196 Result +=
"\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
5198 Result +=
" __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 5201 Result +=
"\", 0, ";
5203 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
5210 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
5220 llvm_unreachable(
"protocol already synthesized");
5223 void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
5225 StringRef prefix, StringRef ClassName,
5226 std::string &Result) {
5227 if (Protocols.
empty())
return;
5229 for (
unsigned i = 0; i != Protocols.
size(); i++)
5230 RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
5239 Result +=
"\nstatic struct {\n";
5240 Result +=
"\tstruct _objc_protocol_list *next;\n";
5241 Result +=
"\tint protocol_count;\n";
5242 Result +=
"\tstruct _objc_protocol *class_protocols[";
5243 Result += utostr(Protocols.
size());
5244 Result +=
"];\n} _OBJC_";
5246 Result +=
"_PROTOCOLS_";
5247 Result += ClassName;
5248 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5250 Result += utostr(Protocols.
size());
5253 Result +=
"\t,{&_OBJC_PROTOCOL_";
5254 Result += Protocols[0]->getNameAsString();
5257 for (
unsigned i = 1; i != Protocols.
size(); i++) {
5258 Result +=
"\t ,&_OBJC_PROTOCOL_";
5259 Result += Protocols[i]->getNameAsString();
5262 Result +=
"\t }\n};\n";
5266 std::string &Result) {
5273 RewriteObjCInternalStruct(CDecl, Result);
5281 static bool objc_ivar =
false;
5289 Result +=
"\nstruct _objc_ivar {\n";
5290 Result +=
"\tchar *ivar_name;\n";
5291 Result +=
"\tchar *ivar_type;\n";
5292 Result +=
"\tint ivar_offset;\n";
5303 Result +=
"\nstatic struct {\n";
5304 Result +=
"\tint ivar_count;\n";
5305 Result +=
"\tstruct _objc_ivar ivar_list[";
5306 Result += utostr(NumIvars);
5307 Result +=
"];\n} _OBJC_INSTANCE_VARIABLES_";
5309 Result +=
" __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 5311 Result += utostr(NumIvars);
5317 for (
auto *IV : IDecl->
ivars())
5318 IVars.push_back(IV);
5325 Result +=
"\t,{{\"";
5326 Result += IVI->getNameAsString();
5328 std::string TmpString, StrEncoding;
5330 QuoteDoublequotes(TmpString, StrEncoding);
5331 Result += StrEncoding;
5333 RewriteIvarOffsetComputation(*IVI, Result);
5335 for (++IVI; IVI != IVE; ++IVI) {
5336 Result +=
"\t ,{\"";
5337 Result += IVI->getNameAsString();
5339 std::string TmpString, StrEncoding;
5341 QuoteDoublequotes(TmpString, StrEncoding);
5342 Result += StrEncoding;
5344 RewriteIvarOffsetComputation(*IVI, Result);
5348 Result +=
"\t }\n};\n";
5359 if (!Prop->getPropertyIvarDecl())
5365 if (!Getter->isDefined())
5366 InstanceMethods.push_back(Getter);
5370 if (!Setter->isDefined())
5371 InstanceMethods.push_back(Setter);
5373 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5400 static bool objc_class =
false;
5402 Result +=
"\nstruct _objc_class {\n";
5403 Result +=
"\tstruct _objc_class *isa;\n";
5404 Result +=
"\tconst char *super_class_name;\n";
5405 Result +=
"\tchar *name;\n";
5406 Result +=
"\tlong version;\n";
5407 Result +=
"\tlong info;\n";
5408 Result +=
"\tlong instance_size;\n";
5409 Result +=
"\tstruct _objc_ivar_list *ivars;\n";
5410 Result +=
"\tstruct _objc_method_list *methods;\n";
5411 Result +=
"\tstruct objc_cache *cache;\n";
5412 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5413 Result +=
"\tconst char *ivar_layout;\n";
5414 Result +=
"\tstruct _objc_class_ext *ext;\n";
5422 while (SuperClass) {
5423 RootClass = SuperClass;
5428 Result +=
"\nstatic struct _objc_class _OBJC_METACLASS_";
5430 Result +=
" __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 5431 "{\n\t(struct _objc_class *)\"";
5443 Result +=
", 0, \"";
5449 Result +=
", 0,2, sizeof(struct _objc_class), 0";
5451 Result +=
"\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
5458 Result +=
"\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
5463 Result +=
"\t,0,0,0,0\n";
5467 Result +=
"\nstatic struct _objc_class _OBJC_CLASS_";
5469 Result +=
" __attribute__ ((used, section (\"__OBJC, __class\")))= " 5470 "{\n\t&_OBJC_METACLASS_";
5480 Result +=
", 0, \"";
5486 if (!ObjCSynthesizedStructs.count(CDecl))
5490 Result +=
",sizeof(struct ";
5492 if (LangOpts.MicrosoftExt)
5497 Result +=
", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
5504 Result +=
", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
5506 Result +=
", 0\n\t";
5511 Result +=
", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
5513 Result +=
", 0,0\n";
5516 Result +=
",0,0,0\n";
5520 void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
5521 int ClsDefCount = ClassImplementation.size();
5522 int CatDefCount = CategoryImplementation.size();
5525 for (
int i = 0; i < ClsDefCount; i++)
5526 RewriteObjCClassMetaData(ClassImplementation[i], Result);
5529 for (
int i = 0; i < CatDefCount; i++)
5530 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
5544 Result +=
"\nstruct _objc_symtab {\n";
5545 Result +=
"\tlong sel_ref_cnt;\n";
5546 Result +=
"\tSEL *refs;\n";
5547 Result +=
"\tshort cls_def_cnt;\n";
5548 Result +=
"\tshort cat_def_cnt;\n";
5549 Result +=
"\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+
"];\n";
5552 Result +=
"static struct _objc_symtab " 5553 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
5554 Result +=
"\t0, 0, " + utostr(ClsDefCount)
5555 +
", " + utostr(CatDefCount) +
"\n";
5556 for (
int i = 0; i < ClsDefCount; i++) {
5557 Result +=
"\t,&_OBJC_CLASS_";
5558 Result += ClassImplementation[i]->getNameAsString();
5562 for (
int i = 0; i < CatDefCount; i++) {
5563 Result +=
"\t,&_OBJC_CATEGORY_";
5564 Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
5566 Result += CategoryImplementation[i]->getNameAsString();
5583 Result +=
"\nstruct _objc_module {\n";
5584 Result +=
"\tlong version;\n";
5585 Result +=
"\tlong size;\n";
5586 Result +=
"\tconst char *name;\n";
5587 Result +=
"\tstruct _objc_symtab *symtab;\n";
5589 Result +=
"static struct _objc_module " 5590 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
5591 Result +=
"\t" + utostr(OBJC_ABI_VERSION) +
5592 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
5595 if (LangOpts.MicrosoftExt) {
5596 if (ProtocolExprDecls.size()) {
5597 Result +=
"#pragma section(\".objc_protocol$B\",long,read,write)\n";
5598 Result +=
"#pragma data_seg(push, \".objc_protocol$B\")\n";
5600 Result +=
"static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
5601 Result += ProtDecl->getNameAsString();
5602 Result +=
" = &_OBJC_PROTOCOL_";
5603 Result += ProtDecl->getNameAsString();
5606 Result +=
"#pragma data_seg(pop)\n\n";
5608 Result +=
"#pragma section(\".objc_module_info$B\",long,read,write)\n";
5609 Result +=
"#pragma data_seg(push, \".objc_module_info$B\")\n";
5610 Result +=
"static struct _objc_module *_POINTER_OBJC_MODULES = ";
5611 Result +=
"&_OBJC_MODULES;\n";
5612 Result +=
"#pragma data_seg(pop)\n\n";
5619 std::string &Result) {
5626 FullCategoryName +=
'_';
5637 if (!Prop->getPropertyIvarDecl())
5643 InstanceMethods.push_back(Getter);
5647 InstanceMethods.push_back(Setter);
5649 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5650 true,
"CATEGORY_", FullCategoryName,
Result);
5654 false,
"CATEGORY_", FullCategoryName,
Result);
5660 FullCategoryName,
Result);
5674 static bool objc_category =
false;
5675 if (!objc_category) {
5676 Result +=
"\nstruct _objc_category {\n";
5677 Result +=
"\tchar *category_name;\n";
5678 Result +=
"\tchar *class_name;\n";
5679 Result +=
"\tstruct _objc_method_list *instance_methods;\n";
5680 Result +=
"\tstruct _objc_method_list *class_methods;\n";
5681 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5682 Result +=
"\tunsigned int size;\n";
5683 Result +=
"\tstruct _objc_property_list *instance_properties;\n";
5685 objc_category =
true;
5687 Result +=
"\nstatic struct _objc_category _OBJC_CATEGORY_";
5688 Result += FullCategoryName;
5689 Result +=
" __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
5691 Result +=
"\"\n\t, \"";
5696 Result +=
"\t, (struct _objc_method_list *)" 5697 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
5698 Result += FullCategoryName;
5702 Result +=
"\t, 0\n";
5704 Result +=
"\t, (struct _objc_method_list *)" 5705 "&_OBJC_CATEGORY_CLASS_METHODS_";
5706 Result += FullCategoryName;
5710 Result +=
"\t, 0\n";
5713 Result +=
"\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
5714 Result += FullCategoryName;
5718 Result +=
"\t, 0\n";
5719 Result +=
"\t, sizeof(struct _objc_category), 0\n};\n";
5724 template<
typename MethodIterator>
5725 void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5726 MethodIterator MethodEnd,
5727 bool IsInstanceMethod,
5729 StringRef ClassName,
5730 std::string &Result) {
5731 if (MethodBegin == MethodEnd)
return;
5733 if (!objc_impl_method) {
5740 Result +=
"\nstruct _objc_method {\n";
5741 Result +=
"\tSEL _cmd;\n";
5742 Result +=
"\tchar *method_types;\n";
5743 Result +=
"\tvoid *_imp;\n";
5746 objc_impl_method =
true;
5757 unsigned NumMethods =
std::distance(MethodBegin, MethodEnd);
5758 Result +=
"\nstatic struct {\n";
5759 Result +=
"\tstruct _objc_method_list *next_method;\n";
5760 Result +=
"\tint method_count;\n";
5761 Result +=
"\tstruct _objc_method method_list[";
5762 Result += utostr(NumMethods);
5763 Result +=
"];\n} _OBJC_";
5765 Result += IsInstanceMethod ?
"INSTANCE" :
"CLASS";
5766 Result +=
"_METHODS_";
5767 Result += ClassName;
5768 Result +=
" __attribute__ ((used, section (\"__OBJC, __";
5769 Result += IsInstanceMethod ?
"inst" :
"cls";
5770 Result +=
"_meth\")))= ";
5771 Result +=
"{\n\t0, " + utostr(NumMethods) +
"\n";
5773 Result +=
"\t,{{(SEL)\"";
5774 Result += (*MethodBegin)->getSelector().getAsString();
5775 std::string MethodTypeString =
5778 Result += MethodTypeString;
5779 Result +=
"\", (void *)";
5780 Result += MethodInternalNames[*MethodBegin];
5782 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
5783 Result +=
"\t ,{(SEL)\"";
5784 Result += (*MethodBegin)->getSelector().getAsString();
5785 std::string MethodTypeString =
5788 Result += MethodTypeString;
5789 Result +=
"\", (void *)";
5790 Result += MethodInternalNames[*MethodBegin];
5793 Result +=
"\t }\n};\n";
5802 DisableReplaceStmtScope S(*
this);
5803 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
5814 assert(iFaceDecl &&
"RewriteObjCIvarRefExpr - iFaceDecl is null");
5819 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5828 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5848 assert(!IV->
isFreeIvar() &&
"Cannot have a free standing ivar outside a method");
5859 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5862 std::string RecName = clsDeclared->getIdentifier()->getName();
5868 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5883 ReplaceStmtWithRange(IV, Replacement, OldRange);
5887 #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.
An instance of this class is created to represent 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
isOverloadedOperator - Whether this function declaration represents an C++ overloaded 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()
completeDefinition - Notes 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.
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
isCompleteDefinition - 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.
VarDecl - An instance of this class is created to represent 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
getIdentifier - Get the identifier that names this declaration, if there is one.
RecordDecl - 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
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
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
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
TypeDecl - 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.
SourceLocation getLocEnd() const LLVM_READONLY
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)
SourceLocation getLocEnd() const LLVM_READONLY
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
BlockDecl - This represents a block literal declaration, which is like an unnamed FunctionDecl...
ValueDecl - Represent the declaration of a variable (in which case it is an lvalue) a function (in wh...
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 FunctionProtoType * T
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
getNameAsString - Get a human-readable name for the declaration, even if it is one of the special kin...
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.
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
getName - 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...
TranslationUnitDecl - 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
NamedDecl - This represents a decl with 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 getLocStart() const LLVM_READONLY
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...