23 #include "clang/Config/config.h" 26 #include "llvm/ADT/DenseSet.h" 27 #include "llvm/ADT/SmallPtrSet.h" 28 #include "llvm/ADT/StringExtras.h" 29 #include "llvm/Support/MemoryBuffer.h" 30 #include "llvm/Support/raw_ostream.h" 33 #if CLANG_ENABLE_OBJC_REWRITER 35 using namespace clang;
55 BLOCK_NEEDS_FREE = (1 << 24),
58 BLOCK_IS_GC = (1 << 27),
60 BLOCK_HAS_DESCRIPTOR = (1 << 29)
62 static const int OBJC_ABI_VERSION = 7;
71 const char *MainFileStart, *MainFileEnd;
74 std::string InFileName;
75 std::unique_ptr<raw_ostream> OutFile;
80 unsigned RewriteFailedDiag;
82 unsigned NumObjCStringLiterals;
83 VarDecl *ConstantStringClassReference;
89 unsigned TryFinallyContainsReturnDiag;
112 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
113 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
114 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
115 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
119 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
132 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
134 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
135 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
136 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
137 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
139 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
144 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
148 bool SilenceRewriteMacroWarning;
149 bool objc_impl_method;
151 bool DisableReplaceStmt;
152 class DisableReplaceStmtScope {
158 : R(R), SavedValue(R.DisableReplaceStmt) {
159 R.DisableReplaceStmt =
true;
162 ~DisableReplaceStmtScope() {
163 R.DisableReplaceStmt = SavedValue;
174 if (!
Class->isThisDeclarationADefinition()) {
175 RewriteForwardClassDecl(D);
181 if (!Proto->isThisDeclarationADefinition()) {
182 RewriteForwardProtocolDecl(D);
187 HandleTopLevelSingleDecl(*I);
192 void HandleTopLevelSingleDecl(
Decl *D);
193 void HandleDeclInMainFile(
Decl *D);
194 RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
196 bool silenceMacroWarn);
200 void HandleTranslationUnit(
ASTContext &
C)
override;
202 void ReplaceStmt(
Stmt *Old,
Stmt *New) {
207 assert(Old !=
nullptr && New !=
nullptr &&
"Expected non-null Stmt's");
209 Stmt *ReplacingStmt = ReplacedNodes[Old];
213 if (DisableReplaceStmt)
225 llvm::raw_string_ostream S(SStr);
227 const std::string &Str = S.str();
231 ReplacedNodes[Old] = New;
234 if (SilenceRewriteMacroWarning)
241 bool InsertAfter =
true) {
243 if (!Rewrite.
InsertText(Loc, Str, InsertAfter) ||
244 SilenceRewriteMacroWarning)
253 if (!Rewrite.
ReplaceText(Start, OrigLength, Str) ||
254 SilenceRewriteMacroWarning)
262 void RewriteInclude();
266 const std::string &typedefString);
267 void RewriteImplementations();
272 void RewriteImplementationDecl(
Decl *Dcl);
275 void RewriteTypeIntoString(
QualType T, std::string &ResultStr,
277 void RewriteByRefString(std::string &ResultStr,
const std::string &Name,
286 void RewriteBlockPointerType(std::string& Str,
QualType Type);
287 void RewriteBlockPointerTypeVariable(std::string& Str,
ValueDecl *VD);
289 void RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl);
290 void RewriteTypeOfDecl(
VarDecl *VD);
291 void RewriteObjCQualifiedInterfaceTypes(
Expr *E);
294 Stmt *RewriteFunctionBodyOrGlobalInitializer(
Stmt *S);
302 void RewriteTryReturnStmts(
Stmt *S);
303 void RewriteSyncReturnStmts(
Stmt *S, std::string buf);
317 void RewriteBlockPointerDecl(
NamedDecl *VD);
318 void RewriteByRefVar(
VarDecl *VD);
326 void Initialize(
ASTContext &context)
override = 0;
329 virtual void RewriteMetaDataIntoBuffer(std::string &
Result) = 0;
345 virtual void RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
364 void SynthCountByEnumWithState(std::string &buf);
365 void SynthMsgSendFunctionDecl();
366 void SynthMsgSendSuperFunctionDecl();
367 void SynthMsgSendStretFunctionDecl();
368 void SynthMsgSendFpretFunctionDecl();
369 void SynthMsgSendSuperStretFunctionDecl();
370 void SynthGetClassFunctionDecl();
371 void SynthGetMetaClassFunctionDecl();
372 void SynthGetSuperClassFunctionDecl();
373 void SynthSelGetUidFunctionDecl();
374 void SynthSuperConstructorFunctionDecl();
376 std::string SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
int flag);
377 std::string SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
378 StringRef funcName, std::string Tag);
379 std::string SynthesizeBlockFunc(
BlockExpr *CE,
int i,
380 StringRef funcName, std::string Tag);
381 std::string SynthesizeBlockImpl(
BlockExpr *CE,
382 std::string Tag, std::string Desc);
383 std::string SynthesizeBlockDescriptor(std::string DescTag,
385 int i, StringRef funcName,
390 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
396 void WarnAboutReturnGotoStmts(
Stmt *S);
397 void HasReturnStmts(
Stmt *S,
bool &hasReturns);
399 void InsertBlockLiteralsWithinFunction(
FunctionDecl *FD);
402 bool IsDeclStmtInForeachHeader(
DeclStmt *DS);
403 void CollectBlockDeclRefInfo(
BlockExpr *Exp);
404 void GetBlockDeclRefExprs(
Stmt *S);
405 void GetInnerBlockDeclRefExprs(
Stmt *S,
407 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
411 bool isTopLevelBlockPointerType(
QualType T) {
412 return isa<BlockPointerType>(T);
418 bool convertBlockPointerToFunctionPointer(
QualType &T) {
419 if (isTopLevelBlockPointerType(T)) {
427 bool needToScanForQualifiers(
QualType T);
429 QualType getConstantStringStructType();
431 bool BufferContainsPPDirectives(
const char *startBuf,
const char *endBuf);
433 void convertToUnqualifiedObjCType(
QualType &T) {
461 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
462 PT->getPointeeType()->isObjCQualifiedIdType())
467 bool PointerTypeTakesAnyBlockArguments(
QualType QT);
468 bool PointerTypeTakesAnyObjCQualifiedType(
QualType QT);
469 void GetExtentOfArgList(
const char *Name,
const char *&LParen,
470 const char *&RParen);
472 void QuoteDoublequotes(std::string &From, std::string &To) {
473 for (
unsigned i = 0; i < From.length(); i++) {
483 bool variadic =
false) {
510 RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
512 bool silenceMacroWarn)
513 :
RewriteObjC(inFile,
std::move(OS), D, LOpts, silenceMacroWarn) {}
515 ~RewriteObjCFragileABI()
override {}
516 void Initialize(
ASTContext &context)
override;
519 template<
typename MethodIterator>
520 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
521 MethodIterator MethodEnd,
522 bool IsInstanceMethod,
527 StringRef prefix, StringRef ClassName,
528 std::string &
Result)
override;
529 void RewriteObjCProtocolListMetaData(
531 StringRef prefix, StringRef ClassName, std::string &
Result)
override;
533 std::string &
Result)
override;
534 void RewriteMetaDataIntoBuffer(std::string &
Result)
override;
536 std::string &
Result)
override;
540 std::string &
Result)
override;
545 void RewriteObjC::RewriteBlocksInFunctionProtoType(
QualType funcType,
548 = dyn_cast<FunctionProtoType>(funcType.
IgnoreParens())) {
549 for (
const auto &I : fproto->param_types())
550 if (isTopLevelBlockPointerType(I)) {
552 RewriteBlockPointerDecl(D);
560 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
565 std::string::size_type DotPos = Filename.rfind(
'.');
567 if (DotPos == std::string::npos) {
572 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
575 return Ext ==
"h" || Ext ==
"hh" || Ext ==
"H";
580 bool silenceMacroWarn)
581 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
582 SilenceRewriteMacroWarning(silenceMacroWarn) {
585 "rewriting sub-expression within a macro (may not be correct)");
588 "rewriter doesn't support user-specified control flow semantics " 589 "for @try/@finally (code may not execute properly)");
592 std::unique_ptr<ASTConsumer>
594 std::unique_ptr<raw_ostream> OS,
596 bool SilenceRewriteMacroWarning) {
597 return llvm::make_unique<RewriteObjCFragileABI>(
598 InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);
601 void RewriteObjC::InitializeCommon(
ASTContext &context) {
605 MsgSendFunctionDecl =
nullptr;
606 MsgSendSuperFunctionDecl =
nullptr;
607 MsgSendStretFunctionDecl =
nullptr;
608 MsgSendSuperStretFunctionDecl =
nullptr;
609 MsgSendFpretFunctionDecl =
nullptr;
610 GetClassFunctionDecl =
nullptr;
611 GetMetaClassFunctionDecl =
nullptr;
612 GetSuperClassFunctionDecl =
nullptr;
613 SelGetUidFunctionDecl =
nullptr;
614 CFStringFunctionDecl =
nullptr;
615 ConstantStringClassReference =
nullptr;
616 NSStringRecord =
nullptr;
617 CurMethodDef =
nullptr;
618 CurFunctionDef =
nullptr;
619 CurFunctionDeclToDeclareForBlock =
nullptr;
620 GlobalVarDecl =
nullptr;
621 SuperStructDecl =
nullptr;
622 ProtocolTypeDecl =
nullptr;
623 ConstantStringDecl =
nullptr;
625 SuperConstructorFunctionDecl =
nullptr;
626 NumObjCStringLiterals = 0;
627 PropParentMap =
nullptr;
628 CurrentBody =
nullptr;
629 DisableReplaceStmt =
false;
630 objc_impl_method =
false;
634 const llvm::MemoryBuffer *MainBuf = SM->
getBuffer(MainFileID);
635 MainFileStart = MainBuf->getBufferStart();
636 MainFileEnd = MainBuf->getBufferEnd();
645 void RewriteObjC::HandleTopLevelSingleDecl(
Decl *D) {
660 RewriteFunctionDecl(FD);
661 }
else if (
VarDecl *FVD = dyn_cast<VarDecl>(D)) {
663 if (FVD->getName() ==
"_NSConstantStringClassReference") {
664 ConstantStringClassReference = FVD;
668 if (
ID->isThisDeclarationADefinition())
669 RewriteInterfaceDecl(
ID);
671 RewriteCategoryDecl(CD);
673 if (PD->isThisDeclarationADefinition())
674 RewriteProtocolDecl(PD);
678 DIEnd = LSD->decls_end();
681 if (!IFace->isThisDeclarationADefinition()) {
685 if (isa<ObjCInterfaceDecl>(*DI) &&
686 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
687 StartLoc == (*DI)->getBeginLoc())
693 }
while (DI != DIEnd);
694 RewriteForwardClassDecl(DG);
700 if (!Proto->isThisDeclarationADefinition()) {
704 if (isa<ObjCProtocolDecl>(*DI) &&
705 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
706 StartLoc == (*DI)->getBeginLoc())
712 }
while (DI != DIEnd);
713 RewriteForwardProtocolDecl(DG);
718 HandleTopLevelSingleDecl(*DI);
724 return HandleDeclInMainFile(D);
731 void RewriteObjC::RewriteInclude() {
734 const char *MainBufStart = MainBuf.begin();
735 const char *MainBufEnd = MainBuf.end();
736 size_t ImportLen = strlen(
"import");
739 for (
const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
740 if (*BufPtr ==
'#') {
741 if (++BufPtr == MainBufEnd)
743 while (*BufPtr ==
' ' || *BufPtr ==
'\t')
744 if (++BufPtr == MainBufEnd)
746 if (!strncmp(BufPtr,
"import", ImportLen)) {
750 ReplaceText(ImportLoc, ImportLen,
"include");
762 S +=
"_IMPL *)self)->";
770 static bool objcGetPropertyDefined =
false;
771 static bool objcSetPropertyDefined =
false;
773 InsertText(startLoc,
"// ");
775 assert((*startBuf ==
'@') &&
"bogus @synthesize location");
776 const char *semiBuf = strchr(startBuf,
';');
777 assert((*semiBuf ==
';') &&
"@synthesize: can't find ';'");
796 if (GenGetProperty && !objcGetPropertyDefined) {
797 objcGetPropertyDefined =
true;
799 Getr =
"\nextern \"C\" __declspec(dllimport) " 800 "id objc_getProperty(id, SEL, long, bool);\n";
807 if (GenGetProperty) {
820 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
822 std::string ParamStr =
826 if (FT->isVariadic()) {
827 if (FT->getNumParams())
836 Getr +=
"return (_TYPE)";
837 Getr +=
"objc_getProperty(self, _cmd, ";
838 RewriteIvarOffsetComputation(OID, Getr);
844 InsertText(onePastSemiLoc, Getr);
854 if (GenSetProperty && !objcSetPropertyDefined) {
855 objcSetPropertyDefined =
true;
857 Setr =
"\nextern \"C\" __declspec(dllimport) " 858 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
866 if (GenSetProperty) {
867 Setr +=
"objc_setProperty (self, _cmd, ";
868 RewriteIvarOffsetComputation(OID, Setr);
886 InsertText(onePastSemiLoc, Setr);
890 std::string &typedefString) {
891 typedefString +=
"#ifndef _REWRITER_typedef_";
893 typedefString +=
"\n";
894 typedefString +=
"#define _REWRITER_typedef_";
896 typedefString +=
"\n";
897 typedefString +=
"typedef struct objc_object ";
899 typedefString +=
";\n#endif\n";
903 const std::string &typedefString) {
906 const char *semiPtr = strchr(startBuf,
';');
908 ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);
911 void RewriteObjC::RewriteForwardClassDecl(
DeclGroupRef D) {
912 std::string typedefString;
915 if (I == D.
begin()) {
919 typedefString +=
"// @class ";
921 typedefString +=
";\n";
926 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
930 std::string typedefString;
931 for (
unsigned i = 0; i < D.size(); i++) {
934 typedefString +=
"// @class ";
936 typedefString +=
";\n";
940 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
943 void RewriteObjC::RewriteMethodDeclaration(
ObjCMethodDecl *Method) {
953 InsertText(LocStart,
"#if 0\n");
954 ReplaceText(LocEnd, 1,
";\n#endif\n");
956 InsertText(LocStart,
"// ");
963 ReplaceText(Loc, 0,
"// ");
971 ReplaceText(LocStart, 0,
"// ");
976 RewriteMethodDeclaration(I);
978 RewriteMethodDeclaration(I);
982 strlen(
"@end"),
"/* @end */");
990 ReplaceText(LocStart, 0,
"// ");
993 RewriteMethodDeclaration(I);
995 RewriteMethodDeclaration(I);
1001 ReplaceText(LocEnd, strlen(
"@end"),
"/* @end */");
1006 for (
const char *p = startBuf; p < endBuf; p++) {
1007 if (*p ==
'@' && !strncmp(p+1,
"optional", strlen(
"optional"))) {
1009 ReplaceText(OptionalLoc, strlen(
"@optional"),
"/* @optional */");
1012 else if (*p ==
'@' && !strncmp(p+1,
"required", strlen(
"required"))) {
1014 ReplaceText(OptionalLoc, strlen(
"@required"),
"/* @required */");
1020 void RewriteObjC::RewriteForwardProtocolDecl(
DeclGroupRef D) {
1023 llvm_unreachable(
"Invalid SourceLocation");
1025 ReplaceText(LocStart, 0,
"// ");
1032 llvm_unreachable(
"Invalid SourceLocation");
1034 ReplaceText(LocStart, 0,
"// ");
1037 void RewriteObjC::RewriteTypeIntoString(
QualType T, std::string &ResultStr,
1062 std::string &ResultStr) {
1065 ResultStr +=
"\nstatic ";
1066 RewriteTypeIntoString(OMD->
getReturnType(), ResultStr, FPRetType);
1070 std::string NameStr;
1088 int len = selString.size();
1089 for (
int i = 0; i < len; i++)
1090 if (selString[i] ==
':')
1092 NameStr += selString;
1095 MethodInternalNames[OMD] = NameStr;
1096 ResultStr += NameStr;
1105 if (!LangOpts.MicrosoftExt) {
1106 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
1107 ResultStr +=
"struct ";
1117 ResultStr +=
" self, ";
1119 ResultStr +=
" _cmd";
1122 for (
const auto *PDecl : OMD->
parameters()) {
1124 if (PDecl->getType()->isObjCQualifiedIdType()) {
1131 (void)convertBlockPointerToFunctionPointer(QT);
1137 ResultStr +=
", ...";
1146 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
1147 if (i) ResultStr +=
", ";
1148 std::string ParamStr =
1150 ResultStr += ParamStr;
1152 if (FT->isVariadic()) {
1153 if (FT->getNumParams())
1164 void RewriteObjC::RewriteImplementationDecl(
Decl *OID) {
1168 InsertText(IMD ? IMD->
getBeginLoc() : CID->getBeginLoc(),
"// ");
1170 for (
auto *OMD : IMD ? IMD->
instance_methods() : CID->instance_methods()) {
1171 std::string ResultStr;
1178 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1181 for (
auto *OMD : IMD ? IMD->
class_methods() : CID->class_methods()) {
1182 std::string ResultStr;
1189 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1191 for (
auto *I : IMD ? IMD->
property_impls() : CID->property_impls())
1192 RewritePropertyImplDecl(I, IMD, CID);
1194 InsertText(IMD ? IMD->
getEndLoc() : CID->getEndLoc(),
"// ");
1198 std::string ResultStr;
1201 ResultStr =
"#ifndef _REWRITER_typedef_";
1204 ResultStr +=
"#define _REWRITER_typedef_";
1207 ResultStr +=
"typedef struct objc_object ";
1209 ResultStr +=
";\n#endif\n";
1213 RewriteObjCInternalStruct(ClassDecl, ResultStr);
1218 RewriteMethodDeclaration(I);
1220 RewriteMethodDeclaration(I);
1240 DisableReplaceStmtScope S(*
this);
1246 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1247 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1252 RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
1253 RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1305 Stmt *Replacement = SynthMessageExpr(NewMsg);
1306 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1322 DisableReplaceStmtScope S(*
this);
1327 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1328 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1381 Stmt *Replacement = SynthMessageExpr(NewMsg);
1382 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1395 void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1396 buf +=
"((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 1397 "id *, unsigned int))(void *)objc_msgSend)";
1399 buf +=
"((id)l_collection,\n\t\t";
1400 buf +=
"sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1402 buf +=
"&enumState, " 1403 "(id *)__rw_items, (unsigned int)16)";
1410 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1416 buf =
"goto __break_label_";
1417 buf += utostr(ObjCBcLabelNo.back());
1418 ReplaceText(startLoc, strlen(
"break"), buf);
1427 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1433 buf =
"goto __continue_label_";
1434 buf += utostr(ObjCBcLabelNo.back());
1435 ReplaceText(startLoc, strlen(
"continue"), buf);
1474 assert(!Stmts.empty() &&
"ObjCForCollectionStmt - Statement stack empty");
1475 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1476 "ObjCForCollectionStmt Statement stack mismatch");
1477 assert(!ObjCBcLabelNo.empty() &&
1478 "ObjCForCollectionStmt - Label No stack empty");
1482 StringRef elementName;
1483 std::string elementTypeAsString;
1488 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1489 QualType ElementType = cast<ValueDecl>(D)->getType();
1490 if (ElementType->isObjCQualifiedIdType() ||
1491 ElementType->isObjCQualifiedInterfaceType())
1493 elementTypeAsString =
"id";
1496 buf += elementTypeAsString;
1509 elementTypeAsString =
"id";
1515 buf +=
"struct __objcFastEnumerationState enumState = { 0 };\n\t";
1517 buf +=
"id __rw_items[16];\n\t";
1519 buf +=
"id l_collection = (id)";
1521 const char *startCollectionBuf = startBuf;
1522 startCollectionBuf += 3;
1523 startCollectionBuf = strchr(startCollectionBuf,
'(');
1524 startCollectionBuf++;
1526 while (*startCollectionBuf !=
' ' ||
1527 *(startCollectionBuf+1) !=
'i' || *(startCollectionBuf+2) !=
'n' ||
1528 (*(startCollectionBuf+3) !=
' ' &&
1529 *(startCollectionBuf+3) !=
'[' && *(startCollectionBuf+3) !=
'('))
1530 startCollectionBuf++;
1531 startCollectionBuf += 3;
1534 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1552 buf +=
"unsigned long limit =\n\t\t";
1553 SynthCountByEnumWithState(buf);
1563 buf +=
"if (limit) {\n\t";
1564 buf +=
"unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1565 buf +=
"do {\n\t\t";
1566 buf +=
"unsigned long counter = 0;\n\t\t";
1567 buf +=
"do {\n\t\t\t";
1568 buf +=
"if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1569 buf +=
"objc_enumerationMutation(l_collection);\n\t\t\t";
1572 buf += elementTypeAsString;
1573 buf +=
")enumState.itemsPtr[counter++];";
1575 ReplaceText(lparenLoc, 1, buf);
1589 buf +=
"__continue_label_";
1590 buf += utostr(ObjCBcLabelNo.back());
1593 buf +=
"} while (counter < limit);\n\t";
1594 buf +=
"} while (limit = ";
1595 SynthCountByEnumWithState(buf);
1599 buf += elementTypeAsString;
1601 buf +=
"__break_label_";
1602 buf += utostr(ObjCBcLabelNo.back());
1605 buf +=
"else\n\t\t";
1608 buf += elementTypeAsString;
1614 if (isa<CompoundStmt>(S->
getBody())) {
1616 InsertText(endBodyLoc, buf);
1626 const char *semiBuf = strchr(stmtBuf,
';');
1627 assert(semiBuf &&
"Can't find ';'");
1629 InsertText(endBodyLoc, buf);
1632 ObjCBcLabelNo.pop_back();
1647 assert((*startBuf ==
'@') &&
"bogus @synchronized location");
1650 buf =
"objc_sync_enter((id)";
1651 const char *lparenBuf = startBuf;
1652 while (*lparenBuf !=
'(') lparenBuf++;
1653 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1659 while (*endBuf !=
')') endBuf--;
1663 buf +=
"/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1664 buf +=
"int buf[18/*32-bit i386*/];\n";
1665 buf +=
"char *pointers[4];} _stack;\n";
1666 buf +=
"id volatile _rethrow = 0;\n";
1667 buf +=
"objc_exception_try_enter(&_stack);\n";
1668 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1669 ReplaceText(rparenLoc, 1, buf);
1673 assert((*startBuf ==
'}') &&
"bogus @synchronized block");
1675 buf =
"}\nelse {\n";
1676 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1678 buf +=
"{ /* implicit finally clause */\n";
1679 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1681 std::string syncBuf;
1682 syncBuf +=
" objc_sync_exit(";
1688 ? CK_BlockPointerToObjCPointerCast
1689 : CK_CPointerToObjCPointerCast;
1690 syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
1692 std::string syncExprBufS;
1693 llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1694 assert(syncExpr !=
nullptr &&
"Expected non-null Expr");
1696 syncBuf += syncExprBuf.str();
1700 buf +=
"\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1704 ReplaceText(lastCurlyLoc, 1, buf);
1706 bool hasReturns =
false;
1714 void RewriteObjC::WarnAboutReturnGotoStmts(
Stmt *S)
1719 WarnAboutReturnGotoStmts(SubStmt);
1721 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1723 TryFinallyContainsReturnDiag);
1727 void RewriteObjC::HasReturnStmts(
Stmt *S,
bool &hasReturns)
1732 HasReturnStmts(SubStmt, hasReturns);
1734 if (isa<ReturnStmt>(S))
1738 void RewriteObjC::RewriteTryReturnStmts(
Stmt *S) {
1742 RewriteTryReturnStmts(SubStmt);
1744 if (isa<ReturnStmt>(S)) {
1747 const char *semiBuf = strchr(startBuf,
';');
1748 assert((*semiBuf ==
';') &&
"RewriteTryReturnStmts: can't find ';'");
1752 buf =
"{ objc_exception_try_exit(&_stack); return";
1754 ReplaceText(startLoc, 6, buf);
1755 InsertText(onePastSemiLoc,
"}");
1759 void RewriteObjC::RewriteSyncReturnStmts(
Stmt *S, std::string syncExitBuf) {
1763 RewriteSyncReturnStmts(SubStmt, syncExitBuf);
1765 if (isa<ReturnStmt>(S)) {
1769 const char *semiBuf = strchr(startBuf,
';');
1770 assert((*semiBuf ==
';') &&
"RewriteSyncReturnStmts: can't find ';'");
1774 buf =
"{ objc_exception_try_exit(&_stack);";
1778 ReplaceText(startLoc, 6, buf);
1779 InsertText(onePastSemiLoc,
"}");
1788 assert((*startBuf ==
'@') &&
"bogus @try location");
1792 buf =
"/* @try scope begin */ { struct _objc_exception_data {\n";
1793 buf +=
"int buf[18/*32-bit i386*/];\n";
1794 buf +=
"char *pointers[4];} _stack;\n";
1795 buf +=
"id volatile _rethrow = 0;\n";
1796 buf +=
"objc_exception_try_enter(&_stack);\n";
1797 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1799 ReplaceText(startLoc, 4, buf);
1804 assert((*startBuf ==
'}') &&
"bogus @try block");
1809 buf =
" /* @catch begin */ else {\n";
1810 buf +=
" id _caught = objc_exception_extract(&_stack);\n";
1811 buf +=
" objc_exception_try_enter (&_stack);\n";
1812 buf +=
" if (_setjmp(_stack.buf))\n";
1813 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1814 buf +=
" else { /* @catch continue */";
1816 InsertText(startLoc, buf);
1818 buf =
"}\nelse {\n";
1819 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1821 ReplaceText(lastCurlyLoc, 1, buf);
1823 Stmt *lastCatchBody =
nullptr;
1835 assert((*startBuf ==
'@') &&
"bogus @catch location");
1837 const char *lParenLoc = strchr(startBuf,
'(');
1845 "bogus @catch paren location");
1846 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1848 buf +=
"1) { id _tmp = _caught;";
1849 Rewrite.
ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
1850 }
else if (catchDecl) {
1854 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1860 buf +=
"objc_exception_match((struct objc_class *)objc_getClass(\"";
1862 buf +=
"\"), (struct objc_object *)_caught)) { ";
1863 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1872 assert((*rParenBuf ==
')') &&
"bogus @catch paren location");
1873 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1877 ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
" = _caught;");
1879 llvm_unreachable(
"@catch rewrite bug");
1883 if (lastCatchBody) {
1886 "bogus @catch body location");
1890 buf =
"} /* last catch end */\n";
1892 buf +=
" _rethrow = _caught;\n";
1893 buf +=
" objc_exception_try_exit(&_stack);\n";
1894 buf +=
"} } /* @catch end */\n";
1897 InsertText(bodyLoc, buf);
1900 lastCurlyLoc = lastCatchBody->
getEndLoc();
1903 startLoc = finalStmt->getBeginLoc();
1905 assert((*startBuf ==
'@') &&
"bogus @finally start");
1907 ReplaceText(startLoc, 8,
"/* @finally */");
1909 Stmt *body = finalStmt->getFinallyBody();
1913 "bogus @finally body location");
1915 "bogus @finally body location");
1918 InsertText(startLoc,
" if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1920 InsertText(endLoc,
" if (_rethrow) objc_exception_throw(_rethrow);\n");
1928 buf =
"{ /* implicit finally clause */\n";
1929 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1930 buf +=
" if (_rethrow) objc_exception_throw(_rethrow);\n";
1932 ReplaceText(lastCurlyLoc, 1, buf);
1937 bool hasReturns =
false;
1944 InsertText(lastCurlyLoc,
" } /* @try scope end */\n");
1956 assert((*startBuf ==
'@') &&
"bogus @throw location");
1961 buf =
"objc_exception_throw(";
1963 buf =
"objc_exception_throw(_caught";
1966 const char *wBuf = strchr(startBuf,
'w');
1967 assert((*wBuf ==
'w') &&
"@throw: can't find 'w'");
1968 ReplaceText(startLoc, wBuf-startBuf+1, buf);
1970 const char *semiBuf = strchr(startBuf,
';');
1971 assert((*semiBuf ==
';') &&
"@throw: can't find ';'");
1973 ReplaceText(semiLoc, 1,
");");
1979 std::string StrEncoding;
1981 Expr *Replacement = getStringLiteral(StrEncoding);
1982 ReplaceStmt(Exp, Replacement);
1990 if (!SelGetUidFunctionDecl)
1991 SynthSelGetUidFunctionDecl();
1992 assert(SelGetUidFunctionDecl &&
"Can't find sel_registerName() decl");
1996 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
1998 ReplaceStmt(Exp, SelExp);
2004 RewriteObjC::SynthesizeCallToFunctionDecl(
FunctionDecl *FD,
2029 const char *&startRef,
const char *&endRef) {
2030 while (startBuf < endBuf) {
2031 if (*startBuf ==
'<')
2032 startRef = startBuf;
2033 if (*startBuf ==
'>') {
2034 if (startRef && *startRef ==
'<') {
2047 while (*argRef !=
')' && (*argRef !=
',' || angle > 0)) {
2050 else if (*argRef ==
'>')
2054 assert(angle == 0 &&
"scanToNextArgument - bad protocol type syntax");
2057 bool RewriteObjC::needToScanForQualifiers(
QualType T) {
2070 return needToScanForQualifiers(ElemTy);
2075 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Expr *E) {
2077 if (needToScanForQualifiers(Type)) {
2081 Loc = ECE->getLParenLoc();
2082 EndLoc = ECE->getRParenLoc();
2093 const char *startRef =
nullptr, *endRef =
nullptr;
2099 InsertText(LessLoc,
"/*");
2100 InsertText(GreaterLoc,
"*/");
2105 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl) {
2109 if (
VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2110 Loc = VD->getLocation();
2111 Type = VD->getType();
2113 else if (
FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2118 assert(funcType &&
"missing function type");
2124 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2131 if (needToScanForQualifiers(Type)) {
2135 const char *startBuf = endBuf;
2136 while (*startBuf !=
';' && *startBuf !=
'<' && startBuf != MainFileStart)
2138 const char *startRef =
nullptr, *endRef =
nullptr;
2144 InsertText(LessLoc,
"/*");
2145 InsertText(GreaterLoc,
"*/");
2152 const char *startFuncBuf = startBuf;
2157 const char *endBuf = startBuf;
2160 const char *startRef =
nullptr, *endRef =
nullptr;
2168 InsertText(LessLoc,
"/*");
2169 InsertText(GreaterLoc,
"*/");
2171 startBuf = ++endBuf;
2176 while (*startBuf && *startBuf !=
')' && *startBuf !=
',')
2183 void RewriteObjC::RewriteTypeOfDecl(
VarDecl *ND) {
2186 if (!isa<TypeOfExprType>(TypePtr))
2188 while (isa<TypeOfExprType>(TypePtr)) {
2189 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2200 TypeAsString +=
" " + Name +
" = ";
2204 startLoc = ECE->getLParenLoc();
2209 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2215 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2220 void RewriteObjC::SynthSelGetUidFunctionDecl() {
2229 SelGetUidIdent, getFuncType,
2233 void RewriteObjC::RewriteFunctionDecl(
FunctionDecl *FD) {
2236 FD->
getName() ==
"sel_registerName") {
2237 SelGetUidFunctionDecl = FD;
2240 RewriteObjCQualifiedInterfaceTypes(FD);
2243 void RewriteObjC::RewriteBlockPointerType(std::string& Str,
QualType Type) {
2245 const char *argPtr = TypeString.c_str();
2246 if (!strchr(argPtr,
'^')) {
2251 Str += (*argPtr ==
'^' ?
'*' : *argPtr);
2257 void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2261 const char *argPtr = TypeString.c_str();
2286 void RewriteObjC::RewriteBlockLiteralFunctionDecl(
FunctionDecl *FD) {
2292 QualType Type = proto->getReturnType();
2297 unsigned numArgs = proto->getNumParams();
2298 for (
unsigned i = 0; i < numArgs; i++) {
2299 QualType ArgType = proto->getParamType(i);
2300 RewriteBlockPointerType(FdStr, ArgType);
2305 InsertText(FunLocStart, FdStr);
2306 CurFunctionDeclToDeclareForBlock =
nullptr;
2310 void RewriteObjC::SynthSuperConstructorFunctionDecl() {
2311 if (SuperConstructorFunctionDecl)
2316 assert(!argT.
isNull() &&
"Can't find 'id' type");
2317 ArgTys.push_back(argT);
2318 ArgTys.push_back(argT);
2324 msgSendIdent, msgSendType,
2329 void RewriteObjC::SynthMsgSendFunctionDecl() {
2333 assert(!argT.
isNull() &&
"Can't find 'id' type");
2334 ArgTys.push_back(argT);
2336 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2337 ArgTys.push_back(argT);
2343 msgSendIdent, msgSendType,
2348 void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2355 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2356 ArgTys.push_back(argT);
2358 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2359 ArgTys.push_back(argT);
2365 msgSendIdent, msgSendType,
2370 void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2374 assert(!argT.
isNull() &&
"Can't find 'id' type");
2375 ArgTys.push_back(argT);
2377 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2378 ArgTys.push_back(argT);
2384 msgSendIdent, msgSendType,
2390 void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2392 &Context->
Idents.
get(
"objc_msgSendSuper_stret");
2398 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2399 ArgTys.push_back(argT);
2401 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2402 ArgTys.push_back(argT);
2409 msgSendType,
nullptr,
2414 void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2418 assert(!argT.
isNull() &&
"Can't find 'id' type");
2419 ArgTys.push_back(argT);
2421 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2422 ArgTys.push_back(argT);
2428 msgSendIdent, msgSendType,
2433 void RewriteObjC::SynthGetClassFunctionDecl() {
2442 getClassIdent, getClassType,
2447 void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2449 &Context->
Idents.
get(
"class_getSuperclass");
2458 getClassType,
nullptr,
2463 void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2472 getClassIdent, getClassType,
2477 assert(Exp !=
nullptr &&
"Expected non-null ObjCStringLiteral");
2478 QualType strType = getConstantStringStructType();
2480 std::string S =
"__NSConstantStringImpl_";
2482 std::string tmpName = InFileName;
2484 for (i=0; i < tmpName.length(); i++) {
2485 char c = tmpName.at(i);
2492 S += utostr(NumObjCStringLiterals++);
2494 Preamble +=
"static __NSConstantStringImpl " + S;
2495 Preamble +=
" __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2496 Preamble +=
"0x000007c8,";
2498 std::string prettyBufS;
2499 llvm::raw_string_ostream prettyBuf(prettyBufS);
2501 Preamble += prettyBuf.str();
2510 Expr *Unop =
new (Context)
2515 CK_CPointerToObjCPointerCast, Unop);
2516 ReplaceStmt(Exp, cast);
2522 QualType RewriteObjC::getSuperStructType() {
2523 if (!SuperStructDecl) {
2535 for (
unsigned i = 0; i < 2; ++i) {
2539 FieldTypes[i],
nullptr,
2550 QualType RewriteObjC::getConstantStringStructType() {
2551 if (!ConstantStringDecl) {
2554 &Context->
Idents.
get(
"__NSConstantStringImpl"));
2560 FieldTypes[1] = Context->
IntTy;
2564 FieldTypes[3] = Context->
LongTy;
2567 for (
unsigned i = 0; i < 4; ++i) {
2572 FieldTypes[i],
nullptr,
2591 new (Context)
DeclRefExpr(*Context, MsgSendStretFlavor,
false,
2598 QualType castType = getSimpleFunctionType(returnType, ArgTypes,
2602 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2617 if (!SelGetUidFunctionDecl)
2618 SynthSelGetUidFunctionDecl();
2619 if (!MsgSendFunctionDecl)
2620 SynthMsgSendFunctionDecl();
2621 if (!MsgSendSuperFunctionDecl)
2622 SynthMsgSendSuperFunctionDecl();
2623 if (!MsgSendStretFunctionDecl)
2624 SynthMsgSendStretFunctionDecl();
2625 if (!MsgSendSuperStretFunctionDecl)
2626 SynthMsgSendSuperStretFunctionDecl();
2627 if (!MsgSendFpretFunctionDecl)
2628 SynthMsgSendFpretFunctionDecl();
2629 if (!GetClassFunctionDecl)
2630 SynthGetClassFunctionDecl();
2631 if (!GetSuperClassFunctionDecl)
2632 SynthGetSuperClassFunctionDecl();
2633 if (!GetMetaClassFunctionDecl)
2634 SynthGetMetaClassFunctionDecl();
2641 QualType resultType = mDecl->getReturnType();
2643 MsgSendStretFlavor = MsgSendStretFunctionDecl;
2645 MsgSendFlavor = MsgSendFpretFunctionDecl;
2652 MsgSendFlavor = MsgSendSuperFunctionDecl;
2653 if (MsgSendStretFlavor)
2654 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2655 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2662 InitExprs.push_back(
2676 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2677 ClsExprs, StartLoc, EndLoc);
2679 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2683 ClsExprs.push_back(ArgExpr);
2684 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2688 InitExprs.push_back(
2689 NoTypeInfoCStyleCastExpr(Context,
2693 QualType superType = getSuperStructType();
2696 if (LangOpts.MicrosoftExt) {
2697 SynthSuperConstructorFunctionDecl();
2700 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2714 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2716 CK_BitCast, SuperRep);
2733 MsgExprs.push_back(SuperRep);
2742 ClsExprs.push_back(getStringLiteral(clsName->
getName()));
2743 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2745 MsgExprs.push_back(Cls);
2750 MsgSendFlavor = MsgSendSuperFunctionDecl;
2751 if (MsgSendStretFlavor)
2752 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2753 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2757 InitExprs.push_back(
2770 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2773 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2777 ClsExprs.push_back(ArgExpr);
2778 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2783 InitExprs.push_back(
2788 QualType superType = getSuperStructType();
2791 if (LangOpts.MicrosoftExt) {
2792 SynthSuperConstructorFunctionDecl();
2795 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2809 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2811 CK_BitCast, SuperRep);
2823 MsgExprs.push_back(SuperRep);
2832 recExpr = CE->getSubExpr();
2835 ? CK_BlockPointerToObjCPointerCast
2836 : CK_CPointerToObjCPointerCast;
2838 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
2840 MsgExprs.push_back(recExpr);
2848 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2849 SelExprs, StartLoc, EndLoc);
2850 MsgExprs.push_back(SelExp);
2853 for (
unsigned i = 0; i < Exp->
getNumArgs(); i++) {
2859 if (needToScanForQualifiers(type))
2862 (void)convertBlockPointerToFunctionPointer(type);
2867 CK = CK_IntegralToBoolean;
2870 CK = CK_BlockPointerToObjCPointerCast;
2872 CK = CK_CPointerToObjCPointerCast;
2880 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2883 else if (
CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2884 if (CE->getType()->isObjCQualifiedIdType()) {
2885 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2886 userExpr = CE->getSubExpr();
2889 CK = CK_IntegralToPointer;
2891 CK = CK_BlockPointerToObjCPointerCast;
2893 CK = CK_CPointerToObjCPointerCast;
2897 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
2901 MsgExprs.push_back(userExpr);
2913 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2914 ArgTypes.push_back(Context->
getPointerType(getSuperStructType()));
2925 (void)convertBlockPointerToFunctionPointer(t);
2926 ArgTypes.push_back(t);
2929 convertToUnqualifiedObjCType(returnType);
2930 (void)convertBlockPointerToFunctionPointer(returnType);
2945 cast = NoTypeInfoCStyleCastExpr(Context,
2953 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() :
true);
2955 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2964 Stmt *ReplacingStmt = CE;
2965 if (MsgSendStretFlavor) {
2971 CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
2972 msgSendType, returnType,
2989 llvm::APInt(IntSize, 8),
3006 return ReplacingStmt;
3010 Stmt *ReplacingStmt =
3014 ReplaceStmt(Exp, ReplacingStmt);
3017 return ReplacingStmt;
3021 QualType RewriteObjC::getProtocolType() {
3022 if (!ProtocolTypeDecl) {
3051 ReplaceStmt(Exp, castExpr);
3057 bool RewriteObjC::BufferContainsPPDirectives(
const char *startBuf,
3058 const char *endBuf) {
3059 while (startBuf < endBuf) {
3060 if (*startBuf ==
'#') {
3062 for (++startBuf; startBuf[0] ==
' ' || startBuf[0] ==
'\t'; ++startBuf)
3064 if (!strncmp(startBuf,
"if", strlen(
"if")) ||
3065 !strncmp(startBuf,
"ifdef", strlen(
"ifdef")) ||
3066 !strncmp(startBuf,
"ifndef", strlen(
"ifndef")) ||
3067 !strncmp(startBuf,
"define", strlen(
"define")) ||
3068 !strncmp(startBuf,
"undef", strlen(
"undef")) ||
3069 !strncmp(startBuf,
"else", strlen(
"else")) ||
3070 !strncmp(startBuf,
"elif", strlen(
"elif")) ||
3071 !strncmp(startBuf,
"endif", strlen(
"endif")) ||
3072 !strncmp(startBuf,
"pragma", strlen(
"pragma")) ||
3073 !strncmp(startBuf,
"include", strlen(
"include")) ||
3074 !strncmp(startBuf,
"import", strlen(
"import")) ||
3075 !strncmp(startBuf,
"include_next", strlen(
"include_next")))
3087 assert(CDecl &&
"Class missing in SynthesizeObjCInternalStruct");
3088 assert(CDecl->
getName() !=
"" &&
3089 "Name missing in SynthesizeObjCInternalStruct");
3091 if (ObjCSynthesizedStructs.count(CDecl))
3104 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3106 ReplaceText(LocStart, endBuf-startBuf, Result);
3112 Result +=
"\nstruct ";
3114 if (LangOpts.MicrosoftExt)
3118 const char *cursor = strchr(startBuf,
'{');
3119 assert((cursor && endBuf)
3120 &&
"SynthesizeObjCInternalStruct - malformed @interface");
3136 if (BufferContainsPPDirectives(startBuf, cursor)) {
3144 while (endHeader < cursor && *endHeader != '>
') endHeader++; 3147 // rewrite the original header 3148 ReplaceText(LocStart, endHeader-startBuf, Result); 3150 // rewrite the original header *without* disturbing the '{
' 3151 ReplaceText(LocStart, cursor-startBuf, Result); 3153 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 3154 Result = "\n struct "; 3155 Result += RCDecl->getNameAsString(); 3157 Result += RCDecl->getNameAsString(); 3158 Result += "_IVARS;\n"; 3160 // insert the super class structure definition. 3161 SourceLocation OnePastCurly = 3162 LocStart.getLocWithOffset(cursor-startBuf+1); 3163 InsertText(OnePastCurly, Result); 3165 cursor++; // past '{
' 3167 // Now comment out any visibility specifiers. 3168 while (cursor < endBuf) { 3169 if (*cursor == '@
') { 3170 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3172 for (++cursor; cursor[0] == ' ' || cursor[0] == '\t
'; ++cursor) 3175 // FIXME: presence of @public, etc. inside comment results in 3176 // this transformation as well, which is still correct c-code. 3177 if (!strncmp(cursor, "public", strlen("public")) || 3178 !strncmp(cursor, "private", strlen("private")) || 3179 !strncmp(cursor, "package", strlen("package")) || 3180 !strncmp(cursor, "protected", strlen("protected"))) 3181 InsertText(atLoc, "// "); 3183 // FIXME: If there are cases where '<
' is used in ivar declaration part 3184 // of user code, then scan the ivar list and use needToScanForQualifiers 3185 // for type checking. 3186 else if (*cursor == '<
') { 3187 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3188 InsertText(atLoc, "/* "); 3189 cursor = strchr(cursor, '>
'); 3191 atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3192 InsertText(atLoc, " */"); 3193 } else if (*cursor == '^
') { // rewrite block specifier. 3194 SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf); 3195 ReplaceText(caretLoc, 1, "*"); 3199 // Don't forget to add a
';'!!
3203 Result +=
" {\n struct ";
3207 Result +=
"_IVARS;\n};\n";
3208 ReplaceText(LocStart, endBuf-startBuf, Result);
3211 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3212 llvm_unreachable(
"struct already synthesize- SynthesizeObjCInternalStruct");
3222 void RewriteObjC::RewriteImplementations() {
3223 int ClsDefCount = ClassImplementation.size();
3224 int CatDefCount = CategoryImplementation.size();
3227 for (
int i = 0; i < ClsDefCount; i++)
3228 RewriteImplementationDecl(ClassImplementation[i]);
3230 for (
int i = 0; i < CatDefCount; i++)
3231 RewriteImplementationDecl(CategoryImplementation[i]);
3234 void RewriteObjC::RewriteByRefString(std::string &ResultStr,
3235 const std::string &Name,
3237 assert(BlockByRefDeclNo.count(VD) &&
3238 "RewriteByRefString: ByRef decl missing");
3240 ResultStr +=
"struct ";
3241 ResultStr +=
"__Block_byref_" + Name +
3242 "_" + utostr(BlockByRefDeclNo[VD]) ;
3246 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3247 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3251 std::string RewriteObjC::SynthesizeBlockFunc(
BlockExpr *CE,
int i,
3256 std::string StructRef =
"struct " + Tag;
3258 funcName.str() +
"_" +
"block_func_" + utostr(i);
3262 if (isa<FunctionNoProtoType>(AFT)) {
3265 S +=
"(" + StructRef +
" *__cself)";
3267 S +=
"(" + StructRef +
" *__cself)";
3270 assert(FT &&
"SynthesizeBlockFunc: No function proto");
3273 S += StructRef +
" *__cself, ";
3274 std::string ParamStr;
3278 ParamStr = (*AI)->getNameAsString();
3280 (void)convertBlockPointerToFunctionPointer(QT);
3295 E = BlockByRefDecls.end(); I != E; ++I) {
3297 std::string Name = (*I)->getNameAsString();
3298 std::string TypeString;
3299 RewriteByRefString(TypeString, Name, (*I));
3301 Name = TypeString + Name;
3302 S += Name +
" = __cself->" + (*I)->getNameAsString() +
"; // bound by ref\n";
3306 E = BlockByCopyDecls.end(); I != E; ++I) {
3318 if (isTopLevelBlockPointerType((*I)->getType())) {
3319 RewriteBlockPointerTypeVariable(S, (*I));
3321 RewriteBlockPointerType(S, (*I)->getType());
3323 S +=
"__cself->" + (*I)->getNameAsString() +
"; // bound by copy\n";
3326 std::string Name = (*I)->getNameAsString();
3331 S += Name +
" = __cself->" +
3332 (*I)->getNameAsString() +
"; // bound by copy\n";
3335 std::string RewrittenStr = RewrittenBlockExprs[CE];
3336 const char *cstr = RewrittenStr.c_str();
3337 while (*cstr++ !=
'{') ;
3343 std::string RewriteObjC::SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
3346 std::string StructRef =
"struct " + Tag;
3347 std::string S =
"static void __";
3350 S +=
"_block_copy_" + utostr(i);
3351 S +=
"(" + StructRef;
3352 S +=
"*dst, " + StructRef;
3354 for (
ValueDecl *VD : ImportedBlockDecls) {
3355 S +=
"_Block_object_assign((void*)&dst->";
3357 S +=
", (void*)src->";
3359 if (BlockByRefDeclsPtrSet.count(VD))
3368 S +=
"\nstatic void __";
3370 S +=
"_block_dispose_" + utostr(i);
3371 S +=
"(" + StructRef;
3373 for (
ValueDecl *VD : ImportedBlockDecls) {
3374 S +=
"_Block_object_dispose((void*)src->";
3376 if (BlockByRefDeclsPtrSet.count(VD))
3387 std::string RewriteObjC::SynthesizeBlockImpl(
BlockExpr *CE, std::string Tag,
3389 std::string S =
"\nstruct " + Tag;
3390 std::string Constructor =
" " + Tag;
3392 S +=
" {\n struct __block_impl impl;\n";
3393 S +=
" struct " + Desc;
3396 Constructor +=
"(void *fp, ";
3397 Constructor +=
"struct " + Desc;
3398 Constructor +=
" *desc";
3400 if (BlockDeclRefs.size()) {
3403 E = BlockByCopyDecls.end(); I != E; ++I) {
3405 std::string FieldName = (*I)->getNameAsString();
3406 std::string ArgName =
"_" + FieldName;
3417 if (isTopLevelBlockPointerType((*I)->getType())) {
3418 S +=
"struct __block_impl *";
3419 Constructor +=
", void *" + ArgName;
3426 Constructor +=
", " + ArgName;
3428 S += FieldName +
";\n";
3432 E = BlockByRefDecls.end(); I != E; ++I) {
3434 std::string FieldName = (*I)->getNameAsString();
3435 std::string ArgName =
"_" + FieldName;
3437 std::string TypeString;
3438 RewriteByRefString(TypeString, FieldName, (*I));
3440 FieldName = TypeString + FieldName;
3441 ArgName = TypeString + ArgName;
3442 Constructor +=
", " + ArgName;
3444 S += FieldName +
"; // by ref\n";
3447 Constructor +=
", int flags=0)";
3449 bool firsTime =
true;
3451 E = BlockByCopyDecls.end(); I != E; ++I) {
3452 std::string Name = (*I)->getNameAsString();
3454 Constructor +=
" : ";
3458 Constructor +=
", ";
3459 if (isTopLevelBlockPointerType((*I)->getType()))
3460 Constructor += Name +
"((struct __block_impl *)_" + Name +
")";
3462 Constructor += Name +
"(_" + Name +
")";
3466 E = BlockByRefDecls.end(); I != E; ++I) {
3467 std::string Name = (*I)->getNameAsString();
3469 Constructor +=
" : ";
3473 Constructor +=
", ";
3474 Constructor += Name +
"(_" + Name +
"->__forwarding)";
3477 Constructor +=
" {\n";
3479 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3481 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3482 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3484 Constructor +=
" Desc = desc;\n";
3487 Constructor +=
", int flags=0) {\n";
3489 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3491 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3492 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3493 Constructor +=
" Desc = desc;\n";
3496 Constructor +=
"}\n";
3502 std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
3503 std::string ImplTag,
int i,
3506 std::string S =
"\nstatic struct " + DescTag;
3508 S +=
" {\n unsigned long reserved;\n";
3509 S +=
" unsigned long Block_size;\n";
3511 S +=
" void (*copy)(struct ";
3512 S += ImplTag; S +=
"*, struct ";
3513 S += ImplTag; S +=
"*);\n";
3515 S +=
" void (*dispose)(struct ";
3516 S += ImplTag; S +=
"*);\n";
3520 S += DescTag +
"_DATA = { 0, sizeof(struct ";
3523 S +=
", __" + FunName.str() +
"_block_copy_" + utostr(i);
3524 S +=
", __" + FunName.str() +
"_block_dispose_" + utostr(i);
3530 void RewriteObjC::SynthesizeBlockLiterals(
SourceLocation FunLocStart,
3531 StringRef FunName) {
3533 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3534 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3535 bool RewriteSC = (GlobalVarDecl &&
3540 std::string SC(
" void __");
3543 InsertText(FunLocStart, SC);
3547 for (
unsigned i = 0, count=0; i < Blocks.size(); i++) {
3548 CollectBlockDeclRefInfo(Blocks[i]);
3551 for (
int j = 0; j < InnerDeclRefsCount[i]; j++) {
3554 BlockDeclRefs.push_back(Exp);
3555 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
3556 BlockByCopyDeclsPtrSet.insert(VD);
3557 BlockByCopyDecls.push_back(VD);
3559 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
3560 BlockByRefDeclsPtrSet.insert(VD);
3561 BlockByRefDecls.push_back(VD);
3565 if (VD->
hasAttr<BlocksAttr>() ||
3568 ImportedBlockDecls.insert(VD);
3571 std::string ImplTag =
"__" + FunName.str() +
"_block_impl_" + utostr(i);
3572 std::string DescTag =
"__" + FunName.str() +
"_block_desc_" + utostr(i);
3574 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3576 InsertText(FunLocStart, CI);
3578 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3580 InsertText(FunLocStart, CF);
3582 if (ImportedBlockDecls.size()) {
3583 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3584 InsertText(FunLocStart, HF);
3586 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3587 ImportedBlockDecls.size() > 0);
3588 InsertText(FunLocStart, BD);
3590 BlockDeclRefs.clear();
3591 BlockByRefDecls.clear();
3592 BlockByRefDeclsPtrSet.clear();
3593 BlockByCopyDecls.clear();
3594 BlockByCopyDeclsPtrSet.clear();
3595 ImportedBlockDecls.clear();
3609 InsertText(FunLocStart, SC);
3613 InnerDeclRefsCount.clear();
3614 InnerDeclRefs.clear();
3615 RewrittenBlockExprs.clear();
3618 void RewriteObjC::InsertBlockLiteralsWithinFunction(
FunctionDecl *FD) {
3620 StringRef FuncName = FD->
getName();
3622 SynthesizeBlockLiterals(FunLocStart, FuncName);
3631 std::string::size_type loc = 0;
3632 while ((loc = Name.find(
':', loc)) != std::string::npos)
3633 Name.replace(loc, 1,
"_");
3636 void RewriteObjC::InsertBlockLiteralsWithinMethod(
ObjCMethodDecl *MD) {
3640 std::string FuncName;
3642 SynthesizeBlockLiterals(FunLocStart, FuncName);
3645 void RewriteObjC::GetBlockDeclRefExprs(
Stmt *S) {
3648 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
3649 GetBlockDeclRefExprs(CBE->getBody());
3651 GetBlockDeclRefExprs(SubStmt);
3655 if (DRE->refersToEnclosingVariableOrCapture() ||
3658 BlockDeclRefs.push_back(DRE);
3661 void RewriteObjC::GetInnerBlockDeclRefExprs(
Stmt *S,
3663 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
3666 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
3667 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
3668 GetInnerBlockDeclRefExprs(CBE->getBody(),
3673 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
3676 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3677 if (DRE->refersToEnclosingVariableOrCapture() ||
3679 if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
3680 InnerBlockDeclRefs.push_back(DRE);
3681 if (
VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
3682 if (Var->isFunctionOrMethodVarDecl())
3683 ImportedLocalExternalDecls.insert(Var);
3698 bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
3704 if (convertBlockPointerToFunctionPointer(t))
3705 HasBlockType =
true;
3706 ArgTypes.push_back(t);
3713 FuncType = getSimpleFunctionType(Res, ArgTypes);
3718 Stmt *RewriteObjC::SynthesizeBlockCall(
CallExpr *Exp,
const Expr *BlockExp) {
3722 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3724 }
else if (
const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3727 else if (
const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3728 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3730 else if (
const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3733 dyn_cast<ConditionalOperator>(BlockExp)) {
3734 Expr *LHSExp = CEXPR->getLHS();
3735 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3736 Expr *RHSExp = CEXPR->getRHS();
3737 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3738 Expr *CONDExp = CEXPR->getCond();
3745 }
else if (
const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3748 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
3751 assert(
false &&
"RewriteBlockClass: Bad type");
3753 assert(CPT &&
"RewriteBlockClass: Bad type");
3755 assert(FT &&
"RewriteBlockClass: Bad type");
3768 ArgTypes.push_back(PtrBlock);
3773 if (!convertBlockPointerToFunctionPointer(t))
3774 convertToUnqualifiedObjCType(t);
3775 ArgTypes.push_back(t);
3779 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->
getType(), ArgTypes);
3783 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
3785 const_cast<Expr*>(BlockExp));
3801 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
3807 BlkExprs.push_back(BlkCast);
3810 E = Exp->
arg_end(); I != E; ++I) {
3811 BlkExprs.push_back(*I);
3848 StringRef Name = VD->
getName();
3862 ReplaceStmt(DeclRefExp, PE);
3869 Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(
DeclRefExpr *DRE) {
3871 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3872 if (!ImportedLocalExternalDecls.count(Var))
3880 ReplaceStmt(DRE, PE);
3898 const Type* TypePtr = QT->
getAs<Type>();
3899 if (isa<TypeOfExprType>(TypePtr)) {
3900 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
3902 std::string TypeAsString =
"(";
3903 RewriteBlockPointerType(TypeAsString, QT);
3904 TypeAsString +=
")";
3905 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
3909 const char *argPtr = startBuf;
3911 while (*argPtr++ && (argPtr < endBuf)) {
3916 ReplaceText(LocStart, 1,
"*");
3922 void RewriteObjC::RewriteBlockPointerFunctionArgs(
FunctionDecl *FD) {
3924 unsigned parenCount = 0;
3928 const char *startArgList = strchr(startBuf,
'(');
3930 assert((*startArgList ==
'(') &&
"Rewriter fuzzy parser confused");
3935 assert((DeclLoc.
isValid()) &&
"Invalid DeclLoc");
3937 const char *argPtr = startArgList;
3939 while (*argPtr++ && parenCount) {
3944 ReplaceText(DeclLoc, 1,
"*");
3956 bool RewriteObjC::PointerTypeTakesAnyBlockArguments(
QualType QT) {
3963 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3968 if (isTopLevelBlockPointerType(I))
3974 bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(
QualType QT) {
3981 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3986 if (I->isObjCQualifiedIdType())
3988 if (I->isObjCObjectPointerType() &&
3989 I->getPointeeType()->isObjCQualifiedInterfaceType())
3997 void RewriteObjC::GetExtentOfArgList(
const char *Name,
const char *&LParen,
3998 const char *&RParen) {
3999 const char *argPtr = strchr(Name,
'(');
4000 assert((*argPtr ==
'(') &&
"Rewriter fuzzy parser confused");
4004 unsigned parenCount = 1;
4006 while (*argPtr && parenCount) {
4008 case '(': parenCount++;
break;
4009 case ')': parenCount--;
break;
4012 if (parenCount) argPtr++;
4014 assert((*argPtr ==
')') &&
"Rewriter fuzzy parser confused");
4018 void RewriteObjC::RewriteBlockPointerDecl(
NamedDecl *ND) {
4020 RewriteBlockPointerFunctionArgs(FD);
4026 if (
VarDecl *VD = dyn_cast<VarDecl>(ND))
4029 DeclT = TDD->getUnderlyingType();
4030 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4033 llvm_unreachable(
"RewriteBlockPointerDecl(): Decl type not yet handled");
4036 const char *endBuf = startBuf;
4038 while (*startBuf !=
'^' && *startBuf !=
';' && startBuf != MainFileStart)
4042 unsigned OrigLength=0;
4045 if (*startBuf ==
'^') {
4051 while (*startBuf !=
')') {
4059 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4060 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4065 const char *argListBegin, *argListEnd;
4066 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4067 while (argListBegin < argListEnd) {
4068 if (*argListBegin ==
'^')
4070 else if (*argListBegin ==
'<') {
4072 buf += *argListBegin++;
4074 while (*argListBegin !=
'>') {
4075 buf += *argListBegin++;
4078 buf += *argListBegin;
4082 buf += *argListBegin;
4089 ReplaceText(Start, OrigLength, buf);
4112 std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
4115 if (CopyDestroyCache.count(flag))
4117 CopyDestroyCache.insert(flag);
4118 S =
"static void __Block_byref_id_object_copy_";
4120 S +=
"(void *dst, void *src) {\n";
4126 unsigned VoidPtrSize =
4129 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->
getCharWidth();
4130 S +=
" _Block_object_assign((char*)dst + ";
4131 S += utostr(offset);
4132 S +=
", *(void * *) ((char*)src + ";
4133 S += utostr(offset);
4138 S +=
"static void __Block_byref_id_object_dispose_";
4140 S +=
"(void *src) {\n";
4141 S +=
" _Block_object_dispose(*(void * *) ((char*)src + ";
4142 S += utostr(offset);
4167 void RewriteObjC::RewriteByRefVar(
VarDecl *ND) {
4170 if (CurFunctionDeclToDeclareForBlock)
4171 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4184 std::string ByrefType;
4185 RewriteByRefString(ByrefType, Name, ND,
true);
4186 ByrefType +=
" {\n";
4187 ByrefType +=
" void *__isa;\n";
4188 RewriteByRefString(ByrefType, Name, ND);
4189 ByrefType +=
" *__forwarding;\n";
4190 ByrefType +=
" int __flags;\n";
4191 ByrefType +=
" int __size;\n";
4196 if (HasCopyAndDispose) {
4197 ByrefType +=
" void (*__Block_byref_id_object_copy)(void*, void*);\n";
4198 ByrefType +=
" void (*__Block_byref_id_object_dispose)(void*);\n";
4202 (void)convertBlockPointerToFunctionPointer(T);
4205 ByrefType +=
" " + Name +
";\n";
4206 ByrefType +=
"};\n";
4212 assert(CurMethodDef &&
"RewriteByRefVar - CurMethodDef is null");
4215 InsertText(FunLocStart, ByrefType);
4221 if (HasCopyAndDispose) {
4229 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4231 InsertText(FunLocStart, HF);
4237 bool hasInit = (ND->
getInit() !=
nullptr);
4239 if (HasCopyAndDispose)
4243 RewriteByRefString(ByrefType, Name, ND);
4244 std::string ForwardingCastType(
"(");
4245 ForwardingCastType += ByrefType +
" *)";
4247 ByrefType +=
" " + Name +
" = {(void*)";
4248 ByrefType += utostr(isa);
4249 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4250 ByrefType += utostr(flags);
4252 ByrefType +=
"sizeof(";
4253 RewriteByRefString(ByrefType, Name, ND);
4255 if (HasCopyAndDispose) {
4256 ByrefType +=
", __Block_byref_id_object_copy_";
4257 ByrefType += utostr(flag);
4258 ByrefType +=
", __Block_byref_id_object_dispose_";
4259 ByrefType += utostr(flag);
4261 ByrefType +=
"};\n";
4262 unsigned nameSize = Name.size();
4267 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4273 startLoc = ECE->getLParenLoc();
4278 ByrefType +=
" " + Name;
4279 ByrefType +=
" = {(void*)";
4280 ByrefType += utostr(isa);
4281 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4282 ByrefType += utostr(flags);
4284 ByrefType +=
"sizeof(";
4285 RewriteByRefString(ByrefType, Name, ND);
4287 if (HasCopyAndDispose) {
4288 ByrefType +=
"__Block_byref_id_object_copy_";
4289 ByrefType += utostr(flag);
4290 ByrefType +=
", __Block_byref_id_object_dispose_";
4291 ByrefType += utostr(flag);
4294 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4305 const char *semiBuf = strchr(startInitializerBuf,
';');
4306 assert((*semiBuf ==
';') &&
"RewriteByRefVar: can't find ';'");
4310 InsertText(semiLoc,
"}");
4314 void RewriteObjC::CollectBlockDeclRefInfo(
BlockExpr *Exp) {
4316 GetBlockDeclRefExprs(Exp->
getBody());
4317 if (BlockDeclRefs.size()) {
4319 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4320 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4321 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4322 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4323 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
4327 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4328 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4329 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4330 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4331 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
4335 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4336 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4337 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4338 BlockDeclRefs[i]->getType()->isBlockPointerType())
4339 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4343 FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
4354 Blocks.push_back(Exp);
4356 CollectBlockDeclRefInfo(Exp);
4359 int countOfInnerDecls = 0;
4360 if (!InnerBlockDeclRefs.empty()) {
4361 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
4364 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
4368 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4369 BlockDeclRefs.push_back(Exp);
4370 BlockByCopyDeclsPtrSet.insert(VD);
4371 BlockByCopyDecls.push_back(VD);
4373 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
4374 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4375 BlockDeclRefs.push_back(Exp);
4376 BlockByRefDeclsPtrSet.insert(VD);
4377 BlockByRefDecls.push_back(VD);
4381 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
4382 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4383 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4384 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
4385 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4387 InnerDeclRefsCount.push_back(countOfInnerDecls);
4389 std::string FuncName;
4393 else if (CurMethodDef)
4395 else if (GlobalVarDecl)
4398 std::string BlockNumber = utostr(Blocks.size()-1);
4400 std::string Tag =
"__" + FuncName +
"_block_impl_" + BlockNumber;
4401 std::string Func =
"__" + FuncName +
"_block_func_" + BlockNumber;
4411 FD = SynthBlockInitFunctionDecl(Tag);
4418 FD = SynthBlockInitFunctionDecl(Func);
4422 NoTypeInfoCStyleCastExpr(Context, Context->
VoidPtrTy, CK_BitCast, Arg);
4423 InitExprs.push_back(castExpr);
4426 std::string DescData =
"__" + FuncName +
"_block_desc_" + BlockNumber +
"_DATA";
4436 InitExprs.push_back(DescRefExpr);
4439 if (BlockDeclRefs.size()) {
4443 E = BlockByCopyDecls.end(); I != E; ++I) {
4444 if (isObjCType((*I)->getType())) {
4446 FD = SynthBlockInitFunctionDecl((*I)->getName());
4456 }
else if (isTopLevelBlockPointerType((*I)->getType())) {
4457 FD = SynthBlockInitFunctionDecl((*I)->getName());
4460 Exp = NoTypeInfoCStyleCastExpr(Context, Context->
VoidPtrTy, CK_BitCast,
4463 FD = SynthBlockInitFunctionDecl((*I)->getName());
4474 InitExprs.push_back(Exp);
4478 E = BlockByRefDecls.end(); I != E; ++I) {
4481 std::string RecName;
4482 RewriteByRefString(RecName, Name, ND,
true);
4484 +
sizeof(
"struct"));
4488 assert(RD &&
"SynthBlockInitExpr(): Can't find RecordDecl");
4491 FD = SynthBlockInitFunctionDecl((*I)->getName());
4494 bool isNestedCapturedVar =
false;
4496 for (
const auto &CI : block->
captures()) {
4497 const VarDecl *variable = CI.getVariable();
4498 if (variable == ND && CI.isNested()) {
4499 assert (CI.isByRef() &&
4500 "SynthBlockInitExpr - captured block variable is not byref");
4501 isNestedCapturedVar =
true;
4507 if (!isNestedCapturedVar)
4511 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
4512 InitExprs.push_back(Exp);
4515 if (ImportedBlockDecls.size()) {
4522 InitExprs.push_back(FlagExp);
4529 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
4531 BlockDeclRefs.clear();
4532 BlockByRefDecls.clear();
4533 BlockByRefDeclsPtrSet.clear();
4534 BlockByCopyDecls.clear();
4535 BlockByCopyDeclsPtrSet.clear();
4536 ImportedBlockDecls.clear();
4540 bool RewriteObjC::IsDeclStmtInForeachHeader(
DeclStmt *DS) {
4542 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4543 return CS->getElement() == DS;
4551 Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(
Stmt *S) {
4552 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4553 isa<DoStmt>(S) || isa<ForStmt>(S))
4555 else if (isa<ObjCForCollectionStmt>(S)) {
4557 ObjCBcLabelNo.push_back(++BcLabelCount);
4564 return RewritePropertyOrImplicitSetter(PseudoOp);
4566 return RewritePropertyOrImplicitGetter(PseudoOp);
4568 }
else if (
ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4569 return RewriteObjCIvarRefExpr(IvarRefExpr);
4577 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4579 childStmt = newStmt;
4583 if (
BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
4585 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
4586 InnerContexts.insert(BE->getBlockDecl());
4587 ImportedLocalExternalDecls.clear();
4588 GetInnerBlockDeclRefExprs(BE->getBody(),
4589 InnerBlockDeclRefs, InnerContexts);
4591 Stmt *SaveCurrentBody = CurrentBody;
4592 CurrentBody = BE->getBody();
4593 PropParentMap =
nullptr;
4599 bool saveDisableReplaceStmt = DisableReplaceStmt;
4600 DisableReplaceStmt =
false;
4601 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4602 DisableReplaceStmt = saveDisableReplaceStmt;
4603 CurrentBody = SaveCurrentBody;
4604 PropParentMap =
nullptr;
4605 ImportedLocalExternalDecls.clear();
4608 RewrittenBlockExprs[BE] = Str;
4610 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4613 ReplaceStmt(S, blockTranscribed);
4614 return blockTranscribed;
4618 return RewriteAtEncode(AtEncode);
4621 return RewriteAtSelector(AtSelector);
4624 return RewriteObjCStringLiteral(AtString);
4635 std::string messString;
4636 messString +=
"// ";
4637 messString.append(startBuf, endBuf-startBuf+1);
4646 return RewriteMessageExpr(MessExpr);
4650 return RewriteObjCTryStmt(StmtTry);
4653 return RewriteObjCSynchronizedStmt(StmtTry);
4656 return RewriteObjCThrowStmt(StmtThrow);
4659 return RewriteObjCProtocolExpr(ProtocolExp);
4662 dyn_cast<ObjCForCollectionStmt>(S))
4663 return RewriteObjCForCollectionStmt(StmtForCollection,
4666 dyn_cast<BreakStmt>(S))
4667 return RewriteBreakStmt(StmtBreakStmt);
4669 dyn_cast<ContinueStmt>(S))
4670 return RewriteContinueStmt(StmtContinueStmt);
4674 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4684 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4685 RewriteObjCQualifiedInterfaceTypes(*DS->
decl_begin());
4688 for (
auto *SD : DS->
decls()) {
4689 if (
ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4690 if (isTopLevelBlockPointerType(ND->
getType()))
4691 RewriteBlockPointerDecl(ND);
4693 CheckFunctionPointerDecl(ND->
getType(), ND);
4694 if (
VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4695 if (VD->
hasAttr<BlocksAttr>()) {
4696 static unsigned uniqueByrefDeclCount = 0;
4697 assert(!BlockByRefDeclNo.count(ND) &&
4698 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4699 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4700 RewriteByRefVar(VD);
4703 RewriteTypeOfDecl(VD);
4707 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4708 RewriteBlockPointerDecl(TD);
4709 else if (TD->getUnderlyingType()->isFunctionPointerType())
4710 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4716 RewriteObjCQualifiedInterfaceTypes(CE);
4718 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4719 isa<DoStmt>(S) || isa<ForStmt>(S)) {
4720 assert(!Stmts.empty() &&
"Statement stack is empty");
4721 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
4722 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
4723 &&
"Statement stack mismatch");
4727 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4729 if (VD->
hasAttr<BlocksAttr>())
4730 return RewriteBlockDeclRefExpr(DRE);
4732 return RewriteLocalVariableExternalStorage(DRE);
4735 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
4738 ReplaceStmt(S, BlockCall);
4743 RewriteCastExpr(CE);
4752 llvm::raw_string_ostream Buf(SStr);
4754 const std::string &Str = Buf.str();
4756 printf(
"CAST = %s\n", &Str[0]);
4757 InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
4766 void RewriteObjC::RewriteRecordBody(
RecordDecl *RD) {
4767 for (
auto *FD : RD->
fields()) {
4768 if (isTopLevelBlockPointerType(FD->
getType()))
4769 RewriteBlockPointerDecl(FD);
4772 RewriteObjCQualifiedInterfaceTypes(FD);
4778 void RewriteObjC::HandleDeclInMainFile(
Decl *D) {
4788 RewriteBlocksInFunctionProtoType(FD->
getType(), FD);
4795 CurFunctionDef = FD;
4796 CurFunctionDeclToDeclareForBlock = FD;
4799 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4801 CurrentBody =
nullptr;
4802 if (PropParentMap) {
4803 delete PropParentMap;
4804 PropParentMap =
nullptr;
4808 InsertBlockLiteralsWithinFunction(FD);
4809 CurFunctionDef =
nullptr;
4810 CurFunctionDeclToDeclareForBlock =
nullptr;
4814 case Decl::ObjCMethod: {
4820 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4822 CurrentBody =
nullptr;
4823 if (PropParentMap) {
4824 delete PropParentMap;
4825 PropParentMap =
nullptr;
4827 InsertBlockLiteralsWithinMethod(MD);
4828 CurMethodDef =
nullptr;
4832 case Decl::ObjCImplementation: {
4834 ClassImplementation.push_back(CI);
4837 case Decl::ObjCCategoryImpl: {
4839 CategoryImplementation.push_back(CI);
4843 VarDecl *VD = cast<VarDecl>(D);
4844 RewriteObjCQualifiedInterfaceTypes(VD);
4845 if (isTopLevelBlockPointerType(VD->
getType()))
4846 RewriteBlockPointerDecl(VD);
4848 CheckFunctionPointerDecl(VD->
getType(), VD);
4851 RewriteCastExpr(CE);
4857 RewriteRecordBody(RD);
4862 RewriteFunctionBodyOrGlobalInitializer(VD->
getInit());
4863 CurrentBody =
nullptr;
4864 if (PropParentMap) {
4865 delete PropParentMap;
4866 PropParentMap =
nullptr;
4869 GlobalVarDecl =
nullptr;
4873 RewriteCastExpr(CE);
4878 case Decl::TypeAlias:
4879 case Decl::Typedef: {
4881 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4882 RewriteBlockPointerDecl(TD);
4883 else if (TD->getUnderlyingType()->isFunctionPointerType())
4884 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4888 case Decl::CXXRecord:
4889 case Decl::Record: {
4892 RewriteRecordBody(RD);
4901 void RewriteObjC::HandleTranslationUnit(
ASTContext &
C) {
4910 RewriteObjCProtocolMetaData(ProtDecl,
"",
"", Preamble);
4913 if (ClassImplementation.size() || CategoryImplementation.size())
4914 RewriteImplementations();
4921 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
4923 llvm::errs() <<
"No changes\n";
4926 if (ClassImplementation.size() || CategoryImplementation.size() ||
4927 ProtocolExprDecls.size()) {
4929 std::string ResultStr;
4930 RewriteMetaDataIntoBuffer(ResultStr);
4932 *OutFile << ResultStr;
4937 void RewriteObjCFragileABI::Initialize(
ASTContext &context) {
4938 InitializeCommon(context);
4943 Preamble =
"#pragma once\n";
4944 Preamble +=
"struct objc_selector; struct objc_class;\n";
4945 Preamble +=
"struct __rw_objc_super { struct objc_object *object; ";
4946 Preamble +=
"struct objc_object *superClass; ";
4947 if (LangOpts.MicrosoftExt) {
4949 Preamble +=
"__rw_objc_super(struct objc_object *o, struct objc_object *s) " 4951 Preamble +=
"object(o), superClass(s) {} ";
4954 Preamble +=
"#ifndef _REWRITER_typedef_Protocol\n";
4955 Preamble +=
"typedef struct objc_object Protocol;\n";
4956 Preamble +=
"#define _REWRITER_typedef_Protocol\n";
4957 Preamble +=
"#endif\n";
4958 if (LangOpts.MicrosoftExt) {
4959 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
4960 Preamble +=
"#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
4962 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern\n";
4963 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
4964 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4965 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
4966 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4967 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
4968 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4969 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
4970 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4971 Preamble +=
"__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
4972 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4973 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
4974 Preamble +=
"(const char *);\n";
4975 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
4976 Preamble +=
"(struct objc_class *);\n";
4977 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
4978 Preamble +=
"(const char *);\n";
4979 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
4980 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
4981 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
4982 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
4983 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_exception_match";
4984 Preamble +=
"(struct objc_class *, struct objc_object *);\n";
4986 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
4987 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
4988 Preamble +=
"__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
4989 Preamble +=
"#ifndef __FASTENUMERATIONSTATE\n";
4990 Preamble +=
"struct __objcFastEnumerationState {\n\t";
4991 Preamble +=
"unsigned long state;\n\t";
4992 Preamble +=
"void **itemsPtr;\n\t";
4993 Preamble +=
"unsigned long *mutationsPtr;\n\t";
4994 Preamble +=
"unsigned long extra[5];\n};\n";
4995 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
4996 Preamble +=
"#define __FASTENUMERATIONSTATE\n";
4997 Preamble +=
"#endif\n";
4998 Preamble +=
"#ifndef __NSCONSTANTSTRINGIMPL\n";
4999 Preamble +=
"struct __NSConstantStringImpl {\n";
5000 Preamble +=
" int *isa;\n";
5001 Preamble +=
" int flags;\n";
5002 Preamble +=
" char *str;\n";
5003 Preamble +=
" long length;\n";
5005 Preamble +=
"#ifdef CF_EXPORT_CONSTANT_STRING\n";
5006 Preamble +=
"extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5007 Preamble +=
"#else\n";
5008 Preamble +=
"__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5009 Preamble +=
"#endif\n";
5010 Preamble +=
"#define __NSCONSTANTSTRINGIMPL\n";
5011 Preamble +=
"#endif\n";
5013 Preamble +=
"#ifndef BLOCK_IMPL\n";
5014 Preamble +=
"#define BLOCK_IMPL\n";
5015 Preamble +=
"struct __block_impl {\n";
5016 Preamble +=
" void *isa;\n";
5017 Preamble +=
" int Flags;\n";
5018 Preamble +=
" int Reserved;\n";
5019 Preamble +=
" void *FuncPtr;\n";
5021 Preamble +=
"// Runtime copy/destroy helper functions (from Block_private.h)\n";
5022 Preamble +=
"#ifdef __OBJC_EXPORT_BLOCKS\n";
5023 Preamble +=
"extern \"C\" __declspec(dllexport) " 5024 "void _Block_object_assign(void *, const void *, const int);\n";
5025 Preamble +=
"extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5026 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5027 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5028 Preamble +=
"#else\n";
5029 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5030 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5031 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5032 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5033 Preamble +=
"#endif\n";
5034 Preamble +=
"#endif\n";
5035 if (LangOpts.MicrosoftExt) {
5036 Preamble +=
"#undef __OBJC_RW_DLLIMPORT\n";
5037 Preamble +=
"#undef __OBJC_RW_STATICIMPORT\n";
5038 Preamble +=
"#ifndef KEEP_ATTRIBUTES\n";
5039 Preamble +=
"#define __attribute__(X)\n";
5040 Preamble +=
"#endif\n";
5041 Preamble +=
"#define __weak\n";
5044 Preamble +=
"#define __block\n";
5045 Preamble +=
"#define __weak\n";
5049 Preamble +=
"\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5054 void RewriteObjCFragileABI::RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
5055 std::string &Result) {
5061 Result +=
"__OFFSETOFIVAR__(struct ";
5063 if (LangOpts.MicrosoftExt)
5072 void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
5074 StringRef ClassName, std::string &Result) {
5075 static bool objc_protocol_methods =
false;
5084 Result +=
"\nstruct _protocol_methods {\n";
5085 Result +=
"\tstruct objc_selector *_cmd;\n";
5086 Result +=
"\tchar *method_types;\n";
5089 objc_protocol_methods =
true;
5106 Result +=
"\nstatic struct {\n";
5107 Result +=
"\tint protocol_method_count;\n";
5108 Result +=
"\tstruct _protocol_methods protocol_methods[";
5109 Result += utostr(NumMethods);
5110 Result +=
"];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
5112 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 5113 "{\n\t" + utostr(NumMethods) +
"\n";
5120 Result +=
"\t ,{{(struct objc_selector *)\"";
5122 Result +=
"\t ,{(struct objc_selector *)\"";
5123 Result += (*I)->getSelector().getAsString();
5126 Result += MethodTypeString;
5129 Result +=
"\t }\n};\n";
5135 if (NumMethods > 0) {
5141 Result +=
"\nstatic struct {\n";
5142 Result +=
"\tint protocol_method_count;\n";
5143 Result +=
"\tstruct _protocol_methods protocol_methods[";
5144 Result += utostr(NumMethods);
5145 Result +=
"];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
5147 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5149 Result += utostr(NumMethods);
5157 Result +=
"\t ,{{(struct objc_selector *)\"";
5159 Result +=
"\t ,{(struct objc_selector *)\"";
5160 Result += (*I)->getSelector().getAsString();
5163 Result += MethodTypeString;
5166 Result +=
"\t }\n};\n";
5179 static bool objc_protocol =
false;
5180 if (!objc_protocol) {
5181 Result +=
"\nstruct _objc_protocol {\n";
5182 Result +=
"\tstruct _objc_protocol_extension *isa;\n";
5183 Result +=
"\tchar *protocol_name;\n";
5184 Result +=
"\tstruct _objc_protocol **protocol_list;\n";
5185 Result +=
"\tstruct _objc_protocol_method_list *instance_methods;\n";
5186 Result +=
"\tstruct _objc_protocol_method_list *class_methods;\n";
5189 objc_protocol =
true;
5192 Result +=
"\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
5194 Result +=
" __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 5197 Result +=
"\", 0, ";
5199 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
5206 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
5216 llvm_unreachable(
"protocol already synthesized");
5219 void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
5221 StringRef prefix, StringRef ClassName,
5222 std::string &Result) {
5223 if (Protocols.
empty())
return;
5225 for (
unsigned i = 0; i != Protocols.
size(); i++)
5226 RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
5235 Result +=
"\nstatic struct {\n";
5236 Result +=
"\tstruct _objc_protocol_list *next;\n";
5237 Result +=
"\tint protocol_count;\n";
5238 Result +=
"\tstruct _objc_protocol *class_protocols[";
5239 Result += utostr(Protocols.
size());
5240 Result +=
"];\n} _OBJC_";
5242 Result +=
"_PROTOCOLS_";
5243 Result += ClassName;
5244 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5246 Result += utostr(Protocols.
size());
5249 Result +=
"\t,{&_OBJC_PROTOCOL_";
5250 Result += Protocols[0]->getNameAsString();
5253 for (
unsigned i = 1; i != Protocols.
size(); i++) {
5254 Result +=
"\t ,&_OBJC_PROTOCOL_";
5255 Result += Protocols[i]->getNameAsString();
5258 Result +=
"\t }\n};\n";
5262 std::string &Result) {
5269 RewriteObjCInternalStruct(CDecl, Result);
5277 static bool objc_ivar =
false;
5285 Result +=
"\nstruct _objc_ivar {\n";
5286 Result +=
"\tchar *ivar_name;\n";
5287 Result +=
"\tchar *ivar_type;\n";
5288 Result +=
"\tint ivar_offset;\n";
5299 Result +=
"\nstatic struct {\n";
5300 Result +=
"\tint ivar_count;\n";
5301 Result +=
"\tstruct _objc_ivar ivar_list[";
5302 Result += utostr(NumIvars);
5303 Result +=
"];\n} _OBJC_INSTANCE_VARIABLES_";
5305 Result +=
" __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 5307 Result += utostr(NumIvars);
5313 for (
auto *IV : IDecl->
ivars())
5314 IVars.push_back(IV);
5321 Result +=
"\t,{{\"";
5322 Result += IVI->getNameAsString();
5324 std::string TmpString, StrEncoding;
5326 QuoteDoublequotes(TmpString, StrEncoding);
5327 Result += StrEncoding;
5329 RewriteIvarOffsetComputation(*IVI, Result);
5331 for (++IVI; IVI != IVE; ++IVI) {
5332 Result +=
"\t ,{\"";
5333 Result += IVI->getNameAsString();
5335 std::string TmpString, StrEncoding;
5337 QuoteDoublequotes(TmpString, StrEncoding);
5338 Result += StrEncoding;
5340 RewriteIvarOffsetComputation(*IVI, Result);
5344 Result +=
"\t }\n};\n";
5355 if (!Prop->getPropertyIvarDecl())
5361 if (!Getter->isDefined())
5362 InstanceMethods.push_back(Getter);
5366 if (!Setter->isDefined())
5367 InstanceMethods.push_back(Setter);
5369 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5396 static bool objc_class =
false;
5398 Result +=
"\nstruct _objc_class {\n";
5399 Result +=
"\tstruct _objc_class *isa;\n";
5400 Result +=
"\tconst char *super_class_name;\n";
5401 Result +=
"\tchar *name;\n";
5402 Result +=
"\tlong version;\n";
5403 Result +=
"\tlong info;\n";
5404 Result +=
"\tlong instance_size;\n";
5405 Result +=
"\tstruct _objc_ivar_list *ivars;\n";
5406 Result +=
"\tstruct _objc_method_list *methods;\n";
5407 Result +=
"\tstruct objc_cache *cache;\n";
5408 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5409 Result +=
"\tconst char *ivar_layout;\n";
5410 Result +=
"\tstruct _objc_class_ext *ext;\n";
5418 while (SuperClass) {
5419 RootClass = SuperClass;
5424 Result +=
"\nstatic struct _objc_class _OBJC_METACLASS_";
5426 Result +=
" __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 5427 "{\n\t(struct _objc_class *)\"";
5439 Result +=
", 0, \"";
5445 Result +=
", 0,2, sizeof(struct _objc_class), 0";
5447 Result +=
"\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
5454 Result +=
"\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
5459 Result +=
"\t,0,0,0,0\n";
5463 Result +=
"\nstatic struct _objc_class _OBJC_CLASS_";
5465 Result +=
" __attribute__ ((used, section (\"__OBJC, __class\")))= " 5466 "{\n\t&_OBJC_METACLASS_";
5476 Result +=
", 0, \"";
5482 if (!ObjCSynthesizedStructs.count(CDecl))
5486 Result +=
",sizeof(struct ";
5488 if (LangOpts.MicrosoftExt)
5493 Result +=
", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
5500 Result +=
", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
5502 Result +=
", 0\n\t";
5507 Result +=
", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
5509 Result +=
", 0,0\n";
5512 Result +=
",0,0,0\n";
5516 void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
5517 int ClsDefCount = ClassImplementation.size();
5518 int CatDefCount = CategoryImplementation.size();
5521 for (
int i = 0; i < ClsDefCount; i++)
5522 RewriteObjCClassMetaData(ClassImplementation[i], Result);
5525 for (
int i = 0; i < CatDefCount; i++)
5526 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
5540 Result +=
"\nstruct _objc_symtab {\n";
5541 Result +=
"\tlong sel_ref_cnt;\n";
5542 Result +=
"\tSEL *refs;\n";
5543 Result +=
"\tshort cls_def_cnt;\n";
5544 Result +=
"\tshort cat_def_cnt;\n";
5545 Result +=
"\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+
"];\n";
5548 Result +=
"static struct _objc_symtab " 5549 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
5550 Result +=
"\t0, 0, " + utostr(ClsDefCount)
5551 +
", " + utostr(CatDefCount) +
"\n";
5552 for (
int i = 0; i < ClsDefCount; i++) {
5553 Result +=
"\t,&_OBJC_CLASS_";
5554 Result += ClassImplementation[i]->getNameAsString();
5558 for (
int i = 0; i < CatDefCount; i++) {
5559 Result +=
"\t,&_OBJC_CATEGORY_";
5560 Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
5562 Result += CategoryImplementation[i]->getNameAsString();
5579 Result +=
"\nstruct _objc_module {\n";
5580 Result +=
"\tlong version;\n";
5581 Result +=
"\tlong size;\n";
5582 Result +=
"\tconst char *name;\n";
5583 Result +=
"\tstruct _objc_symtab *symtab;\n";
5585 Result +=
"static struct _objc_module " 5586 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
5587 Result +=
"\t" + utostr(OBJC_ABI_VERSION) +
5588 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
5591 if (LangOpts.MicrosoftExt) {
5592 if (ProtocolExprDecls.size()) {
5593 Result +=
"#pragma section(\".objc_protocol$B\",long,read,write)\n";
5594 Result +=
"#pragma data_seg(push, \".objc_protocol$B\")\n";
5596 Result +=
"static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
5597 Result += ProtDecl->getNameAsString();
5598 Result +=
" = &_OBJC_PROTOCOL_";
5599 Result += ProtDecl->getNameAsString();
5602 Result +=
"#pragma data_seg(pop)\n\n";
5604 Result +=
"#pragma section(\".objc_module_info$B\",long,read,write)\n";
5605 Result +=
"#pragma data_seg(push, \".objc_module_info$B\")\n";
5606 Result +=
"static struct _objc_module *_POINTER_OBJC_MODULES = ";
5607 Result +=
"&_OBJC_MODULES;\n";
5608 Result +=
"#pragma data_seg(pop)\n\n";
5615 std::string &Result) {
5622 FullCategoryName +=
'_';
5633 if (!Prop->getPropertyIvarDecl())
5639 InstanceMethods.push_back(Getter);
5643 InstanceMethods.push_back(Setter);
5645 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5646 true,
"CATEGORY_", FullCategoryName,
Result);
5650 false,
"CATEGORY_", FullCategoryName,
Result);
5656 FullCategoryName,
Result);
5670 static bool objc_category =
false;
5671 if (!objc_category) {
5672 Result +=
"\nstruct _objc_category {\n";
5673 Result +=
"\tchar *category_name;\n";
5674 Result +=
"\tchar *class_name;\n";
5675 Result +=
"\tstruct _objc_method_list *instance_methods;\n";
5676 Result +=
"\tstruct _objc_method_list *class_methods;\n";
5677 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5678 Result +=
"\tunsigned int size;\n";
5679 Result +=
"\tstruct _objc_property_list *instance_properties;\n";
5681 objc_category =
true;
5683 Result +=
"\nstatic struct _objc_category _OBJC_CATEGORY_";
5684 Result += FullCategoryName;
5685 Result +=
" __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
5687 Result +=
"\"\n\t, \"";
5692 Result +=
"\t, (struct _objc_method_list *)" 5693 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
5694 Result += FullCategoryName;
5698 Result +=
"\t, 0\n";
5700 Result +=
"\t, (struct _objc_method_list *)" 5701 "&_OBJC_CATEGORY_CLASS_METHODS_";
5702 Result += FullCategoryName;
5706 Result +=
"\t, 0\n";
5709 Result +=
"\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
5710 Result += FullCategoryName;
5714 Result +=
"\t, 0\n";
5715 Result +=
"\t, sizeof(struct _objc_category), 0\n};\n";
5720 template<
typename MethodIterator>
5721 void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5722 MethodIterator MethodEnd,
5723 bool IsInstanceMethod,
5725 StringRef ClassName,
5726 std::string &Result) {
5727 if (MethodBegin == MethodEnd)
return;
5729 if (!objc_impl_method) {
5736 Result +=
"\nstruct _objc_method {\n";
5737 Result +=
"\tSEL _cmd;\n";
5738 Result +=
"\tchar *method_types;\n";
5739 Result +=
"\tvoid *_imp;\n";
5742 objc_impl_method =
true;
5753 unsigned NumMethods =
std::distance(MethodBegin, MethodEnd);
5754 Result +=
"\nstatic struct {\n";
5755 Result +=
"\tstruct _objc_method_list *next_method;\n";
5756 Result +=
"\tint method_count;\n";
5757 Result +=
"\tstruct _objc_method method_list[";
5758 Result += utostr(NumMethods);
5759 Result +=
"];\n} _OBJC_";
5761 Result += IsInstanceMethod ?
"INSTANCE" :
"CLASS";
5762 Result +=
"_METHODS_";
5763 Result += ClassName;
5764 Result +=
" __attribute__ ((used, section (\"__OBJC, __";
5765 Result += IsInstanceMethod ?
"inst" :
"cls";
5766 Result +=
"_meth\")))= ";
5767 Result +=
"{\n\t0, " + utostr(NumMethods) +
"\n";
5769 Result +=
"\t,{{(SEL)\"";
5770 Result += (*MethodBegin)->getSelector().getAsString();
5771 std::string MethodTypeString =
5774 Result += MethodTypeString;
5775 Result +=
"\", (void *)";
5776 Result += MethodInternalNames[*MethodBegin];
5778 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
5779 Result +=
"\t ,{(SEL)\"";
5780 Result += (*MethodBegin)->getSelector().getAsString();
5781 std::string MethodTypeString =
5784 Result += MethodTypeString;
5785 Result +=
"\", (void *)";
5786 Result += MethodInternalNames[*MethodBegin];
5789 Result +=
"\t }\n};\n";
5798 DisableReplaceStmtScope S(*
this);
5799 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
5805 Expr *Replacement = IV;
5810 assert(iFaceDecl &&
"RewriteObjCIvarRefExpr - iFaceDecl is null");
5815 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5824 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5844 assert(!IV->
isFreeIvar() &&
"Cannot have a free standing ivar outside a method");
5855 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5858 std::string RecName = clsDeclared->getIdentifier()->getName();
5864 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5879 ReplaceStmtWithRange(IV, Replacement, OldRange);
5883 #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
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.
ObjCMethodDecl - Represents an instance or class method declaration.
SourceLocation getLeftLoc() const
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
Expr * IgnoreImplicit() LLVM_READONLY
IgnoreImplicit - Skip past any implicit AST nodes which might surround this expression.
QualType getObjCClassType() const
Represents the Objective-C Class type.
Describes how types, statements, expressions, and declarations should be printed. ...
classmeth_range class_methods() const
std::string getRewrittenText(SourceRange Range) const
getRewrittenText - Return the rewritten form of the text in the specified range.
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.
static ObjCMessageExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, ArrayRef< SourceLocation > SelLocs, ObjCMethodDecl *Method, ArrayRef< Expr *> Args, SourceLocation RBracLoc, bool isImplicit)
Create a message send to super.
instmeth_range instance_methods() const
StringLiteral * getString()
std::string getNameAsString() const
Get the name of the class associated with this interface.
SourceLocation getRParenLoc() const
ObjCMethodDecl * getSetterMethodDecl() const
protocol_iterator protocol_end() const
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isObjCQualifiedClassType() const
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
Selector getSelector() const
Represents Objective-C's @catch statement.
Describes an C or C++ initializer list.
bool isBitField() const
Determines whether this field is a bitfield.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
const Expr * getThrowExpr() const
filtered_decl_iterator< ObjCMethodDecl, &ObjCMethodDecl::isInstanceMethod > instmeth_iterator
unsigned ivar_size() const
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
PropertyAttributeKind getPropertyAttributes() const
Concrete class used by the front-end to report problems and issues.
Represents a typeof (or typeof) expression (a GCC extension).
const clang::PrintingPolicy & getPrintingPolicy() const
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
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified=false, bool hasWrittenPrototype=true, bool isConstexprSpecified=false)
SourceLocation getAtStartLoc() const
Iterator for iterating over Stmt * arrays that contain only Expr *.
std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended=false) const
Emit the encoded type for the method declaration Decl into S.
const ObjCAtCatchStmt * getCatchStmt(unsigned I) const
Retrieve a @catch statement.
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
ConditionalOperator - The ?: ternary operator.
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.
Pepresents a block literal declaration, which is like an unnamed FunctionDecl.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
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
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type...
const Stmt * getTryBody() const
Retrieve the @try body.
QualType getEncodedType() const
bool isa(CodeGen::Address addr)
An expression that sends a message to the given Objective-C object or class.
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl...
SourceLocation getEnd() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
bool isInstanceMethod() const
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
int getRangeSize(SourceRange Range, RewriteOptions opts=RewriteOptions()) const
getRangeSize - Return the size in bytes of the specified range if they are in the same file...
Selector getSelector() const
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
The result type of a method or function.
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
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.
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
void setSourceMgr(SourceManager &SM, const LangOptions &LO)
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
param_type_range param_types() const
ivar_iterator ivar_begin() const
classmeth_iterator classmeth_end() const
Encodes a location in the source.
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
QualType getReturnType() const
ivar_iterator ivar_end() const
const Stmt * getCatchBody() const
Interfaces are the core concept in Objective-C for object oriented design.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
const RewriteBuffer * getRewriteBufferFor(FileID FID) const
getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
InsertText - Insert the specified string at the specified location in the original buffer...
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 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
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
bool isBooleanType() const
QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
U cast(CodeGen::Address addr)
int printf(__constant const char *st,...)
const Expr * getSynchExpr() const
const ObjCInterfaceDecl * getContainingInterface() const
Return the class interface that this ivar is logically contained in; this is either the interface whe...
QualType getCallResultType(const ASTContext &Context) const
Determine the type of an expression that calls a function of this type.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext, providing only those that are of type SpecificDecl (or a class derived from it).
static bool scanForProtocolRefs(const char *startBuf, const char *endBuf, const char *&startRef, const char *&endRef)
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
Represents a pointer to an Objective C object.
unsigned getByteLength() const
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
SourceLocation getRParenLoc() const
static void BuildUniqueMethodName(std::string &Name, ObjCMethodDecl *MD)
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Represents Objective-C's collection statement.
ObjCEncodeExpr, used for @encode in Objective-C.
static CStyleCastExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R)
SourceLocation getLocation() const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
protocol_iterator protocol_begin() const
void getObjCEncodingForType(QualType T, std::string &S, const FieldDecl *Field=nullptr, QualType *NotEncodedT=nullptr) const
Emit the Objective-CC type encoding for the given type T into S.
bool isObjCQualifiedIdType() const
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
Represents Objective-C's @finally statement.
void addDecl(Decl *D)
Add the declaration D into this context.
const Expr * getBase() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
SourceManager & getSourceManager()
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
SourceRange getAtEndRange() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
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
ObjCMethodDecl * getGetterMethodDecl() 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...