22 #include "clang/Config/config.h" 25 #include "llvm/ADT/DenseSet.h" 26 #include "llvm/ADT/SmallPtrSet.h" 27 #include "llvm/ADT/StringExtras.h" 28 #include "llvm/Support/MemoryBuffer.h" 29 #include "llvm/Support/raw_ostream.h" 32 #if CLANG_ENABLE_OBJC_REWRITER 34 using namespace clang;
54 BLOCK_NEEDS_FREE = (1 << 24),
57 BLOCK_IS_GC = (1 << 27),
59 BLOCK_HAS_DESCRIPTOR = (1 << 29)
61 static const int OBJC_ABI_VERSION = 7;
70 const char *MainFileStart, *MainFileEnd;
73 std::string InFileName;
74 std::unique_ptr<raw_ostream> OutFile;
79 unsigned RewriteFailedDiag;
81 unsigned NumObjCStringLiterals;
82 VarDecl *ConstantStringClassReference;
88 unsigned TryFinallyContainsReturnDiag;
111 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
112 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
113 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
114 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
118 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
131 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
133 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
134 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
135 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
136 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
138 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
143 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
147 bool SilenceRewriteMacroWarning;
148 bool objc_impl_method;
150 bool DisableReplaceStmt;
151 class DisableReplaceStmtScope {
157 : R(R), SavedValue(R.DisableReplaceStmt) {
158 R.DisableReplaceStmt =
true;
161 ~DisableReplaceStmtScope() {
162 R.DisableReplaceStmt = SavedValue;
173 if (!
Class->isThisDeclarationADefinition()) {
174 RewriteForwardClassDecl(D);
180 if (!Proto->isThisDeclarationADefinition()) {
181 RewriteForwardProtocolDecl(D);
186 HandleTopLevelSingleDecl(*I);
191 void HandleTopLevelSingleDecl(
Decl *D);
192 void HandleDeclInMainFile(
Decl *D);
193 RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
195 bool silenceMacroWarn);
199 void HandleTranslationUnit(
ASTContext &
C)
override;
201 void ReplaceStmt(
Stmt *Old,
Stmt *New) {
206 assert(Old !=
nullptr && New !=
nullptr &&
"Expected non-null Stmt's");
208 Stmt *ReplacingStmt = ReplacedNodes[Old];
212 if (DisableReplaceStmt)
224 llvm::raw_string_ostream S(SStr);
226 const std::string &Str = S.str();
230 ReplacedNodes[Old] = New;
233 if (SilenceRewriteMacroWarning)
240 bool InsertAfter =
true) {
242 if (!Rewrite.
InsertText(Loc, Str, InsertAfter) ||
243 SilenceRewriteMacroWarning)
252 if (!Rewrite.
ReplaceText(Start, OrigLength, Str) ||
253 SilenceRewriteMacroWarning)
261 void RewriteInclude();
265 const std::string &typedefString);
266 void RewriteImplementations();
271 void RewriteImplementationDecl(
Decl *Dcl);
274 void RewriteTypeIntoString(
QualType T, std::string &ResultStr,
276 void RewriteByRefString(std::string &ResultStr,
const std::string &Name,
285 void RewriteBlockPointerType(std::string& Str,
QualType Type);
286 void RewriteBlockPointerTypeVariable(std::string& Str,
ValueDecl *VD);
288 void RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl);
289 void RewriteTypeOfDecl(
VarDecl *VD);
290 void RewriteObjCQualifiedInterfaceTypes(
Expr *E);
293 Stmt *RewriteFunctionBodyOrGlobalInitializer(
Stmt *S);
301 void RewriteTryReturnStmts(
Stmt *S);
302 void RewriteSyncReturnStmts(
Stmt *S, std::string buf);
316 void RewriteBlockPointerDecl(
NamedDecl *VD);
317 void RewriteByRefVar(
VarDecl *VD);
325 void Initialize(
ASTContext &context)
override = 0;
328 virtual void RewriteMetaDataIntoBuffer(std::string &
Result) = 0;
344 virtual void RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
363 void SynthCountByEnumWithState(std::string &buf);
364 void SynthMsgSendFunctionDecl();
365 void SynthMsgSendSuperFunctionDecl();
366 void SynthMsgSendStretFunctionDecl();
367 void SynthMsgSendFpretFunctionDecl();
368 void SynthMsgSendSuperStretFunctionDecl();
369 void SynthGetClassFunctionDecl();
370 void SynthGetMetaClassFunctionDecl();
371 void SynthGetSuperClassFunctionDecl();
372 void SynthSelGetUidFunctionDecl();
373 void SynthSuperConstructorFunctionDecl();
375 std::string SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
int flag);
376 std::string SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
377 StringRef funcName, std::string Tag);
378 std::string SynthesizeBlockFunc(
BlockExpr *CE,
int i,
379 StringRef funcName, std::string Tag);
380 std::string SynthesizeBlockImpl(
BlockExpr *CE,
381 std::string Tag, std::string Desc);
382 std::string SynthesizeBlockDescriptor(std::string DescTag,
384 int i, StringRef funcName,
395 void WarnAboutReturnGotoStmts(
Stmt *S);
396 void HasReturnStmts(
Stmt *S,
bool &hasReturns);
398 void InsertBlockLiteralsWithinFunction(
FunctionDecl *FD);
401 bool IsDeclStmtInForeachHeader(
DeclStmt *DS);
402 void CollectBlockDeclRefInfo(
BlockExpr *Exp);
403 void GetBlockDeclRefExprs(
Stmt *S);
404 void GetInnerBlockDeclRefExprs(
Stmt *S,
406 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
410 bool isTopLevelBlockPointerType(
QualType T) {
411 return isa<BlockPointerType>(T);
417 bool convertBlockPointerToFunctionPointer(
QualType &T) {
418 if (isTopLevelBlockPointerType(T)) {
426 bool needToScanForQualifiers(
QualType T);
428 QualType getConstantStringStructType();
430 bool BufferContainsPPDirectives(
const char *startBuf,
const char *endBuf);
432 void convertToUnqualifiedObjCType(
QualType &T) {
460 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
461 PT->getPointeeType()->isObjCQualifiedIdType())
466 bool PointerTypeTakesAnyBlockArguments(
QualType QT);
467 bool PointerTypeTakesAnyObjCQualifiedType(
QualType QT);
468 void GetExtentOfArgList(
const char *Name,
const char *&LParen,
469 const char *&RParen);
471 void QuoteDoublequotes(std::string &From, std::string &To) {
472 for (
unsigned i = 0; i < From.length(); i++) {
482 bool variadic =
false) {
509 RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
511 bool silenceMacroWarn)
512 :
RewriteObjC(inFile,
std::move(OS), D, LOpts, silenceMacroWarn) {}
514 ~RewriteObjCFragileABI()
override {}
515 void Initialize(
ASTContext &context)
override;
518 template<
typename MethodIterator>
519 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
520 MethodIterator MethodEnd,
521 bool IsInstanceMethod,
526 StringRef prefix, StringRef ClassName,
527 std::string &
Result)
override;
528 void RewriteObjCProtocolListMetaData(
530 StringRef prefix, StringRef ClassName, std::string &
Result)
override;
532 std::string &
Result)
override;
533 void RewriteMetaDataIntoBuffer(std::string &
Result)
override;
535 std::string &
Result)
override;
539 std::string &
Result)
override;
544 void RewriteObjC::RewriteBlocksInFunctionProtoType(
QualType funcType,
547 = dyn_cast<FunctionProtoType>(funcType.
IgnoreParens())) {
548 for (
const auto &I : fproto->param_types())
549 if (isTopLevelBlockPointerType(I)) {
551 RewriteBlockPointerDecl(D);
559 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
564 std::string::size_type DotPos = Filename.rfind(
'.');
566 if (DotPos == std::string::npos) {
571 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
574 return Ext ==
"h" || Ext ==
"hh" || Ext ==
"H";
579 bool silenceMacroWarn)
580 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
581 SilenceRewriteMacroWarning(silenceMacroWarn) {
584 "rewriting sub-expression within a macro (may not be correct)");
587 "rewriter doesn't support user-specified control flow semantics " 588 "for @try/@finally (code may not execute properly)");
591 std::unique_ptr<ASTConsumer>
593 std::unique_ptr<raw_ostream> OS,
595 bool SilenceRewriteMacroWarning) {
596 return std::make_unique<RewriteObjCFragileABI>(
597 InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);
600 void RewriteObjC::InitializeCommon(
ASTContext &context) {
604 MsgSendFunctionDecl =
nullptr;
605 MsgSendSuperFunctionDecl =
nullptr;
606 MsgSendStretFunctionDecl =
nullptr;
607 MsgSendSuperStretFunctionDecl =
nullptr;
608 MsgSendFpretFunctionDecl =
nullptr;
609 GetClassFunctionDecl =
nullptr;
610 GetMetaClassFunctionDecl =
nullptr;
611 GetSuperClassFunctionDecl =
nullptr;
612 SelGetUidFunctionDecl =
nullptr;
613 CFStringFunctionDecl =
nullptr;
614 ConstantStringClassReference =
nullptr;
615 NSStringRecord =
nullptr;
616 CurMethodDef =
nullptr;
617 CurFunctionDef =
nullptr;
618 CurFunctionDeclToDeclareForBlock =
nullptr;
619 GlobalVarDecl =
nullptr;
620 SuperStructDecl =
nullptr;
621 ProtocolTypeDecl =
nullptr;
622 ConstantStringDecl =
nullptr;
624 SuperConstructorFunctionDecl =
nullptr;
625 NumObjCStringLiterals = 0;
626 PropParentMap =
nullptr;
627 CurrentBody =
nullptr;
628 DisableReplaceStmt =
false;
629 objc_impl_method =
false;
633 const llvm::MemoryBuffer *MainBuf = SM->
getBuffer(MainFileID);
634 MainFileStart = MainBuf->getBufferStart();
635 MainFileEnd = MainBuf->getBufferEnd();
644 void RewriteObjC::HandleTopLevelSingleDecl(
Decl *D) {
659 RewriteFunctionDecl(FD);
660 }
else if (
VarDecl *FVD = dyn_cast<VarDecl>(D)) {
662 if (FVD->getName() ==
"_NSConstantStringClassReference") {
663 ConstantStringClassReference = FVD;
667 if (
ID->isThisDeclarationADefinition())
668 RewriteInterfaceDecl(
ID);
670 RewriteCategoryDecl(CD);
672 if (PD->isThisDeclarationADefinition())
673 RewriteProtocolDecl(PD);
677 DIEnd = LSD->decls_end();
680 if (!IFace->isThisDeclarationADefinition()) {
684 if (isa<ObjCInterfaceDecl>(*DI) &&
685 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
686 StartLoc == (*DI)->getBeginLoc())
692 }
while (DI != DIEnd);
693 RewriteForwardClassDecl(DG);
699 if (!Proto->isThisDeclarationADefinition()) {
703 if (isa<ObjCProtocolDecl>(*DI) &&
704 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
705 StartLoc == (*DI)->getBeginLoc())
711 }
while (DI != DIEnd);
712 RewriteForwardProtocolDecl(DG);
717 HandleTopLevelSingleDecl(*DI);
723 return HandleDeclInMainFile(D);
730 void RewriteObjC::RewriteInclude() {
733 const char *MainBufStart = MainBuf.begin();
734 const char *MainBufEnd = MainBuf.end();
735 size_t ImportLen = strlen(
"import");
738 for (
const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
739 if (*BufPtr ==
'#') {
740 if (++BufPtr == MainBufEnd)
742 while (*BufPtr ==
' ' || *BufPtr ==
'\t')
743 if (++BufPtr == MainBufEnd)
745 if (!strncmp(BufPtr,
"import", ImportLen)) {
749 ReplaceText(ImportLoc, ImportLen,
"include");
761 S +=
"_IMPL *)self)->";
769 static bool objcGetPropertyDefined =
false;
770 static bool objcSetPropertyDefined =
false;
772 InsertText(startLoc,
"// ");
774 assert((*startBuf ==
'@') &&
"bogus @synthesize location");
775 const char *semiBuf = strchr(startBuf,
';');
776 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);
855 if (GenSetProperty && !objcSetPropertyDefined) {
856 objcSetPropertyDefined =
true;
858 Setr =
"\nextern \"C\" __declspec(dllimport) " 859 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
867 if (GenSetProperty) {
868 Setr +=
"objc_setProperty (self, _cmd, ";
869 RewriteIvarOffsetComputation(OID, Setr);
887 InsertText(onePastSemiLoc, Setr);
891 std::string &typedefString) {
892 typedefString +=
"#ifndef _REWRITER_typedef_";
894 typedefString +=
"\n";
895 typedefString +=
"#define _REWRITER_typedef_";
897 typedefString +=
"\n";
898 typedefString +=
"typedef struct objc_object ";
900 typedefString +=
";\n#endif\n";
904 const std::string &typedefString) {
907 const char *semiPtr = strchr(startBuf,
';');
909 ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);
912 void RewriteObjC::RewriteForwardClassDecl(
DeclGroupRef D) {
913 std::string typedefString;
916 if (I == D.
begin()) {
920 typedefString +=
"// @class ";
922 typedefString +=
";\n";
927 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
931 std::string typedefString;
932 for (
unsigned i = 0; i < D.size(); i++) {
935 typedefString +=
"// @class ";
937 typedefString +=
";\n";
941 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
944 void RewriteObjC::RewriteMethodDeclaration(
ObjCMethodDecl *Method) {
954 InsertText(LocStart,
"#if 0\n");
955 ReplaceText(LocEnd, 1,
";\n#endif\n");
957 InsertText(LocStart,
"// ");
964 ReplaceText(Loc, 0,
"// ");
972 ReplaceText(LocStart, 0,
"// ");
977 RewriteMethodDeclaration(I);
979 RewriteMethodDeclaration(I);
983 strlen(
"@end"),
"/* @end */");
991 ReplaceText(LocStart, 0,
"// ");
994 RewriteMethodDeclaration(I);
996 RewriteMethodDeclaration(I);
1002 ReplaceText(LocEnd, strlen(
"@end"),
"/* @end */");
1007 for (
const char *p = startBuf; p < endBuf; p++) {
1008 if (*p ==
'@' && !strncmp(p+1,
"optional", strlen(
"optional"))) {
1010 ReplaceText(OptionalLoc, strlen(
"@optional"),
"/* @optional */");
1013 else if (*p ==
'@' && !strncmp(p+1,
"required", strlen(
"required"))) {
1015 ReplaceText(OptionalLoc, strlen(
"@required"),
"/* @required */");
1021 void RewriteObjC::RewriteForwardProtocolDecl(
DeclGroupRef D) {
1024 llvm_unreachable(
"Invalid SourceLocation");
1026 ReplaceText(LocStart, 0,
"// ");
1033 llvm_unreachable(
"Invalid SourceLocation");
1035 ReplaceText(LocStart, 0,
"// ");
1038 void RewriteObjC::RewriteTypeIntoString(
QualType T, std::string &ResultStr,
1063 std::string &ResultStr) {
1066 ResultStr +=
"\nstatic ";
1067 RewriteTypeIntoString(OMD->
getReturnType(), ResultStr, FPRetType);
1071 std::string NameStr;
1089 int len = selString.size();
1090 for (
int i = 0; i < len; i++)
1091 if (selString[i] ==
':')
1093 NameStr += selString;
1096 MethodInternalNames[OMD] = NameStr;
1097 ResultStr += NameStr;
1106 if (!LangOpts.MicrosoftExt) {
1107 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
1108 ResultStr +=
"struct ";
1118 ResultStr +=
" self, ";
1120 ResultStr +=
" _cmd";
1123 for (
const auto *PDecl : OMD->
parameters()) {
1125 if (PDecl->getType()->isObjCQualifiedIdType()) {
1132 (void)convertBlockPointerToFunctionPointer(QT);
1138 ResultStr +=
", ...";
1147 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
1148 if (i) ResultStr +=
", ";
1149 std::string ParamStr =
1151 ResultStr += ParamStr;
1153 if (FT->isVariadic()) {
1154 if (FT->getNumParams())
1165 void RewriteObjC::RewriteImplementationDecl(
Decl *OID) {
1168 assert((IMD || CID) &&
"Unknown ImplementationDecl");
1170 InsertText(IMD ? IMD->
getBeginLoc() : CID->getBeginLoc(),
"// ");
1172 for (
auto *OMD : IMD ? IMD->
instance_methods() : CID->instance_methods()) {
1175 std::string ResultStr;
1182 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1185 for (
auto *OMD : IMD ? IMD->
class_methods() : CID->class_methods()) {
1188 std::string ResultStr;
1195 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1197 for (
auto *I : IMD ? IMD->
property_impls() : CID->property_impls())
1198 RewritePropertyImplDecl(I, IMD, CID);
1200 InsertText(IMD ? IMD->
getEndLoc() : CID->getEndLoc(),
"// ");
1204 std::string ResultStr;
1207 ResultStr =
"#ifndef _REWRITER_typedef_";
1210 ResultStr +=
"#define _REWRITER_typedef_";
1213 ResultStr +=
"typedef struct objc_object ";
1215 ResultStr +=
";\n#endif\n";
1219 RewriteObjCInternalStruct(ClassDecl, ResultStr);
1224 RewriteMethodDeclaration(I);
1226 RewriteMethodDeclaration(I);
1246 DisableReplaceStmtScope S(*
this);
1252 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1253 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1258 RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
1259 RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1311 Stmt *Replacement = SynthMessageExpr(NewMsg);
1312 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1328 DisableReplaceStmtScope S(*
this);
1333 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1334 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1387 Stmt *Replacement = SynthMessageExpr(NewMsg);
1388 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1401 void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1402 buf +=
"((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 1403 "id *, unsigned int))(void *)objc_msgSend)";
1405 buf +=
"((id)l_collection,\n\t\t";
1406 buf +=
"sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1408 buf +=
"&enumState, " 1409 "(id *)__rw_items, (unsigned int)16)";
1416 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1422 buf =
"goto __break_label_";
1423 buf += utostr(ObjCBcLabelNo.back());
1424 ReplaceText(startLoc, strlen(
"break"), buf);
1433 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1439 buf =
"goto __continue_label_";
1440 buf += utostr(ObjCBcLabelNo.back());
1441 ReplaceText(startLoc, strlen(
"continue"), buf);
1480 assert(!Stmts.empty() &&
"ObjCForCollectionStmt - Statement stack empty");
1481 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1482 "ObjCForCollectionStmt Statement stack mismatch");
1483 assert(!ObjCBcLabelNo.empty() &&
1484 "ObjCForCollectionStmt - Label No stack empty");
1488 StringRef elementName;
1489 std::string elementTypeAsString;
1494 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1495 QualType ElementType = cast<ValueDecl>(D)->getType();
1496 if (ElementType->isObjCQualifiedIdType() ||
1497 ElementType->isObjCQualifiedInterfaceType())
1499 elementTypeAsString =
"id";
1502 buf += elementTypeAsString;
1515 elementTypeAsString =
"id";
1521 buf +=
"struct __objcFastEnumerationState enumState = { 0 };\n\t";
1523 buf +=
"id __rw_items[16];\n\t";
1525 buf +=
"id l_collection = (id)";
1527 const char *startCollectionBuf = startBuf;
1528 startCollectionBuf += 3;
1529 startCollectionBuf = strchr(startCollectionBuf,
'(');
1530 startCollectionBuf++;
1532 while (*startCollectionBuf !=
' ' ||
1533 *(startCollectionBuf+1) !=
'i' || *(startCollectionBuf+2) !=
'n' ||
1534 (*(startCollectionBuf+3) !=
' ' &&
1535 *(startCollectionBuf+3) !=
'[' && *(startCollectionBuf+3) !=
'('))
1536 startCollectionBuf++;
1537 startCollectionBuf += 3;
1540 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1558 buf +=
"unsigned long limit =\n\t\t";
1559 SynthCountByEnumWithState(buf);
1569 buf +=
"if (limit) {\n\t";
1570 buf +=
"unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1571 buf +=
"do {\n\t\t";
1572 buf +=
"unsigned long counter = 0;\n\t\t";
1573 buf +=
"do {\n\t\t\t";
1574 buf +=
"if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1575 buf +=
"objc_enumerationMutation(l_collection);\n\t\t\t";
1578 buf += elementTypeAsString;
1579 buf +=
")enumState.itemsPtr[counter++];";
1581 ReplaceText(lparenLoc, 1, buf);
1595 buf +=
"__continue_label_";
1596 buf += utostr(ObjCBcLabelNo.back());
1599 buf +=
"} while (counter < limit);\n\t";
1600 buf +=
"} while (limit = ";
1601 SynthCountByEnumWithState(buf);
1605 buf += elementTypeAsString;
1607 buf +=
"__break_label_";
1608 buf += utostr(ObjCBcLabelNo.back());
1611 buf +=
"else\n\t\t";
1614 buf += elementTypeAsString;
1620 if (isa<CompoundStmt>(S->
getBody())) {
1622 InsertText(endBodyLoc, buf);
1632 const char *semiBuf = strchr(stmtBuf,
';');
1633 assert(semiBuf &&
"Can't find ';'");
1635 InsertText(endBodyLoc, buf);
1638 ObjCBcLabelNo.pop_back();
1653 assert((*startBuf ==
'@') &&
"bogus @synchronized location");
1656 buf =
"objc_sync_enter((id)";
1657 const char *lparenBuf = startBuf;
1658 while (*lparenBuf !=
'(') lparenBuf++;
1659 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1665 while (*endBuf !=
')') endBuf--;
1669 buf +=
"/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1670 buf +=
"int buf[18/*32-bit i386*/];\n";
1671 buf +=
"char *pointers[4];} _stack;\n";
1672 buf +=
"id volatile _rethrow = 0;\n";
1673 buf +=
"objc_exception_try_enter(&_stack);\n";
1674 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1675 ReplaceText(rparenLoc, 1, buf);
1679 assert((*startBuf ==
'}') &&
"bogus @synchronized block");
1681 buf =
"}\nelse {\n";
1682 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1684 buf +=
"{ /* implicit finally clause */\n";
1685 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1687 std::string syncBuf;
1688 syncBuf +=
" objc_sync_exit(";
1694 ? CK_BlockPointerToObjCPointerCast
1695 : CK_CPointerToObjCPointerCast;
1696 syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
1698 std::string syncExprBufS;
1699 llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1700 assert(syncExpr !=
nullptr &&
"Expected non-null Expr");
1702 syncBuf += syncExprBuf.str();
1706 buf +=
"\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1710 ReplaceText(lastCurlyLoc, 1, buf);
1712 bool hasReturns =
false;
1720 void RewriteObjC::WarnAboutReturnGotoStmts(
Stmt *S)
1725 WarnAboutReturnGotoStmts(SubStmt);
1727 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1729 TryFinallyContainsReturnDiag);
1733 void RewriteObjC::HasReturnStmts(
Stmt *S,
bool &hasReturns)
1738 HasReturnStmts(SubStmt, hasReturns);
1740 if (isa<ReturnStmt>(S))
1744 void RewriteObjC::RewriteTryReturnStmts(
Stmt *S) {
1748 RewriteTryReturnStmts(SubStmt);
1750 if (isa<ReturnStmt>(S)) {
1753 const char *semiBuf = strchr(startBuf,
';');
1754 assert((*semiBuf ==
';') &&
"RewriteTryReturnStmts: can't find ';'");
1758 buf =
"{ objc_exception_try_exit(&_stack); return";
1760 ReplaceText(startLoc, 6, buf);
1761 InsertText(onePastSemiLoc,
"}");
1765 void RewriteObjC::RewriteSyncReturnStmts(
Stmt *S, std::string syncExitBuf) {
1769 RewriteSyncReturnStmts(SubStmt, syncExitBuf);
1771 if (isa<ReturnStmt>(S)) {
1775 const char *semiBuf = strchr(startBuf,
';');
1776 assert((*semiBuf ==
';') &&
"RewriteSyncReturnStmts: can't find ';'");
1780 buf =
"{ objc_exception_try_exit(&_stack);";
1784 ReplaceText(startLoc, 6, buf);
1785 InsertText(onePastSemiLoc,
"}");
1794 assert((*startBuf ==
'@') &&
"bogus @try location");
1798 buf =
"/* @try scope begin */ { struct _objc_exception_data {\n";
1799 buf +=
"int buf[18/*32-bit i386*/];\n";
1800 buf +=
"char *pointers[4];} _stack;\n";
1801 buf +=
"id volatile _rethrow = 0;\n";
1802 buf +=
"objc_exception_try_enter(&_stack);\n";
1803 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1805 ReplaceText(startLoc, 4, buf);
1810 assert((*startBuf ==
'}') &&
"bogus @try block");
1815 buf =
" /* @catch begin */ else {\n";
1816 buf +=
" id _caught = objc_exception_extract(&_stack);\n";
1817 buf +=
" objc_exception_try_enter (&_stack);\n";
1818 buf +=
" if (_setjmp(_stack.buf))\n";
1819 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1820 buf +=
" else { /* @catch continue */";
1822 InsertText(startLoc, buf);
1824 buf =
"}\nelse {\n";
1825 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1827 ReplaceText(lastCurlyLoc, 1, buf);
1829 Stmt *lastCatchBody =
nullptr;
1841 assert((*startBuf ==
'@') &&
"bogus @catch location");
1843 const char *lParenLoc = strchr(startBuf,
'(');
1851 "bogus @catch paren location");
1852 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1854 buf +=
"1) { id _tmp = _caught;";
1855 Rewrite.
ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
1856 }
else if (catchDecl) {
1860 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1866 buf +=
"objc_exception_match((struct objc_class *)objc_getClass(\"";
1868 buf +=
"\"), (struct objc_object *)_caught)) { ";
1869 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1878 assert((*rParenBuf ==
')') &&
"bogus @catch paren location");
1879 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1883 ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
" = _caught;");
1885 llvm_unreachable(
"@catch rewrite bug");
1889 if (lastCatchBody) {
1892 "bogus @catch body location");
1896 buf =
"} /* last catch end */\n";
1898 buf +=
" _rethrow = _caught;\n";
1899 buf +=
" objc_exception_try_exit(&_stack);\n";
1900 buf +=
"} } /* @catch end */\n";
1903 InsertText(bodyLoc, buf);
1906 lastCurlyLoc = lastCatchBody->
getEndLoc();
1909 startLoc = finalStmt->getBeginLoc();
1911 assert((*startBuf ==
'@') &&
"bogus @finally start");
1913 ReplaceText(startLoc, 8,
"/* @finally */");
1915 Stmt *body = finalStmt->getFinallyBody();
1919 "bogus @finally body location");
1921 "bogus @finally body location");
1924 InsertText(startLoc,
" if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1926 InsertText(endLoc,
" if (_rethrow) objc_exception_throw(_rethrow);\n");
1934 buf =
"{ /* implicit finally clause */\n";
1935 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1936 buf +=
" if (_rethrow) objc_exception_throw(_rethrow);\n";
1938 ReplaceText(lastCurlyLoc, 1, buf);
1943 bool hasReturns =
false;
1950 InsertText(lastCurlyLoc,
" } /* @try scope end */\n");
1962 assert((*startBuf ==
'@') &&
"bogus @throw location");
1967 buf =
"objc_exception_throw(";
1969 buf =
"objc_exception_throw(_caught";
1972 const char *wBuf = strchr(startBuf,
'w');
1973 assert((*wBuf ==
'w') &&
"@throw: can't find 'w'");
1974 ReplaceText(startLoc, wBuf-startBuf+1, buf);
1976 const char *semiBuf = strchr(startBuf,
';');
1977 assert((*semiBuf ==
';') &&
"@throw: can't find ';'");
1979 ReplaceText(semiLoc, 1,
");");
1985 std::string StrEncoding;
1987 Expr *Replacement = getStringLiteral(StrEncoding);
1988 ReplaceStmt(Exp, Replacement);
1996 if (!SelGetUidFunctionDecl)
1997 SynthSelGetUidFunctionDecl();
1998 assert(SelGetUidFunctionDecl &&
"Can't find sel_registerName() decl");
2002 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2004 ReplaceStmt(Exp, SelExp);
2010 RewriteObjC::SynthesizeCallToFunctionDecl(
FunctionDecl *FD,
2030 *Context, ICE, Args, FT->getCallResultType(*Context),
VK_RValue, EndLoc);
2035 const char *&startRef,
const char *&endRef) {
2036 while (startBuf < endBuf) {
2037 if (*startBuf ==
'<')
2038 startRef = startBuf;
2039 if (*startBuf ==
'>') {
2040 if (startRef && *startRef ==
'<') {
2053 while (*argRef !=
')' && (*argRef !=
',' || angle > 0)) {
2056 else if (*argRef ==
'>')
2060 assert(angle == 0 &&
"scanToNextArgument - bad protocol type syntax");
2063 bool RewriteObjC::needToScanForQualifiers(
QualType T) {
2076 return needToScanForQualifiers(ElemTy);
2081 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Expr *E) {
2083 if (needToScanForQualifiers(Type)) {
2087 Loc = ECE->getLParenLoc();
2088 EndLoc = ECE->getRParenLoc();
2099 const char *startRef =
nullptr, *endRef =
nullptr;
2105 InsertText(LessLoc,
"/*");
2106 InsertText(GreaterLoc,
"*/");
2111 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl) {
2115 if (
VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2116 Loc = VD->getLocation();
2117 Type = VD->getType();
2119 else if (
FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2124 assert(funcType &&
"missing function type");
2130 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2137 if (needToScanForQualifiers(Type)) {
2141 const char *startBuf = endBuf;
2142 while (*startBuf !=
';' && *startBuf !=
'<' && startBuf != MainFileStart)
2144 const char *startRef =
nullptr, *endRef =
nullptr;
2150 InsertText(LessLoc,
"/*");
2151 InsertText(GreaterLoc,
"*/");
2158 const char *startFuncBuf = startBuf;
2163 const char *endBuf = startBuf;
2166 const char *startRef =
nullptr, *endRef =
nullptr;
2174 InsertText(LessLoc,
"/*");
2175 InsertText(GreaterLoc,
"*/");
2177 startBuf = ++endBuf;
2182 while (*startBuf && *startBuf !=
')' && *startBuf !=
',')
2189 void RewriteObjC::RewriteTypeOfDecl(
VarDecl *ND) {
2192 if (!isa<TypeOfExprType>(TypePtr))
2194 while (isa<TypeOfExprType>(TypePtr)) {
2195 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2206 TypeAsString +=
" " + Name +
" = ";
2210 startLoc = ECE->getLParenLoc();
2215 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2221 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2226 void RewriteObjC::SynthSelGetUidFunctionDecl() {
2235 SelGetUidIdent, getFuncType,
2239 void RewriteObjC::RewriteFunctionDecl(
FunctionDecl *FD) {
2242 FD->
getName() ==
"sel_registerName") {
2243 SelGetUidFunctionDecl = FD;
2246 RewriteObjCQualifiedInterfaceTypes(FD);
2249 void RewriteObjC::RewriteBlockPointerType(std::string& Str,
QualType Type) {
2251 const char *argPtr = TypeString.c_str();
2252 if (!strchr(argPtr,
'^')) {
2257 Str += (*argPtr ==
'^' ?
'*' : *argPtr);
2263 void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2267 const char *argPtr = TypeString.c_str();
2292 void RewriteObjC::RewriteBlockLiteralFunctionDecl(
FunctionDecl *FD) {
2298 QualType Type = proto->getReturnType();
2303 unsigned numArgs = proto->getNumParams();
2304 for (
unsigned i = 0; i < numArgs; i++) {
2305 QualType ArgType = proto->getParamType(i);
2306 RewriteBlockPointerType(FdStr, ArgType);
2311 InsertText(FunLocStart, FdStr);
2312 CurFunctionDeclToDeclareForBlock =
nullptr;
2316 void RewriteObjC::SynthSuperConstructorFunctionDecl() {
2317 if (SuperConstructorFunctionDecl)
2322 assert(!argT.
isNull() &&
"Can't find 'id' type");
2323 ArgTys.push_back(argT);
2324 ArgTys.push_back(argT);
2330 msgSendIdent, msgSendType,
2335 void RewriteObjC::SynthMsgSendFunctionDecl() {
2339 assert(!argT.
isNull() &&
"Can't find 'id' type");
2340 ArgTys.push_back(argT);
2342 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2343 ArgTys.push_back(argT);
2349 msgSendIdent, msgSendType,
2354 void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2361 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2362 ArgTys.push_back(argT);
2364 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2365 ArgTys.push_back(argT);
2371 msgSendIdent, msgSendType,
2376 void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2380 assert(!argT.
isNull() &&
"Can't find 'id' type");
2381 ArgTys.push_back(argT);
2383 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2384 ArgTys.push_back(argT);
2390 msgSendIdent, msgSendType,
2396 void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2398 &Context->
Idents.
get(
"objc_msgSendSuper_stret");
2404 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2405 ArgTys.push_back(argT);
2407 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2408 ArgTys.push_back(argT);
2415 msgSendType,
nullptr,
2420 void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2424 assert(!argT.
isNull() &&
"Can't find 'id' type");
2425 ArgTys.push_back(argT);
2427 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2428 ArgTys.push_back(argT);
2434 msgSendIdent, msgSendType,
2439 void RewriteObjC::SynthGetClassFunctionDecl() {
2448 getClassIdent, getClassType,
2453 void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2455 &Context->
Idents.
get(
"class_getSuperclass");
2464 getClassType,
nullptr,
2469 void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2478 getClassIdent, getClassType,
2483 assert(Exp !=
nullptr &&
"Expected non-null ObjCStringLiteral");
2484 QualType strType = getConstantStringStructType();
2486 std::string S =
"__NSConstantStringImpl_";
2488 std::string tmpName = InFileName;
2490 for (i=0; i < tmpName.length(); i++) {
2491 char c = tmpName.at(i);
2498 S += utostr(NumObjCStringLiterals++);
2500 Preamble +=
"static __NSConstantStringImpl " + S;
2501 Preamble +=
" __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2502 Preamble +=
"0x000007c8,";
2504 std::string prettyBufS;
2505 llvm::raw_string_ostream prettyBuf(prettyBufS);
2507 Preamble += prettyBuf.str();
2516 Expr *Unop =
new (Context)
2521 CK_CPointerToObjCPointerCast, Unop);
2522 ReplaceStmt(Exp, cast);
2528 QualType RewriteObjC::getSuperStructType() {
2529 if (!SuperStructDecl) {
2541 for (
unsigned i = 0; i < 2; ++i) {
2545 FieldTypes[i],
nullptr,
2556 QualType RewriteObjC::getConstantStringStructType() {
2557 if (!ConstantStringDecl) {
2560 &Context->
Idents.
get(
"__NSConstantStringImpl"));
2566 FieldTypes[1] = Context->
IntTy;
2570 FieldTypes[3] = Context->
LongTy;
2573 for (
unsigned i = 0; i < 4; ++i) {
2578 FieldTypes[i],
nullptr,
2597 new (Context)
DeclRefExpr(*Context, MsgSendStretFlavor,
false,
2604 QualType castType = getSimpleFunctionType(returnType, ArgTypes,
2608 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2623 if (!SelGetUidFunctionDecl)
2624 SynthSelGetUidFunctionDecl();
2625 if (!MsgSendFunctionDecl)
2626 SynthMsgSendFunctionDecl();
2627 if (!MsgSendSuperFunctionDecl)
2628 SynthMsgSendSuperFunctionDecl();
2629 if (!MsgSendStretFunctionDecl)
2630 SynthMsgSendStretFunctionDecl();
2631 if (!MsgSendSuperStretFunctionDecl)
2632 SynthMsgSendSuperStretFunctionDecl();
2633 if (!MsgSendFpretFunctionDecl)
2634 SynthMsgSendFpretFunctionDecl();
2635 if (!GetClassFunctionDecl)
2636 SynthGetClassFunctionDecl();
2637 if (!GetSuperClassFunctionDecl)
2638 SynthGetSuperClassFunctionDecl();
2639 if (!GetMetaClassFunctionDecl)
2640 SynthGetMetaClassFunctionDecl();
2647 QualType resultType = mDecl->getReturnType();
2649 MsgSendStretFlavor = MsgSendStretFunctionDecl;
2651 MsgSendFlavor = MsgSendFpretFunctionDecl;
2658 MsgSendFlavor = MsgSendSuperFunctionDecl;
2659 if (MsgSendStretFlavor)
2660 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2661 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2668 InitExprs.push_back(
2682 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2683 ClsExprs, StartLoc, EndLoc);
2685 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2689 ClsExprs.push_back(ArgExpr);
2690 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2694 InitExprs.push_back(
2695 NoTypeInfoCStyleCastExpr(Context,
2699 QualType superType = getSuperStructType();
2702 if (LangOpts.MicrosoftExt) {
2703 SynthSuperConstructorFunctionDecl();
2706 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2720 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2722 CK_BitCast, SuperRep);
2739 MsgExprs.push_back(SuperRep);
2748 ClsExprs.push_back(getStringLiteral(clsName->
getName()));
2749 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2751 MsgExprs.push_back(Cls);
2756 MsgSendFlavor = MsgSendSuperFunctionDecl;
2757 if (MsgSendStretFlavor)
2758 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2759 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2763 InitExprs.push_back(
2776 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2779 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2783 ClsExprs.push_back(ArgExpr);
2784 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2789 InitExprs.push_back(
2794 QualType superType = getSuperStructType();
2797 if (LangOpts.MicrosoftExt) {
2798 SynthSuperConstructorFunctionDecl();
2801 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2815 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2817 CK_BitCast, SuperRep);
2829 MsgExprs.push_back(SuperRep);
2838 recExpr = CE->getSubExpr();
2841 ? CK_BlockPointerToObjCPointerCast
2842 : CK_CPointerToObjCPointerCast;
2844 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
2846 MsgExprs.push_back(recExpr);
2854 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2855 SelExprs, StartLoc, EndLoc);
2856 MsgExprs.push_back(SelExp);
2859 for (
unsigned i = 0; i < Exp->
getNumArgs(); i++) {
2865 if (needToScanForQualifiers(type))
2868 (void)convertBlockPointerToFunctionPointer(type);
2873 CK = CK_IntegralToBoolean;
2876 CK = CK_BlockPointerToObjCPointerCast;
2878 CK = CK_CPointerToObjCPointerCast;
2886 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2889 else if (
CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2890 if (CE->getType()->isObjCQualifiedIdType()) {
2891 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2892 userExpr = CE->getSubExpr();
2895 CK = CK_IntegralToPointer;
2897 CK = CK_BlockPointerToObjCPointerCast;
2899 CK = CK_CPointerToObjCPointerCast;
2903 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
2907 MsgExprs.push_back(userExpr);
2919 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2920 ArgTypes.push_back(Context->
getPointerType(getSuperStructType()));
2931 (void)convertBlockPointerToFunctionPointer(t);
2932 ArgTypes.push_back(t);
2935 convertToUnqualifiedObjCType(returnType);
2936 (void)convertBlockPointerToFunctionPointer(returnType);
2951 cast = NoTypeInfoCStyleCastExpr(Context,
2959 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() :
true);
2961 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2970 Stmt *ReplacingStmt = CE;
2971 if (MsgSendStretFlavor) {
2977 CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
2978 msgSendType, returnType,
3012 return ReplacingStmt;
3016 Stmt *ReplacingStmt =
3020 ReplaceStmt(Exp, ReplacingStmt);
3023 return ReplacingStmt;
3027 QualType RewriteObjC::getProtocolType() {
3028 if (!ProtocolTypeDecl) {
3057 ReplaceStmt(Exp, castExpr);
3063 bool RewriteObjC::BufferContainsPPDirectives(
const char *startBuf,
3064 const char *endBuf) {
3065 while (startBuf < endBuf) {
3066 if (*startBuf ==
'#') {
3068 for (++startBuf; startBuf[0] ==
' ' || startBuf[0] ==
'\t'; ++startBuf)
3070 if (!strncmp(startBuf,
"if", strlen(
"if")) ||
3071 !strncmp(startBuf,
"ifdef", strlen(
"ifdef")) ||
3072 !strncmp(startBuf,
"ifndef", strlen(
"ifndef")) ||
3073 !strncmp(startBuf,
"define", strlen(
"define")) ||
3074 !strncmp(startBuf,
"undef", strlen(
"undef")) ||
3075 !strncmp(startBuf,
"else", strlen(
"else")) ||
3076 !strncmp(startBuf,
"elif", strlen(
"elif")) ||
3077 !strncmp(startBuf,
"endif", strlen(
"endif")) ||
3078 !strncmp(startBuf,
"pragma", strlen(
"pragma")) ||
3079 !strncmp(startBuf,
"include", strlen(
"include")) ||
3080 !strncmp(startBuf,
"import", strlen(
"import")) ||
3081 !strncmp(startBuf,
"include_next", strlen(
"include_next")))
3093 assert(CDecl &&
"Class missing in SynthesizeObjCInternalStruct");
3094 assert(CDecl->
getName() !=
"" &&
3095 "Name missing in SynthesizeObjCInternalStruct");
3097 if (ObjCSynthesizedStructs.count(CDecl))
3110 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3112 ReplaceText(LocStart, endBuf-startBuf, Result);
3118 Result +=
"\nstruct ";
3120 if (LangOpts.MicrosoftExt)
3124 const char *cursor = strchr(startBuf,
'{');
3125 assert((cursor && endBuf)
3126 &&
"SynthesizeObjCInternalStruct - malformed @interface");
3142 if (BufferContainsPPDirectives(startBuf, cursor)) {
3150 while (endHeader < cursor && *endHeader != '>
') endHeader++; 3153 // rewrite the original header 3154 ReplaceText(LocStart, endHeader-startBuf, Result); 3156 // rewrite the original header *without* disturbing the '{
' 3157 ReplaceText(LocStart, cursor-startBuf, Result); 3159 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 3160 Result = "\n struct "; 3161 Result += RCDecl->getNameAsString(); 3163 Result += RCDecl->getNameAsString(); 3164 Result += "_IVARS;\n"; 3166 // insert the super class structure definition. 3167 SourceLocation OnePastCurly = 3168 LocStart.getLocWithOffset(cursor-startBuf+1); 3169 InsertText(OnePastCurly, Result); 3171 cursor++; // past '{
' 3173 // Now comment out any visibility specifiers. 3174 while (cursor < endBuf) { 3175 if (*cursor == '@
') { 3176 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3178 for (++cursor; cursor[0] == ' ' || cursor[0] == '\t
'; ++cursor) 3181 // FIXME: presence of @public, etc. inside comment results in 3182 // this transformation as well, which is still correct c-code. 3183 if (!strncmp(cursor, "public", strlen("public")) || 3184 !strncmp(cursor, "private", strlen("private")) || 3185 !strncmp(cursor, "package", strlen("package")) || 3186 !strncmp(cursor, "protected", strlen("protected"))) 3187 InsertText(atLoc, "// "); 3189 // FIXME: If there are cases where '<
' is used in ivar declaration part 3190 // of user code, then scan the ivar list and use needToScanForQualifiers 3191 // for type checking. 3192 else if (*cursor == '<
') { 3193 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3194 InsertText(atLoc, "/* "); 3195 cursor = strchr(cursor, '>
'); 3197 atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3198 InsertText(atLoc, " */"); 3199 } else if (*cursor == '^
') { // rewrite block specifier. 3200 SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf); 3201 ReplaceText(caretLoc, 1, "*"); 3205 // Don't forget to add a
';'!!
3209 Result +=
" {\n struct ";
3213 Result +=
"_IVARS;\n};\n";
3214 ReplaceText(LocStart, endBuf-startBuf, Result);
3217 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3218 llvm_unreachable(
"struct already synthesize- SynthesizeObjCInternalStruct");
3228 void RewriteObjC::RewriteImplementations() {
3229 int ClsDefCount = ClassImplementation.size();
3230 int CatDefCount = CategoryImplementation.size();
3233 for (
int i = 0; i < ClsDefCount; i++)
3234 RewriteImplementationDecl(ClassImplementation[i]);
3236 for (
int i = 0; i < CatDefCount; i++)
3237 RewriteImplementationDecl(CategoryImplementation[i]);
3240 void RewriteObjC::RewriteByRefString(std::string &ResultStr,
3241 const std::string &Name,
3243 assert(BlockByRefDeclNo.count(VD) &&
3244 "RewriteByRefString: ByRef decl missing");
3246 ResultStr +=
"struct ";
3247 ResultStr +=
"__Block_byref_" + Name +
3248 "_" + utostr(BlockByRefDeclNo[VD]) ;
3252 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3253 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3257 std::string RewriteObjC::SynthesizeBlockFunc(
BlockExpr *CE,
int i,
3262 std::string StructRef =
"struct " + Tag;
3264 funcName.str() +
"_" +
"block_func_" + utostr(i);
3268 if (isa<FunctionNoProtoType>(AFT)) {
3271 S +=
"(" + StructRef +
" *__cself)";
3273 S +=
"(" + StructRef +
" *__cself)";
3276 assert(FT &&
"SynthesizeBlockFunc: No function proto");
3279 S += StructRef +
" *__cself, ";
3280 std::string ParamStr;
3284 ParamStr = (*AI)->getNameAsString();
3286 (void)convertBlockPointerToFunctionPointer(QT);
3301 E = BlockByRefDecls.end(); I != E; ++I) {
3303 std::string Name = (*I)->getNameAsString();
3304 std::string TypeString;
3305 RewriteByRefString(TypeString, Name, (*I));
3307 Name = TypeString + Name;
3308 S += Name +
" = __cself->" + (*I)->getNameAsString() +
"; // bound by ref\n";
3312 E = BlockByCopyDecls.end(); I != E; ++I) {
3324 if (isTopLevelBlockPointerType((*I)->getType())) {
3325 RewriteBlockPointerTypeVariable(S, (*I));
3327 RewriteBlockPointerType(S, (*I)->getType());
3329 S +=
"__cself->" + (*I)->getNameAsString() +
"; // bound by copy\n";
3332 std::string Name = (*I)->getNameAsString();
3337 S += Name +
" = __cself->" +
3338 (*I)->getNameAsString() +
"; // bound by copy\n";
3341 std::string RewrittenStr = RewrittenBlockExprs[CE];
3342 const char *cstr = RewrittenStr.c_str();
3343 while (*cstr++ !=
'{') ;
3349 std::string RewriteObjC::SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
3352 std::string StructRef =
"struct " + Tag;
3353 std::string S =
"static void __";
3356 S +=
"_block_copy_" + utostr(i);
3357 S +=
"(" + StructRef;
3358 S +=
"*dst, " + StructRef;
3360 for (
ValueDecl *VD : ImportedBlockDecls) {
3361 S +=
"_Block_object_assign((void*)&dst->";
3363 S +=
", (void*)src->";
3365 if (BlockByRefDeclsPtrSet.count(VD))
3374 S +=
"\nstatic void __";
3376 S +=
"_block_dispose_" + utostr(i);
3377 S +=
"(" + StructRef;
3379 for (
ValueDecl *VD : ImportedBlockDecls) {
3380 S +=
"_Block_object_dispose((void*)src->";
3382 if (BlockByRefDeclsPtrSet.count(VD))
3393 std::string RewriteObjC::SynthesizeBlockImpl(
BlockExpr *CE, std::string Tag,
3395 std::string S =
"\nstruct " + Tag;
3396 std::string Constructor =
" " + Tag;
3398 S +=
" {\n struct __block_impl impl;\n";
3399 S +=
" struct " + Desc;
3402 Constructor +=
"(void *fp, ";
3403 Constructor +=
"struct " + Desc;
3404 Constructor +=
" *desc";
3406 if (BlockDeclRefs.size()) {
3409 E = BlockByCopyDecls.end(); I != E; ++I) {
3411 std::string FieldName = (*I)->getNameAsString();
3412 std::string ArgName =
"_" + FieldName;
3423 if (isTopLevelBlockPointerType((*I)->getType())) {
3424 S +=
"struct __block_impl *";
3425 Constructor +=
", void *" + ArgName;
3432 Constructor +=
", " + ArgName;
3434 S += FieldName +
";\n";
3438 E = BlockByRefDecls.end(); I != E; ++I) {
3440 std::string FieldName = (*I)->getNameAsString();
3441 std::string ArgName =
"_" + FieldName;
3443 std::string TypeString;
3444 RewriteByRefString(TypeString, FieldName, (*I));
3446 FieldName = TypeString + FieldName;
3447 ArgName = TypeString + ArgName;
3448 Constructor +=
", " + ArgName;
3450 S += FieldName +
"; // by ref\n";
3453 Constructor +=
", int flags=0)";
3455 bool firsTime =
true;
3457 E = BlockByCopyDecls.end(); I != E; ++I) {
3458 std::string Name = (*I)->getNameAsString();
3460 Constructor +=
" : ";
3464 Constructor +=
", ";
3465 if (isTopLevelBlockPointerType((*I)->getType()))
3466 Constructor += Name +
"((struct __block_impl *)_" + Name +
")";
3468 Constructor += Name +
"(_" + Name +
")";
3472 E = BlockByRefDecls.end(); I != E; ++I) {
3473 std::string Name = (*I)->getNameAsString();
3475 Constructor +=
" : ";
3479 Constructor +=
", ";
3480 Constructor += Name +
"(_" + Name +
"->__forwarding)";
3483 Constructor +=
" {\n";
3485 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3487 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3488 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3490 Constructor +=
" Desc = desc;\n";
3493 Constructor +=
", int flags=0) {\n";
3495 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3497 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3498 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3499 Constructor +=
" Desc = desc;\n";
3502 Constructor +=
"}\n";
3508 std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
3509 std::string ImplTag,
int i,
3512 std::string S =
"\nstatic struct " + DescTag;
3514 S +=
" {\n unsigned long reserved;\n";
3515 S +=
" unsigned long Block_size;\n";
3517 S +=
" void (*copy)(struct ";
3518 S += ImplTag; S +=
"*, struct ";
3519 S += ImplTag; S +=
"*);\n";
3521 S +=
" void (*dispose)(struct ";
3522 S += ImplTag; S +=
"*);\n";
3526 S += DescTag +
"_DATA = { 0, sizeof(struct ";
3529 S +=
", __" + FunName.str() +
"_block_copy_" + utostr(i);
3530 S +=
", __" + FunName.str() +
"_block_dispose_" + utostr(i);
3536 void RewriteObjC::SynthesizeBlockLiterals(
SourceLocation FunLocStart,
3537 StringRef FunName) {
3539 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3540 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3541 bool RewriteSC = (GlobalVarDecl &&
3546 std::string SC(
" void __");
3549 InsertText(FunLocStart, SC);
3553 for (
unsigned i = 0, count=0; i < Blocks.size(); i++) {
3554 CollectBlockDeclRefInfo(Blocks[i]);
3557 for (
int j = 0; j < InnerDeclRefsCount[i]; j++) {
3560 BlockDeclRefs.push_back(Exp);
3561 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
3562 BlockByCopyDeclsPtrSet.insert(VD);
3563 BlockByCopyDecls.push_back(VD);
3565 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
3566 BlockByRefDeclsPtrSet.insert(VD);
3567 BlockByRefDecls.push_back(VD);
3571 if (VD->
hasAttr<BlocksAttr>() ||
3574 ImportedBlockDecls.insert(VD);
3577 std::string ImplTag =
"__" + FunName.str() +
"_block_impl_" + utostr(i);
3578 std::string DescTag =
"__" + FunName.str() +
"_block_desc_" + utostr(i);
3580 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3582 InsertText(FunLocStart, CI);
3584 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3586 InsertText(FunLocStart, CF);
3588 if (ImportedBlockDecls.size()) {
3589 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3590 InsertText(FunLocStart, HF);
3592 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3593 ImportedBlockDecls.size() > 0);
3594 InsertText(FunLocStart, BD);
3596 BlockDeclRefs.clear();
3597 BlockByRefDecls.clear();
3598 BlockByRefDeclsPtrSet.clear();
3599 BlockByCopyDecls.clear();
3600 BlockByCopyDeclsPtrSet.clear();
3601 ImportedBlockDecls.clear();
3615 InsertText(FunLocStart, SC);
3619 InnerDeclRefsCount.clear();
3620 InnerDeclRefs.clear();
3621 RewrittenBlockExprs.clear();
3624 void RewriteObjC::InsertBlockLiteralsWithinFunction(
FunctionDecl *FD) {
3626 StringRef FuncName = FD->
getName();
3628 SynthesizeBlockLiterals(FunLocStart, FuncName);
3637 std::string::size_type loc = 0;
3638 while ((loc = Name.find(
':', loc)) != std::string::npos)
3639 Name.replace(loc, 1,
"_");
3642 void RewriteObjC::InsertBlockLiteralsWithinMethod(
ObjCMethodDecl *MD) {
3646 std::string FuncName;
3648 SynthesizeBlockLiterals(FunLocStart, FuncName);
3651 void RewriteObjC::GetBlockDeclRefExprs(
Stmt *S) {
3654 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
3655 GetBlockDeclRefExprs(CBE->getBody());
3657 GetBlockDeclRefExprs(SubStmt);
3661 if (DRE->refersToEnclosingVariableOrCapture() ||
3664 BlockDeclRefs.push_back(DRE);
3667 void RewriteObjC::GetInnerBlockDeclRefExprs(
Stmt *S,
3669 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
3672 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
3673 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
3674 GetInnerBlockDeclRefExprs(CBE->getBody(),
3679 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
3682 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3683 if (DRE->refersToEnclosingVariableOrCapture() ||
3685 if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
3686 InnerBlockDeclRefs.push_back(DRE);
3687 if (
VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
3688 if (Var->isFunctionOrMethodVarDecl())
3689 ImportedLocalExternalDecls.insert(Var);
3704 bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
3710 if (convertBlockPointerToFunctionPointer(t))
3711 HasBlockType =
true;
3712 ArgTypes.push_back(t);
3719 FuncType = getSimpleFunctionType(Res, ArgTypes);
3724 Stmt *RewriteObjC::SynthesizeBlockCall(
CallExpr *Exp,
const Expr *BlockExp) {
3728 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3730 }
else if (
const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3733 else if (
const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3734 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3736 else if (
const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3739 dyn_cast<ConditionalOperator>(BlockExp)) {
3740 Expr *LHSExp = CEXPR->getLHS();
3741 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3742 Expr *RHSExp = CEXPR->getRHS();
3743 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3744 Expr *CONDExp = CEXPR->getCond();
3751 }
else if (
const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3754 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
3757 assert(
false &&
"RewriteBlockClass: Bad type");
3759 assert(CPT &&
"RewriteBlockClass: Bad type");
3761 assert(FT &&
"RewriteBlockClass: Bad type");
3774 ArgTypes.push_back(PtrBlock);
3779 if (!convertBlockPointerToFunctionPointer(t))
3780 convertToUnqualifiedObjCType(t);
3781 ArgTypes.push_back(t);
3785 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->
getType(), ArgTypes);
3789 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
3791 const_cast<Expr*>(BlockExp));
3806 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
3812 BlkExprs.push_back(BlkCast);
3815 E = Exp->
arg_end(); I != E; ++I) {
3816 BlkExprs.push_back(*I);
3853 StringRef Name = VD->
getName();
3866 ReplaceStmt(DeclRefExp, PE);
3873 Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(
DeclRefExpr *DRE) {
3875 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3876 if (!ImportedLocalExternalDecls.count(Var))
3884 ReplaceStmt(DRE, PE);
3902 const Type* TypePtr = QT->
getAs<Type>();
3903 if (isa<TypeOfExprType>(TypePtr)) {
3904 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
3906 std::string TypeAsString =
"(";
3907 RewriteBlockPointerType(TypeAsString, QT);
3908 TypeAsString +=
")";
3909 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
3913 const char *argPtr = startBuf;
3915 while (*argPtr++ && (argPtr < endBuf)) {
3920 ReplaceText(LocStart, 1,
"*");
3926 void RewriteObjC::RewriteBlockPointerFunctionArgs(
FunctionDecl *FD) {
3928 unsigned parenCount = 0;
3932 const char *startArgList = strchr(startBuf,
'(');
3934 assert((*startArgList ==
'(') &&
"Rewriter fuzzy parser confused");
3939 assert((DeclLoc.
isValid()) &&
"Invalid DeclLoc");
3941 const char *argPtr = startArgList;
3943 while (*argPtr++ && parenCount) {
3948 ReplaceText(DeclLoc, 1,
"*");
3960 bool RewriteObjC::PointerTypeTakesAnyBlockArguments(
QualType QT) {
3967 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3972 if (isTopLevelBlockPointerType(I))
3978 bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(
QualType QT) {
3985 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3990 if (I->isObjCQualifiedIdType())
3992 if (I->isObjCObjectPointerType() &&
3993 I->getPointeeType()->isObjCQualifiedInterfaceType())
4001 void RewriteObjC::GetExtentOfArgList(
const char *Name,
const char *&LParen,
4002 const char *&RParen) {
4003 const char *argPtr = strchr(Name,
'(');
4004 assert((*argPtr ==
'(') &&
"Rewriter fuzzy parser confused");
4008 unsigned parenCount = 1;
4010 while (*argPtr && parenCount) {
4012 case '(': parenCount++;
break;
4013 case ')': parenCount--;
break;
4016 if (parenCount) argPtr++;
4018 assert((*argPtr ==
')') &&
"Rewriter fuzzy parser confused");
4022 void RewriteObjC::RewriteBlockPointerDecl(
NamedDecl *ND) {
4024 RewriteBlockPointerFunctionArgs(FD);
4030 if (
VarDecl *VD = dyn_cast<VarDecl>(ND))
4033 DeclT = TDD->getUnderlyingType();
4034 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4037 llvm_unreachable(
"RewriteBlockPointerDecl(): Decl type not yet handled");
4040 const char *endBuf = startBuf;
4042 while (*startBuf !=
'^' && *startBuf !=
';' && startBuf != MainFileStart)
4046 unsigned OrigLength=0;
4049 if (*startBuf ==
'^') {
4055 while (*startBuf !=
')') {
4063 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4064 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4069 const char *argListBegin, *argListEnd;
4070 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4071 while (argListBegin < argListEnd) {
4072 if (*argListBegin ==
'^')
4074 else if (*argListBegin ==
'<') {
4076 buf += *argListBegin++;
4078 while (*argListBegin !=
'>') {
4079 buf += *argListBegin++;
4082 buf += *argListBegin;
4086 buf += *argListBegin;
4093 ReplaceText(Start, OrigLength, buf);
4116 std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
4119 if (CopyDestroyCache.count(flag))
4121 CopyDestroyCache.insert(flag);
4122 S =
"static void __Block_byref_id_object_copy_";
4124 S +=
"(void *dst, void *src) {\n";
4130 unsigned VoidPtrSize =
4133 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->
getCharWidth();
4134 S +=
" _Block_object_assign((char*)dst + ";
4135 S += utostr(offset);
4136 S +=
", *(void * *) ((char*)src + ";
4137 S += utostr(offset);
4142 S +=
"static void __Block_byref_id_object_dispose_";
4144 S +=
"(void *src) {\n";
4145 S +=
" _Block_object_dispose(*(void * *) ((char*)src + ";
4146 S += utostr(offset);
4171 void RewriteObjC::RewriteByRefVar(
VarDecl *ND) {
4174 if (CurFunctionDeclToDeclareForBlock)
4175 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4188 std::string ByrefType;
4189 RewriteByRefString(ByrefType, Name, ND,
true);
4190 ByrefType +=
" {\n";
4191 ByrefType +=
" void *__isa;\n";
4192 RewriteByRefString(ByrefType, Name, ND);
4193 ByrefType +=
" *__forwarding;\n";
4194 ByrefType +=
" int __flags;\n";
4195 ByrefType +=
" int __size;\n";
4200 if (HasCopyAndDispose) {
4201 ByrefType +=
" void (*__Block_byref_id_object_copy)(void*, void*);\n";
4202 ByrefType +=
" void (*__Block_byref_id_object_dispose)(void*);\n";
4206 (void)convertBlockPointerToFunctionPointer(T);
4209 ByrefType +=
" " + Name +
";\n";
4210 ByrefType +=
"};\n";
4216 assert(CurMethodDef &&
"RewriteByRefVar - CurMethodDef is null");
4219 InsertText(FunLocStart, ByrefType);
4225 if (HasCopyAndDispose) {
4233 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4235 InsertText(FunLocStart, HF);
4241 bool hasInit = (ND->
getInit() !=
nullptr);
4243 if (HasCopyAndDispose)
4247 RewriteByRefString(ByrefType, Name, ND);
4248 std::string ForwardingCastType(
"(");
4249 ForwardingCastType += ByrefType +
" *)";
4251 ByrefType +=
" " + Name +
" = {(void*)";
4252 ByrefType += utostr(isa);
4253 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4254 ByrefType += utostr(flags);
4256 ByrefType +=
"sizeof(";
4257 RewriteByRefString(ByrefType, Name, ND);
4259 if (HasCopyAndDispose) {
4260 ByrefType +=
", __Block_byref_id_object_copy_";
4261 ByrefType += utostr(flag);
4262 ByrefType +=
", __Block_byref_id_object_dispose_";
4263 ByrefType += utostr(flag);
4265 ByrefType +=
"};\n";
4266 unsigned nameSize = Name.size();
4271 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4277 startLoc = ECE->getLParenLoc();
4282 ByrefType +=
" " + Name;
4283 ByrefType +=
" = {(void*)";
4284 ByrefType += utostr(isa);
4285 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4286 ByrefType += utostr(flags);
4288 ByrefType +=
"sizeof(";
4289 RewriteByRefString(ByrefType, Name, ND);
4291 if (HasCopyAndDispose) {
4292 ByrefType +=
"__Block_byref_id_object_copy_";
4293 ByrefType += utostr(flag);
4294 ByrefType +=
", __Block_byref_id_object_dispose_";
4295 ByrefType += utostr(flag);
4298 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4309 const char *semiBuf = strchr(startInitializerBuf,
';');
4310 assert((*semiBuf ==
';') &&
"RewriteByRefVar: can't find ';'");
4314 InsertText(semiLoc,
"}");
4318 void RewriteObjC::CollectBlockDeclRefInfo(
BlockExpr *Exp) {
4320 GetBlockDeclRefExprs(Exp->
getBody());
4321 if (BlockDeclRefs.size()) {
4323 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4324 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4325 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4326 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4327 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
4331 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4332 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4333 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4334 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4335 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
4339 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4340 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4341 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4342 BlockDeclRefs[i]->getType()->isBlockPointerType())
4343 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4358 Blocks.push_back(Exp);
4360 CollectBlockDeclRefInfo(Exp);
4363 int countOfInnerDecls = 0;
4364 if (!InnerBlockDeclRefs.empty()) {
4365 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
4368 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
4372 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4373 BlockDeclRefs.push_back(Exp);
4374 BlockByCopyDeclsPtrSet.insert(VD);
4375 BlockByCopyDecls.push_back(VD);
4377 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
4378 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4379 BlockDeclRefs.push_back(Exp);
4380 BlockByRefDeclsPtrSet.insert(VD);
4381 BlockByRefDecls.push_back(VD);
4385 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
4386 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4387 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4388 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
4389 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4391 InnerDeclRefsCount.push_back(countOfInnerDecls);
4393 std::string FuncName;
4397 else if (CurMethodDef)
4399 else if (GlobalVarDecl)
4402 std::string BlockNumber = utostr(Blocks.size()-1);
4404 std::string Tag =
"__" + FuncName +
"_block_impl_" + BlockNumber;
4405 std::string Func =
"__" + FuncName +
"_block_func_" + BlockNumber;
4415 FD = SynthBlockInitFunctionDecl(Tag);
4422 FD = SynthBlockInitFunctionDecl(Func);
4426 NoTypeInfoCStyleCastExpr(Context, Context->
VoidPtrTy, CK_BitCast, Arg);
4427 InitExprs.push_back(castExpr);
4430 std::string DescData =
"__" + FuncName +
"_block_desc_" + BlockNumber +
"_DATA";
4440 InitExprs.push_back(DescRefExpr);
4443 if (BlockDeclRefs.size()) {
4447 E = BlockByCopyDecls.end(); I != E; ++I) {
4448 if (isObjCType((*I)->getType())) {
4450 FD = SynthBlockInitFunctionDecl((*I)->getName());
4460 }
else if (isTopLevelBlockPointerType((*I)->getType())) {
4461 FD = SynthBlockInitFunctionDecl((*I)->getName());
4464 Exp = NoTypeInfoCStyleCastExpr(Context, Context->
VoidPtrTy, CK_BitCast,
4467 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);
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()->getBeginLoc(), 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) {
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));
5809 Expr *Replacement = IV;
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.
Represents a function declaration or definition.
The receiver is an object instance.
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
bool hasErrorOccurred() const
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
const FunctionProtoType * getFunctionType() const
getFunctionType - Return the underlying function type for this block.
QualType getObjCIdType() const
Represents the Objective-CC id type.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isBlockPointerType() const
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Selector getSelector() const
ObjCInterfaceDecl * getClassInterface()
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
ObjCIvarDecl * getPropertyIvarDecl() const
SourceLocation getRParenLoc() const
ObjCProtocolDecl * getProtocol() const
Stmt - This represents one statement.
const ObjCProtocolList & getReferencedProtocols() const
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
bool isRealFloatingType() const
Floating point categories.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Defines the SourceManager interface.
bool isRecordType() const
Decl - This represents one declaration (or definition), e.g.
bool isVariadic() const
Whether this function prototype is variadic.
SourceLocation getBeginLoc() const LLVM_READONLY
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)
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
const ObjCObjectPointerType * getAsObjCInterfacePointerType() const
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
protocol_iterator protocol_begin() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getLParenLoc() const
A container of type source information.
instmeth_iterator instmeth_end() const
Floating point control options.
constexpr XRayInstrMask Function
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, ConstexprSpecKind ConstexprKind=CSK_unspecified, Expr *TrailingRequiresClause=nullptr)
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
MutableArrayRef< ParmVarDecl * >::iterator param_iterator
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
Represents a variable declaration or definition.
CompoundLiteralExpr - [C99 6.5.2.5].
unsigned getNumParams() const
const T * getAs() const
Member-template getAs<specific type>'.
Extra information about a function prototype.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on...
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...
std::string getRewrittenText(CharSourceRange Range) const
getRewrittenText - Return the rewritten form of the text in the specified range.
QualType getObjCClassType() const
Represents the Objective-C Class type.
Describes how types, statements, expressions, and declarations should be printed. ...
classmeth_range class_methods() const
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represents a struct/union/class.
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
instprop_range instance_properties() const
One of these records is kept for each identifier that is lexed.
QualType IgnoreParens() const
Returns the specified type after dropping any outer-level parentheses.
Represents a class type in Objective C.
static RecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl=nullptr)
QualType getPointeeType() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
field_range fields() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a member of a struct/union/class.
ObjCMethodDecl * getSetterMethodDecl() const
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
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.
ObjCMethodDecl * getGetterMethodDecl() const
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
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)
SourceLocation getBeginLoc() const LLVM_READONLY
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.
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'.
An ordinary object is located at an address in memory.
Represents an ObjC class declaration.
Represents a linkage specification.
QualType getReturnType() const
SourceLocation getTypeSpecStartLoc() const
const Stmt * getBody() const
SourceLocation getAtStartLoc() const
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.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Represents a prototype with parameter type info, e.g.
CastKind
CastKind - The kind of operation required for a conversion.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat)
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
SourceLocation getLocation() const
SourceLocation getEndLoc() const LLVM_READONLY
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.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated)
This is the "fully general" constructor that allows representation of strings formed from multiple co...
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr *> Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
ivar_iterator ivar_end() const
ivar_iterator ivar_begin() const
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
const T * castAs() const
Member-template castAs<specific type>.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration is also the definition.
SourceLocation getEndLoc() const LLVM_READONLY
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].
SourceLocation getBeginLoc() const LLVM_READONLY
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
ObjCIvarDecl * lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared)
propimpl_range property_impls() const
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
SourceLocation getBeginLoc() const LLVM_READONLY
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
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getEndLoc() const
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Expr * getUnderlyingExpr() const
SourceLocation getEndLoc() const LLVM_READONLY
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()
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.
void setSourceMgr(SourceManager &SM, const LangOptions &LO)
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
param_type_range param_types() const
ivar_iterator ivar_begin() const
classmeth_iterator classmeth_end() const
Encodes a location in the source.
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
QualType getReturnType() const
ivar_iterator ivar_end() const
const Stmt * getCatchBody() const
Interfaces are the core concept in Objective-C for object oriented design.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
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.
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
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...
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
SourceLocation getBeginLoc() 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 llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
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 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.
SourceLocation getBeginLoc() const LLVM_READONLY
int printf(__constant const char *st,...) __attribute__((format(printf
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)
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...
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
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
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...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point...
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...
Iterator for iterating over Stmt * arrays that contain only T *.
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)
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.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type...
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 ...
SourceLocation getBeginLoc() const
Rewriter - This is the main interface to the rewrite buffers.
QualType getParamType(unsigned i) const
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\, const ASTContext *Context=nullptr) const
TranslationUnitDecl * getTranslationUnitDecl() const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ContinueStmt - This represents a continue.
SourceLocation getBeginLoc() const LLVM_READONLY
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]).
SourceLocation getBeginLoc() const LLVM_READONLY
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
StringRef getName() const
getName - Get the name of identifier for the class interface associated with this implementation as a...
The top declaration context.
A reference to a declared variable, function, enum, etc.
ObjCPropertyDecl * getPropertyDecl() const
SourceLocation getBeginLoc() 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
This represents a decl that may have a name.
SourceLocation getEndOfDefinitionLoc() const
SourceLocation getRightLoc() const
bool isFunctionPointerType() const
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
The receiver is a superclass.
void getSelectorLocs(SmallVectorImpl< SourceLocation > &SelLocs) const
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
FullSourceLoc getFullLoc(SourceLocation Loc) const
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
SourceLocation getBeginLoc() const LLVM_READONLY
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...