25 #include "llvm/ADT/DenseSet.h"
26 #include "llvm/ADT/SmallPtrSet.h"
27 #include "llvm/ADT/StringExtras.h"
28 #include "llvm/Support/MemoryBuffer.h"
29 #include "llvm/Support/raw_ostream.h"
32 #ifdef CLANG_ENABLE_OBJC_REWRITER
34 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;
80 unsigned RewriteFailedDiag;
82 unsigned NumObjCStringLiterals;
83 VarDecl *ConstantStringClassReference;
89 unsigned TryFinallyContainsReturnDiag;
110 SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
111 SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
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;
116 SmallVector<Stmt *, 32> Stmts;
117 SmallVector<int, 8> ObjCBcLabelNo;
119 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
124 SmallVector<BlockExpr *, 32> Blocks;
125 SmallVector<int, 32> InnerDeclRefsCount;
126 SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
128 SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
131 SmallVector<ValueDecl *, 8> BlockByCopyDecls;
132 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
133 SmallVector<ValueDecl *, 8> BlockByRefDecls;
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;
161 ~DisableReplaceStmtScope() {
162 R.DisableReplaceStmt = SavedValue;
173 if (!Class->isThisDeclarationADefinition()) {
174 RewriteForwardClassDecl(D);
180 if (!Proto->isThisDeclarationADefinition()) {
181 RewriteForwardProtocolDecl(D);
186 HandleTopLevelSingleDecl(*I);
190 void HandleTopLevelSingleDecl(
Decl *D);
191 void HandleDeclInMainFile(
Decl *D);
194 bool silenceMacroWarn);
198 void HandleTranslationUnit(
ASTContext &
C)
override;
200 void ReplaceStmt(
Stmt *Old,
Stmt *New) {
201 ReplaceStmtWithRange(Old, New, Old->getSourceRange());
205 assert(Old !=
nullptr && New !=
nullptr &&
"Expected non-null Stmt's");
207 Stmt *ReplacingStmt = ReplacedNodes[Old];
211 if (DisableReplaceStmt)
215 int Size = Rewrite.getRangeSize(SrcRange);
218 << Old->getSourceRange();
223 llvm::raw_string_ostream
S(SStr);
225 const std::string &Str =
S.str();
228 if (!Rewrite.ReplaceText(SrcRange.
getBegin(), Size, Str)) {
229 ReplacedNodes[Old] = New;
232 if (SilenceRewriteMacroWarning)
235 << Old->getSourceRange();
239 bool InsertAfter =
true) {
241 if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
242 SilenceRewriteMacroWarning)
251 if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
252 SilenceRewriteMacroWarning)
260 void RewriteInclude();
262 void RewriteForwardClassDecl(
const SmallVectorImpl<Decl *> &DG);
264 const std::string &typedefString);
265 void RewriteImplementations();
270 void RewriteImplementationDecl(
Decl *Dcl);
273 void RewriteTypeIntoString(
QualType T, std::string &ResultStr,
275 void RewriteByRefString(std::string &ResultStr,
const std::string &Name,
280 void RewriteForwardProtocolDecl(
const SmallVectorImpl<Decl *> &DG);
284 void RewriteBlockPointerType(std::string& Str,
QualType Type);
285 void RewriteBlockPointerTypeVariable(std::string& Str,
ValueDecl *VD);
287 void RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl);
288 void RewriteTypeOfDecl(
VarDecl *VD);
289 void RewriteObjCQualifiedInterfaceTypes(
Expr *E);
292 Stmt *RewriteFunctionBodyOrGlobalInitializer(
Stmt *
S);
300 void RewriteTryReturnStmts(
Stmt *
S);
301 void RewriteSyncReturnStmts(
Stmt *
S, std::string buf);
315 void RewriteBlockPointerDecl(
NamedDecl *VD);
316 void RewriteByRefVar(
VarDecl *VD);
324 void Initialize(
ASTContext &context)
override = 0;
327 virtual void RewriteMetaDataIntoBuffer(std::string &
Result) = 0;
343 virtual void RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
349 Expr **args,
unsigned nargs,
355 SmallVectorImpl<QualType> &ArgTypes,
356 SmallVectorImpl<Expr*> &MsgExprs,
362 void SynthCountByEnumWithState(std::string &buf);
363 void SynthMsgSendFunctionDecl();
364 void SynthMsgSendSuperFunctionDecl();
365 void SynthMsgSendStretFunctionDecl();
366 void SynthMsgSendFpretFunctionDecl();
367 void SynthMsgSendSuperStretFunctionDecl();
368 void SynthGetClassFunctionDecl();
369 void SynthGetMetaClassFunctionDecl();
370 void SynthGetSuperClassFunctionDecl();
371 void SynthSelGetUidFunctionDecl();
372 void SynthSuperConstructorFunctionDecl();
374 std::string SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
int flag);
375 std::string SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
376 StringRef funcName, std::string Tag);
377 std::string SynthesizeBlockFunc(
BlockExpr *CE,
int i,
378 StringRef funcName, std::string Tag);
379 std::string SynthesizeBlockImpl(
BlockExpr *CE,
380 std::string Tag, std::string Desc);
381 std::string SynthesizeBlockDescriptor(std::string DescTag,
383 int i, StringRef funcName,
388 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
390 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);
394 void WarnAboutReturnGotoStmts(
Stmt *
S);
395 void HasReturnStmts(
Stmt *
S,
bool &hasReturns);
397 void InsertBlockLiteralsWithinFunction(
FunctionDecl *FD);
400 bool IsDeclStmtInForeachHeader(
DeclStmt *DS);
401 void CollectBlockDeclRefInfo(
BlockExpr *Exp);
402 void GetBlockDeclRefExprs(
Stmt *
S);
403 void GetInnerBlockDeclRefExprs(
Stmt *
S,
404 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
405 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
409 bool isTopLevelBlockPointerType(
QualType T) {
410 return isa<BlockPointerType>(T);
416 bool convertBlockPointerToFunctionPointer(
QualType &T) {
417 if (isTopLevelBlockPointerType(T)) {
425 bool needToScanForQualifiers(
QualType T);
427 QualType getConstantStringStructType();
429 bool BufferContainsPPDirectives(
const char *startBuf,
const char *endBuf);
431 void convertToUnqualifiedObjCType(
QualType &T) {
449 if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
459 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
460 PT->getPointeeType()->isObjCQualifiedIdType())
465 bool PointerTypeTakesAnyBlockArguments(
QualType QT);
466 bool PointerTypeTakesAnyObjCQualifiedType(
QualType QT);
467 void GetExtentOfArgList(
const char *Name,
const char *&LParen,
468 const char *&RParen);
470 void QuoteDoublequotes(std::string &From, std::string &To) {
471 for (
unsigned i = 0; i < From.length(); i++) {
480 ArrayRef<QualType> args,
481 bool variadic =
false) {
509 RewriteObjCFragileABI(std::string inFile, raw_ostream *OS,
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))
564 static bool IsHeaderFile(
const std::string &Filename) {
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(OS),
582 SilenceRewriteMacroWarning(silenceMacroWarn) {
583 IsHeader = IsHeaderFile(inFile);
585 "rewriting sub-expression within a macro (may not be correct)");
586 TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
588 "rewriter doesn't support user-specified control flow semantics "
589 "for @try/@finally (code may not execute properly)");
592 std::unique_ptr<ASTConsumer>
595 bool SilenceRewriteMacroWarning) {
596 return llvm::make_unique<RewriteObjCFragileABI>(InFile, OS, Diags, LOpts,
597 SilenceRewriteMacroWarning);
600 void RewriteObjC::InitializeCommon(
ASTContext &context) {
604 MsgSendFunctionDecl =
nullptr;
605 MsgSendSuperFunctionDecl =
nullptr;
606 MsgSendStretFunctionDecl =
nullptr;
607 MsgSendSuperStretFunctionDecl =
nullptr;
608 MsgSendFpretFunctionDecl =
nullptr;
609 GetClassFunctionDecl =
nullptr;
610 GetMetaClassFunctionDecl =
nullptr;
611 GetSuperClassFunctionDecl =
nullptr;
612 SelGetUidFunctionDecl =
nullptr;
613 CFStringFunctionDecl =
nullptr;
614 ConstantStringClassReference =
nullptr;
615 NSStringRecord =
nullptr;
616 CurMethodDef =
nullptr;
617 CurFunctionDef =
nullptr;
618 CurFunctionDeclToDeclareForBlock =
nullptr;
619 GlobalVarDecl =
nullptr;
620 SuperStructDecl =
nullptr;
621 ProtocolTypeDecl =
nullptr;
622 ConstantStringDecl =
nullptr;
624 SuperConstructorFunctionDecl =
nullptr;
625 NumObjCStringLiterals = 0;
626 PropParentMap =
nullptr;
627 CurrentBody =
nullptr;
628 DisableReplaceStmt =
false;
629 objc_impl_method =
false;
633 const llvm::MemoryBuffer *MainBuf =
SM->
getBuffer(MainFileID);
634 MainFileStart = MainBuf->getBufferStart();
635 MainFileEnd = MainBuf->getBufferEnd();
644 void RewriteObjC::HandleTopLevelSingleDecl(
Decl *D) {
645 if (Diags.hasErrorOccurred())
659 RewriteFunctionDecl(FD);
660 }
else if (
VarDecl *FVD = dyn_cast<VarDecl>(D)) {
662 if (FVD->getName() ==
"_NSConstantStringClassReference") {
663 ConstantStringClassReference = FVD;
667 if (
ID->isThisDeclarationADefinition())
668 RewriteInterfaceDecl(
ID);
670 RewriteCategoryDecl(CD);
672 if (PD->isThisDeclarationADefinition())
673 RewriteProtocolDecl(PD);
677 DIEnd = LSD->decls_end();
680 if (!IFace->isThisDeclarationADefinition()) {
681 SmallVector<Decl *, 8> DG;
684 if (isa<ObjCInterfaceDecl>(*DI) &&
685 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
686 StartLoc == (*DI)->getLocStart())
692 }
while (DI != DIEnd);
693 RewriteForwardClassDecl(DG);
699 if (!Proto->isThisDeclarationADefinition()) {
700 SmallVector<Decl *, 8> DG;
703 if (isa<ObjCProtocolDecl>(*DI) &&
704 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
705 StartLoc == (*DI)->getLocStart())
711 }
while (DI != DIEnd);
712 RewriteForwardProtocolDecl(DG);
717 HandleTopLevelSingleDecl(*DI);
723 return HandleDeclInMainFile(D);
730 void RewriteObjC::RewriteInclude() {
733 const char *MainBufStart = MainBuf.begin();
734 const char *MainBufEnd = MainBuf.end();
735 size_t ImportLen = strlen(
"import");
738 for (
const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
739 if (*BufPtr ==
'#') {
740 if (++BufPtr == MainBufEnd)
742 while (*BufPtr ==
' ' || *BufPtr ==
'\t')
743 if (++BufPtr == MainBufEnd)
745 if (!strncmp(BufPtr,
"import", ImportLen)) {
749 ReplaceText(ImportLoc, ImportLen,
"include");
756 static std::string getIvarAccessString(
ObjCIvarDecl *OID) {
761 S +=
"_IMPL *)self)->";
769 static bool objcGetPropertyDefined =
false;
770 static bool objcSetPropertyDefined =
false;
772 InsertText(startLoc,
"// ");
774 assert((*startBuf ==
'@') &&
"bogus @synthesize location");
775 const char *semiBuf = strchr(startBuf,
';');
776 assert((*semiBuf ==
';') &&
"@synthesize: can't find ';'");
791 bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
792 (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
793 ObjCPropertyDecl::OBJC_PR_copy));
795 if (GenGetProperty && !objcGetPropertyDefined) {
796 objcGetPropertyDefined =
true;
798 Getr =
"\nextern \"C\" __declspec(dllimport) "
799 "id objc_getProperty(id, SEL, long, bool);\n";
806 if (GenGetProperty) {
819 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
821 std::string ParamStr =
825 if (FT->isVariadic()) {
826 if (FT->getNumParams())
835 Getr +=
"return (_TYPE)";
836 Getr +=
"objc_getProperty(self, _cmd, ";
837 RewriteIvarOffsetComputation(OID, Getr);
841 Getr +=
"return " + getIvarAccessString(OID);
843 InsertText(onePastSemiLoc, Getr);
851 bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
852 ObjCPropertyDecl::OBJC_PR_copy);
853 if (GenSetProperty && !objcSetPropertyDefined) {
854 objcSetPropertyDefined =
true;
856 Setr =
"\nextern \"C\" __declspec(dllimport) "
857 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
865 if (GenSetProperty) {
866 Setr +=
"objc_setProperty (self, _cmd, ";
867 RewriteIvarOffsetComputation(OID, Setr);
871 if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
875 if (Attributes & ObjCPropertyDecl::OBJC_PR_copy)
881 Setr += getIvarAccessString(OID) +
" = ";
885 InsertText(onePastSemiLoc, Setr);
889 std::string &typedefString) {
890 typedefString +=
"#ifndef _REWRITER_typedef_";
892 typedefString +=
"\n";
893 typedefString +=
"#define _REWRITER_typedef_";
895 typedefString +=
"\n";
896 typedefString +=
"typedef struct objc_object ";
898 typedefString +=
";\n#endif\n";
902 const std::string &typedefString) {
905 const char *semiPtr = strchr(startBuf,
';');
907 ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
910 void RewriteObjC::RewriteForwardClassDecl(
DeclGroupRef D) {
911 std::string typedefString;
914 if (I == D.
begin()) {
918 typedefString +=
"// @class ";
920 typedefString +=
";\n";
922 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
925 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
928 void RewriteObjC::RewriteForwardClassDecl(
const SmallVectorImpl<Decl *> &D) {
929 std::string typedefString;
930 for (
unsigned i = 0; i < D.size(); i++) {
933 typedefString +=
"// @class ";
935 typedefString +=
";\n";
937 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
939 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
942 void RewriteObjC::RewriteMethodDeclaration(
ObjCMethodDecl *Method) {
952 InsertText(LocStart,
"#if 0\n");
953 ReplaceText(LocEnd, 1,
";\n#endif\n");
955 InsertText(LocStart,
"// ");
962 ReplaceText(Loc, 0,
"// ");
970 ReplaceText(LocStart, 0,
"// ");
975 RewriteMethodDeclaration(I);
977 RewriteMethodDeclaration(I);
981 strlen(
"@end"),
"/* @end */");
989 ReplaceText(LocStart, 0,
"// ");
992 RewriteMethodDeclaration(I);
994 RewriteMethodDeclaration(I);
1000 ReplaceText(LocEnd, strlen(
"@end"),
"/* @end */");
1005 for (
const char *
p = startBuf;
p < endBuf;
p++) {
1006 if (*
p ==
'@' && !strncmp(
p+1,
"optional", strlen(
"optional"))) {
1008 ReplaceText(OptionalLoc, strlen(
"@optional"),
"/* @optional */");
1011 else if (*
p ==
'@' && !strncmp(
p+1,
"required", strlen(
"required"))) {
1013 ReplaceText(OptionalLoc, strlen(
"@required"),
"/* @required */");
1019 void RewriteObjC::RewriteForwardProtocolDecl(
DeclGroupRef D) {
1022 llvm_unreachable(
"Invalid SourceLocation");
1024 ReplaceText(LocStart, 0,
"// ");
1028 RewriteObjC::RewriteForwardProtocolDecl(
const SmallVectorImpl<Decl *> &DG) {
1031 llvm_unreachable(
"Invalid SourceLocation");
1033 ReplaceText(LocStart, 0,
"// ");
1036 void RewriteObjC::RewriteTypeIntoString(
QualType T, std::string &ResultStr,
1061 std::string &ResultStr) {
1064 ResultStr +=
"\nstatic ";
1065 RewriteTypeIntoString(OMD->
getReturnType(), ResultStr, FPRetType);
1069 std::string NameStr;
1087 int len = selString.size();
1088 for (
int i = 0; i < len; i++)
1089 if (selString[i] ==
':')
1091 NameStr += selString;
1094 MethodInternalNames[OMD] = NameStr;
1095 ResultStr += NameStr;
1104 if (!LangOpts.MicrosoftExt) {
1105 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
1106 ResultStr +=
"struct ";
1116 ResultStr +=
" self, ";
1118 ResultStr +=
" _cmd";
1121 for (
const auto *PDecl : OMD->
params()) {
1123 if (PDecl->getType()->isObjCQualifiedIdType()) {
1130 (void)convertBlockPointerToFunctionPointer(QT);
1136 ResultStr +=
", ...";
1145 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
1146 if (i) ResultStr +=
", ";
1147 std::string ParamStr =
1149 ResultStr += ParamStr;
1151 if (FT->isVariadic()) {
1152 if (FT->getNumParams())
1162 void RewriteObjC::RewriteImplementationDecl(
Decl *OID) {
1166 InsertText(IMD ? IMD->
getLocStart() : CID->getLocStart(),
"// ");
1168 for (
auto *OMD : IMD ? IMD->
instance_methods() : CID->instance_methods()) {
1169 std::string ResultStr;
1176 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1179 for (
auto *OMD : IMD ? IMD->
class_methods() : CID->class_methods()) {
1180 std::string ResultStr;
1187 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1189 for (
auto *I : IMD ? IMD->
property_impls() : CID->property_impls())
1190 RewritePropertyImplDecl(I, IMD, CID);
1192 InsertText(IMD ? IMD->
getLocEnd() : CID->getLocEnd(),
"// ");
1196 std::string ResultStr;
1199 ResultStr =
"#ifndef _REWRITER_typedef_";
1202 ResultStr +=
"#define _REWRITER_typedef_";
1205 ResultStr +=
"typedef struct objc_object ";
1207 ResultStr +=
";\n#endif\n";
1211 RewriteObjCInternalStruct(ClassDecl, ResultStr);
1216 RewriteMethodDeclaration(I);
1218 RewriteMethodDeclaration(I);
1226 SourceRange OldRange = PseudoOp->getSourceRange();
1238 DisableReplaceStmtScope
S(*
this);
1244 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1245 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1250 RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
1251 RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1255 SmallVector<SourceLocation, 1> SelLocs;
1260 case ObjCMessageExpr::Class:
1273 case ObjCMessageExpr::Instance:
1286 case ObjCMessageExpr::SuperClass:
1287 case ObjCMessageExpr::SuperInstance:
1303 Stmt *Replacement = SynthMessageExpr(NewMsg);
1304 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1309 SourceRange OldRange = PseudoOp->getSourceRange();
1318 Expr *Base =
nullptr;
1320 DisableReplaceStmtScope
S(*
this);
1325 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1326 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1331 SmallVector<SourceLocation, 1> SelLocs;
1332 SmallVector<Expr*, 1> Args;
1336 case ObjCMessageExpr::Class:
1349 case ObjCMessageExpr::Instance:
1362 case ObjCMessageExpr::SuperClass:
1363 case ObjCMessageExpr::SuperInstance:
1379 Stmt *Replacement = SynthMessageExpr(NewMsg);
1380 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1393 void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1394 buf +=
"((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
1395 "id *, unsigned int))(void *)objc_msgSend)";
1397 buf +=
"((id)l_collection,\n\t\t";
1398 buf +=
"sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1400 buf +=
"&enumState, "
1401 "(id *)__rw_items, (unsigned int)16)";
1408 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1414 buf =
"goto __break_label_";
1415 buf += utostr(ObjCBcLabelNo.back());
1416 ReplaceText(startLoc, strlen(
"break"), buf);
1425 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1431 buf =
"goto __continue_label_";
1432 buf += utostr(ObjCBcLabelNo.back());
1433 ReplaceText(startLoc, strlen(
"continue"), buf);
1472 assert(!Stmts.empty() &&
"ObjCForCollectionStmt - Statement stack empty");
1473 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1474 "ObjCForCollectionStmt Statement stack mismatch");
1475 assert(!ObjCBcLabelNo.empty() &&
1476 "ObjCForCollectionStmt - Label No stack empty");
1480 StringRef elementName;
1481 std::string elementTypeAsString;
1486 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1487 QualType ElementType = cast<ValueDecl>(D)->getType();
1488 if (ElementType->isObjCQualifiedIdType() ||
1489 ElementType->isObjCQualifiedInterfaceType())
1491 elementTypeAsString =
"id";
1494 buf += elementTypeAsString;
1507 elementTypeAsString =
"id";
1513 buf +=
"struct __objcFastEnumerationState enumState = { 0 };\n\t";
1515 buf +=
"id __rw_items[16];\n\t";
1517 buf +=
"id l_collection = (id)";
1519 const char *startCollectionBuf = startBuf;
1520 startCollectionBuf += 3;
1521 startCollectionBuf = strchr(startCollectionBuf,
'(');
1522 startCollectionBuf++;
1524 while (*startCollectionBuf !=
' ' ||
1525 *(startCollectionBuf+1) !=
'i' || *(startCollectionBuf+2) !=
'n' ||
1526 (*(startCollectionBuf+3) !=
' ' &&
1527 *(startCollectionBuf+3) !=
'[' && *(startCollectionBuf+3) !=
'('))
1528 startCollectionBuf++;
1529 startCollectionBuf += 3;
1532 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1550 buf +=
"unsigned long limit =\n\t\t";
1551 SynthCountByEnumWithState(buf);
1561 buf +=
"if (limit) {\n\t";
1562 buf +=
"unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1563 buf +=
"do {\n\t\t";
1564 buf +=
"unsigned long counter = 0;\n\t\t";
1565 buf +=
"do {\n\t\t\t";
1566 buf +=
"if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1567 buf +=
"objc_enumerationMutation(l_collection);\n\t\t\t";
1570 buf += elementTypeAsString;
1571 buf +=
")enumState.itemsPtr[counter++];";
1573 ReplaceText(lparenLoc, 1, buf);
1587 buf +=
"__continue_label_";
1588 buf += utostr(ObjCBcLabelNo.back());
1591 buf +=
"} while (counter < limit);\n\t";
1592 buf +=
"} while (limit = ";
1593 SynthCountByEnumWithState(buf);
1597 buf += elementTypeAsString;
1599 buf +=
"__break_label_";
1600 buf += utostr(ObjCBcLabelNo.back());
1603 buf +=
"else\n\t\t";
1606 buf += elementTypeAsString;
1612 if (isa<CompoundStmt>(S->
getBody())) {
1614 InsertText(endBodyLoc, buf);
1624 const char *semiBuf = strchr(stmtBuf,
';');
1625 assert(semiBuf &&
"Can't find ';'");
1627 InsertText(endBodyLoc, buf);
1630 ObjCBcLabelNo.pop_back();
1645 assert((*startBuf ==
'@') &&
"bogus @synchronized location");
1648 buf =
"objc_sync_enter((id)";
1649 const char *lparenBuf = startBuf;
1650 while (*lparenBuf !=
'(') lparenBuf++;
1651 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1657 while (*endBuf !=
')') endBuf--;
1661 buf +=
"/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1662 buf +=
"int buf[18/*32-bit i386*/];\n";
1663 buf +=
"char *pointers[4];} _stack;\n";
1664 buf +=
"id volatile _rethrow = 0;\n";
1665 buf +=
"objc_exception_try_enter(&_stack);\n";
1666 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1667 ReplaceText(rparenLoc, 1, buf);
1671 assert((*startBuf ==
'}') &&
"bogus @synchronized block");
1673 buf =
"}\nelse {\n";
1674 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1676 buf +=
"{ /* implicit finally clause */\n";
1677 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1679 std::string syncBuf;
1680 syncBuf +=
" objc_sync_exit(";
1690 std::string syncExprBufS;
1691 llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1692 assert(syncExpr !=
nullptr &&
"Expected non-null Expr");
1693 syncExpr->printPretty(syncExprBuf,
nullptr,
PrintingPolicy(LangOpts));
1694 syncBuf += syncExprBuf.str();
1698 buf +=
"\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1702 ReplaceText(lastCurlyLoc, 1, buf);
1704 bool hasReturns =
false;
1712 void RewriteObjC::WarnAboutReturnGotoStmts(
Stmt *S)
1715 for (
Stmt *SubStmt : S->children())
1717 WarnAboutReturnGotoStmts(SubStmt);
1719 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1721 TryFinallyContainsReturnDiag);
1726 void RewriteObjC::HasReturnStmts(
Stmt *S,
bool &hasReturns)
1729 for (
Stmt *SubStmt : S->children())
1731 HasReturnStmts(SubStmt, hasReturns);
1733 if (isa<ReturnStmt>(S))
1738 void RewriteObjC::RewriteTryReturnStmts(
Stmt *S) {
1740 for (
Stmt *SubStmt : S->children())
1742 RewriteTryReturnStmts(SubStmt);
1744 if (isa<ReturnStmt>(S)) {
1748 const char *semiBuf = strchr(startBuf,
';');
1749 assert((*semiBuf ==
';') &&
"RewriteTryReturnStmts: can't find ';'");
1753 buf =
"{ objc_exception_try_exit(&_stack); return";
1755 ReplaceText(startLoc, 6, buf);
1756 InsertText(onePastSemiLoc,
"}");
1761 void RewriteObjC::RewriteSyncReturnStmts(
Stmt *S, std::string syncExitBuf) {
1763 for (
Stmt *SubStmt : S->children())
1765 RewriteSyncReturnStmts(SubStmt, syncExitBuf);
1767 if (isa<ReturnStmt>(S)) {
1771 const char *semiBuf = strchr(startBuf,
';');
1772 assert((*semiBuf ==
';') &&
"RewriteSyncReturnStmts: can't find ';'");
1776 buf =
"{ objc_exception_try_exit(&_stack);";
1780 ReplaceText(startLoc, 6, buf);
1781 InsertText(onePastSemiLoc,
"}");
1791 assert((*startBuf ==
'@') &&
"bogus @try location");
1795 buf =
"/* @try scope begin */ { struct _objc_exception_data {\n";
1796 buf +=
"int buf[18/*32-bit i386*/];\n";
1797 buf +=
"char *pointers[4];} _stack;\n";
1798 buf +=
"id volatile _rethrow = 0;\n";
1799 buf +=
"objc_exception_try_enter(&_stack);\n";
1800 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1802 ReplaceText(startLoc, 4, buf);
1807 assert((*startBuf ==
'}') &&
"bogus @try block");
1812 buf =
" /* @catch begin */ else {\n";
1813 buf +=
" id _caught = objc_exception_extract(&_stack);\n";
1814 buf +=
" objc_exception_try_enter (&_stack);\n";
1815 buf +=
" if (_setjmp(_stack.buf))\n";
1816 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1817 buf +=
" else { /* @catch continue */";
1819 InsertText(startLoc, buf);
1821 buf =
"}\nelse {\n";
1822 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1824 ReplaceText(lastCurlyLoc, 1, buf);
1826 Stmt *lastCatchBody =
nullptr;
1838 assert((*startBuf ==
'@') &&
"bogus @catch location");
1840 const char *lParenLoc = strchr(startBuf,
'(');
1848 "bogus @catch paren location");
1849 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1851 buf +=
"1) { id _tmp = _caught;";
1852 Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
1853 }
else if (catchDecl) {
1857 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1863 buf +=
"objc_exception_match((struct objc_class *)objc_getClass(\"";
1865 buf +=
"\"), (struct objc_object *)_caught)) { ";
1866 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1875 assert((*rParenBuf ==
')') &&
"bogus @catch paren location");
1876 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1880 ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
" = _caught;");
1882 llvm_unreachable(
"@catch rewrite bug");
1886 if (lastCatchBody) {
1889 "bogus @catch body location");
1893 buf =
"} /* last catch end */\n";
1895 buf +=
" _rethrow = _caught;\n";
1896 buf +=
" objc_exception_try_exit(&_stack);\n";
1897 buf +=
"} } /* @catch end */\n";
1900 InsertText(bodyLoc, buf);
1903 lastCurlyLoc = lastCatchBody->getLocEnd();
1906 startLoc = finalStmt->getLocStart();
1908 assert((*startBuf ==
'@') &&
"bogus @finally start");
1910 ReplaceText(startLoc, 8,
"/* @finally */");
1912 Stmt *body = finalStmt->getFinallyBody();
1916 "bogus @finally body location");
1918 "bogus @finally body location");
1921 InsertText(startLoc,
" if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1923 InsertText(endLoc,
" if (_rethrow) objc_exception_throw(_rethrow);\n");
1926 lastCurlyLoc = body->getLocEnd();
1931 buf =
"{ /* implicit finally clause */\n";
1932 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1933 buf +=
" if (_rethrow) objc_exception_throw(_rethrow);\n";
1935 ReplaceText(lastCurlyLoc, 1, buf);
1940 bool hasReturns =
false;
1947 InsertText(lastCurlyLoc,
" } /* @try scope end */\n");
1959 assert((*startBuf ==
'@') &&
"bogus @throw location");
1964 buf =
"objc_exception_throw(";
1966 buf =
"objc_exception_throw(_caught";
1969 const char *wBuf = strchr(startBuf,
'w');
1970 assert((*wBuf ==
'w') &&
"@throw: can't find 'w'");
1971 ReplaceText(startLoc, wBuf-startBuf+1, buf);
1973 const char *semiBuf = strchr(startBuf,
';');
1974 assert((*semiBuf ==
';') &&
"@throw: can't find ';'");
1976 ReplaceText(semiLoc, 1,
");");
1982 std::string StrEncoding;
1984 Expr *Replacement = getStringLiteral(StrEncoding);
1985 ReplaceStmt(Exp, Replacement);
1993 if (!SelGetUidFunctionDecl)
1994 SynthSelGetUidFunctionDecl();
1995 assert(SelGetUidFunctionDecl &&
"Can't find sel_registerName() decl");
1997 SmallVector<Expr*, 8> SelExprs;
1999 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2000 &SelExprs[0], SelExprs.size());
2001 ReplaceStmt(Exp, SelExp);
2006 CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
2031 static bool scanForProtocolRefs(
const char *startBuf,
const char *endBuf,
2032 const char *&startRef,
const char *&endRef) {
2033 while (startBuf < endBuf) {
2034 if (*startBuf ==
'<')
2035 startRef = startBuf;
2036 if (*startBuf ==
'>') {
2037 if (startRef && *startRef ==
'<') {
2048 static void scanToNextArgument(
const char *&argRef) {
2050 while (*argRef !=
')' && (*argRef !=
',' || angle > 0)) {
2053 else if (*argRef ==
'>')
2057 assert(angle == 0 &&
"scanToNextArgument - bad protocol type syntax");
2060 bool RewriteObjC::needToScanForQualifiers(
QualType T) {
2073 return needToScanForQualifiers(ElemTy);
2078 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Expr *E) {
2080 if (needToScanForQualifiers(Type)) {
2084 Loc = ECE->getLParenLoc();
2085 EndLoc = ECE->getRParenLoc();
2087 Loc = E->getLocStart();
2088 EndLoc = E->getLocEnd();
2096 const char *startRef =
nullptr, *endRef =
nullptr;
2097 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2102 InsertText(LessLoc,
"/*");
2103 InsertText(GreaterLoc,
"*/");
2108 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl) {
2112 if (
VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2116 else if (
FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2121 assert(funcType &&
"missing function type");
2127 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2134 if (needToScanForQualifiers(Type)) {
2138 const char *startBuf = endBuf;
2139 while (*startBuf !=
';' && *startBuf !=
'<' && startBuf != MainFileStart)
2141 const char *startRef =
nullptr, *endRef =
nullptr;
2142 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2147 InsertText(LessLoc,
"/*");
2148 InsertText(GreaterLoc,
"*/");
2155 const char *startFuncBuf = startBuf;
2160 const char *endBuf = startBuf;
2162 scanToNextArgument(endBuf);
2163 const char *startRef =
nullptr, *endRef =
nullptr;
2164 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2171 InsertText(LessLoc,
"/*");
2172 InsertText(GreaterLoc,
"*/");
2174 startBuf = ++endBuf;
2179 while (*startBuf && *startBuf !=
')' && *startBuf !=
',')
2186 void RewriteObjC::RewriteTypeOfDecl(
VarDecl *ND) {
2188 const Type* TypePtr = QT->
getAs<Type>();
2189 if (!isa<TypeOfExprType>(TypePtr))
2191 while (isa<TypeOfExprType>(TypePtr)) {
2192 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2194 TypePtr = QT->
getAs<Type>();
2203 TypeAsString +=
" " + Name +
" = ";
2207 startLoc = ECE->getLParenLoc();
2209 startLoc = E->getLocStart();
2212 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2218 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2223 void RewriteObjC::SynthSelGetUidFunctionDecl() {
2225 SmallVector<QualType, 16> ArgTys;
2232 SelGetUidIdent, getFuncType,
2236 void RewriteObjC::RewriteFunctionDecl(
FunctionDecl *FD) {
2239 FD->
getName() ==
"sel_registerName") {
2240 SelGetUidFunctionDecl = FD;
2243 RewriteObjCQualifiedInterfaceTypes(FD);
2246 void RewriteObjC::RewriteBlockPointerType(std::string& Str,
QualType Type) {
2248 const char *argPtr = TypeString.c_str();
2249 if (!strchr(argPtr,
'^')) {
2254 Str += (*argPtr ==
'^' ?
'*' : *argPtr);
2260 void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2264 const char *argPtr = TypeString.c_str();
2290 void RewriteObjC::RewriteBlockLiteralFunctionDecl(
FunctionDecl *FD) {
2296 QualType Type = proto->getReturnType();
2301 unsigned numArgs = proto->getNumParams();
2302 for (
unsigned i = 0; i < numArgs; i++) {
2303 QualType ArgType = proto->getParamType(i);
2304 RewriteBlockPointerType(FdStr, ArgType);
2309 InsertText(FunLocStart, FdStr);
2310 CurFunctionDeclToDeclareForBlock =
nullptr;
2314 void RewriteObjC::SynthSuperConstructorFunctionDecl() {
2315 if (SuperConstructorFunctionDecl)
2318 SmallVector<QualType, 16> ArgTys;
2320 assert(!argT.
isNull() &&
"Can't find 'id' type");
2321 ArgTys.push_back(argT);
2322 ArgTys.push_back(argT);
2328 msgSendIdent, msgSendType,
2333 void RewriteObjC::SynthMsgSendFunctionDecl() {
2335 SmallVector<QualType, 16> ArgTys;
2337 assert(!argT.
isNull() &&
"Can't find 'id' type");
2338 ArgTys.push_back(argT);
2340 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2341 ArgTys.push_back(argT);
2347 msgSendIdent, msgSendType,
2352 void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2354 SmallVector<QualType, 16> ArgTys;
2359 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2360 ArgTys.push_back(argT);
2362 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2363 ArgTys.push_back(argT);
2369 msgSendIdent, msgSendType,
2374 void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2376 SmallVector<QualType, 16> ArgTys;
2378 assert(!argT.
isNull() &&
"Can't find 'id' type");
2379 ArgTys.push_back(argT);
2381 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2382 ArgTys.push_back(argT);
2388 msgSendIdent, msgSendType,
2394 void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2397 SmallVector<QualType, 16> ArgTys;
2402 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2403 ArgTys.push_back(argT);
2405 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2406 ArgTys.push_back(argT);
2413 msgSendType,
nullptr,
2418 void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2420 SmallVector<QualType, 16> ArgTys;
2422 assert(!argT.
isNull() &&
"Can't find 'id' type");
2423 ArgTys.push_back(argT);
2425 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2426 ArgTys.push_back(argT);
2432 msgSendIdent, msgSendType,
2437 void RewriteObjC::SynthGetClassFunctionDecl() {
2439 SmallVector<QualType, 16> ArgTys;
2446 getClassIdent, getClassType,
2451 void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2454 SmallVector<QualType, 16> ArgTys;
2462 getClassType,
nullptr,
2467 void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2469 SmallVector<QualType, 16> ArgTys;
2476 getClassIdent, getClassType,
2481 assert(Exp !=
nullptr &&
"Expected non-null ObjCStringLiteral");
2482 QualType strType = getConstantStringStructType();
2484 std::string S =
"__NSConstantStringImpl_";
2486 std::string tmpName = InFileName;
2488 for (i=0; i < tmpName.length(); i++) {
2489 char c = tmpName.at(i);
2496 S += utostr(NumObjCStringLiterals++);
2498 Preamble +=
"static __NSConstantStringImpl " +
S;
2499 Preamble +=
" __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2500 Preamble +=
"0x000007c8,";
2502 std::string prettyBufS;
2503 llvm::raw_string_ostream prettyBuf(prettyBufS);
2505 Preamble += prettyBuf.str();
2521 ReplaceStmt(Exp, cast);
2527 QualType RewriteObjC::getSuperStructType() {
2528 if (!SuperStructDecl) {
2540 for (
unsigned i = 0; i < 2; ++i) {
2544 FieldTypes[i],
nullptr,
2550 SuperStructDecl->completeDefinition();
2555 QualType RewriteObjC::getConstantStringStructType() {
2556 if (!ConstantStringDecl) {
2572 for (
unsigned i = 0; i < 4; ++i) {
2577 FieldTypes[i],
nullptr,
2583 ConstantStringDecl->completeDefinition();
2591 SmallVectorImpl<QualType> &ArgTypes,
2592 SmallVectorImpl<Expr*> &MsgExprs,
2603 QualType castType = getSimpleFunctionType(returnType, ArgTypes,
2624 if (!SelGetUidFunctionDecl)
2625 SynthSelGetUidFunctionDecl();
2626 if (!MsgSendFunctionDecl)
2627 SynthMsgSendFunctionDecl();
2628 if (!MsgSendSuperFunctionDecl)
2629 SynthMsgSendSuperFunctionDecl();
2630 if (!MsgSendStretFunctionDecl)
2631 SynthMsgSendStretFunctionDecl();
2632 if (!MsgSendSuperStretFunctionDecl)
2633 SynthMsgSendSuperStretFunctionDecl();
2634 if (!MsgSendFpretFunctionDecl)
2635 SynthMsgSendFpretFunctionDecl();
2636 if (!GetClassFunctionDecl)
2637 SynthGetClassFunctionDecl();
2638 if (!GetSuperClassFunctionDecl)
2639 SynthGetSuperClassFunctionDecl();
2640 if (!GetMetaClassFunctionDecl)
2641 SynthGetMetaClassFunctionDecl();
2648 QualType resultType = mDecl->getReturnType();
2650 MsgSendStretFlavor = MsgSendStretFunctionDecl;
2652 MsgSendFlavor = MsgSendFpretFunctionDecl;
2656 SmallVector<Expr*, 8> MsgExprs;
2658 case ObjCMessageExpr::SuperClass: {
2659 MsgSendFlavor = MsgSendSuperFunctionDecl;
2660 if (MsgSendStretFlavor)
2661 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2662 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2666 SmallVector<Expr*, 4> InitExprs;
2669 InitExprs.push_back(
2680 SmallVector<Expr*, 8> ClsExprs;
2682 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2692 ClsExprs.push_back(ArgExpr);
2693 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
2694 &ClsExprs[0], ClsExprs.size(),
2699 InitExprs.push_back(
2700 NoTypeInfoCStyleCastExpr(
Context,
2704 QualType superType = getSuperStructType();
2707 if (LangOpts.MicrosoftExt) {
2708 SynthSuperConstructorFunctionDecl();
2726 SuperRep = NoTypeInfoCStyleCastExpr(
Context,
2745 MsgExprs.push_back(SuperRep);
2749 case ObjCMessageExpr::Class: {
2750 SmallVector<Expr*, 8> ClsExprs;
2754 ClsExprs.push_back(getStringLiteral(clsName->
getName()));
2755 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
2759 MsgExprs.push_back(Cls);
2763 case ObjCMessageExpr::SuperInstance:{
2764 MsgSendFlavor = MsgSendSuperFunctionDecl;
2765 if (MsgSendStretFlavor)
2766 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2767 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2769 SmallVector<Expr*, 4> InitExprs;
2771 InitExprs.push_back(
2781 SmallVector<Expr*, 8> ClsExprs;
2783 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
2792 ClsExprs.push_back(ArgExpr);
2793 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
2794 &ClsExprs[0], ClsExprs.size(),
2799 InitExprs.push_back(
2804 QualType superType = getSuperStructType();
2807 if (LangOpts.MicrosoftExt) {
2808 SynthSuperConstructorFunctionDecl();
2811 false, superType, VK_LValue,
2825 SuperRep = NoTypeInfoCStyleCastExpr(
Context,
2839 MsgExprs.push_back(SuperRep);
2843 case ObjCMessageExpr::Instance: {
2848 recExpr = CE->getSubExpr();
2856 MsgExprs.push_back(recExpr);
2862 SmallVector<Expr*, 8> SelExprs;
2864 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2865 &SelExprs[0], SelExprs.size(),
2868 MsgExprs.push_back(SelExp);
2871 for (
unsigned i = 0; i < Exp->
getNumArgs(); i++) {
2877 if (needToScanForQualifiers(type))
2880 (void)convertBlockPointerToFunctionPointer(type);
2898 userExpr = NoTypeInfoCStyleCastExpr(
Context, type, CK, userExpr);
2901 else if (
CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2902 if (CE->getType()->isObjCQualifiedIdType()) {
2903 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2904 userExpr = CE->getSubExpr();
2919 MsgExprs.push_back(userExpr);
2927 SmallVector<QualType, 8> ArgTypes;
2931 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2938 for (
const auto *PI : OMD->
params()) {
2943 (void)convertBlockPointerToFunctionPointer(t);
2944 ArgTypes.push_back(t);
2947 convertToUnqualifiedObjCType(returnType);
2948 (void)convertBlockPointerToFunctionPointer(returnType);
2963 cast = NoTypeInfoCStyleCastExpr(
Context,
2971 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() :
true);
2982 Stmt *ReplacingStmt = CE;
2983 if (MsgSendStretFlavor) {
2989 CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
2990 msgSendType, returnType,
3007 llvm::APInt(IntSize, 8),
3024 return ReplacingStmt;
3032 ReplaceStmt(Exp, ReplacingStmt);
3035 return ReplacingStmt;
3039 QualType RewriteObjC::getProtocolType() {
3040 if (!ProtocolTypeDecl) {
3069 ReplaceStmt(Exp, castExpr);
3076 bool RewriteObjC::BufferContainsPPDirectives(
const char *startBuf,
3077 const char *endBuf) {
3078 while (startBuf < endBuf) {
3079 if (*startBuf ==
'#') {
3081 for (++startBuf; startBuf[0] ==
' ' || startBuf[0] ==
'\t'; ++startBuf)
3083 if (!strncmp(startBuf,
"if", strlen(
"if")) ||
3084 !strncmp(startBuf,
"ifdef", strlen(
"ifdef")) ||
3085 !strncmp(startBuf,
"ifndef", strlen(
"ifndef")) ||
3086 !strncmp(startBuf,
"define", strlen(
"define")) ||
3087 !strncmp(startBuf,
"undef", strlen(
"undef")) ||
3088 !strncmp(startBuf,
"else", strlen(
"else")) ||
3089 !strncmp(startBuf,
"elif", strlen(
"elif")) ||
3090 !strncmp(startBuf,
"endif", strlen(
"endif")) ||
3091 !strncmp(startBuf,
"pragma", strlen(
"pragma")) ||
3092 !strncmp(startBuf,
"include", strlen(
"include")) ||
3093 !strncmp(startBuf,
"import", strlen(
"import")) ||
3094 !strncmp(startBuf,
"include_next", strlen(
"include_next")))
3105 std::string &Result) {
3106 assert(CDecl &&
"Class missing in SynthesizeObjCInternalStruct");
3107 assert(CDecl->
getName() !=
"" &&
3108 "Name missing in SynthesizeObjCInternalStruct");
3110 if (ObjCSynthesizedStructs.count(CDecl))
3123 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3124 endBuf += Lexer::MeasureTokenLength(LocEnd, *
SM, LangOpts);
3125 ReplaceText(LocStart, endBuf-startBuf, Result);
3131 Result +=
"\nstruct ";
3133 if (LangOpts.MicrosoftExt)
3137 const char *cursor = strchr(startBuf,
'{');
3138 assert((cursor && endBuf)
3139 &&
"SynthesizeObjCInternalStruct - malformed @interface");
3155 if (BufferContainsPPDirectives(startBuf, cursor)) {
3159 endHeader += Lexer::MeasureTokenLength(L, *
SM, LangOpts);
3163 while (endHeader < cursor && *endHeader != '>
') endHeader++;
3166 // rewrite the original header
3167 ReplaceText(LocStart, endHeader-startBuf, Result);
3169 // rewrite the original header *without* disturbing the '{
'
3170 ReplaceText(LocStart, cursor-startBuf, Result);
3172 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
3173 Result = "\n struct ";
3174 Result += RCDecl->getNameAsString();
3176 Result += RCDecl->getNameAsString();
3177 Result += "_IVARS;\n";
3179 // insert the super class structure definition.
3180 SourceLocation OnePastCurly =
3181 LocStart.getLocWithOffset(cursor-startBuf+1);
3182 InsertText(OnePastCurly, Result);
3184 cursor++; // past '{
'
3186 // Now comment out any visibility specifiers.
3187 while (cursor < endBuf) {
3188 if (*cursor == '@
') {
3189 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3191 for (++cursor; cursor[0] == ' ' || cursor[0] == '\t
'; ++cursor)
3194 // FIXME: presence of @public, etc. inside comment results in
3195 // this transformation as well, which is still correct c-code.
3196 if (!strncmp(cursor, "public", strlen("public")) ||
3197 !strncmp(cursor, "private", strlen("private")) ||
3198 !strncmp(cursor, "package", strlen("package")) ||
3199 !strncmp(cursor, "protected", strlen("protected")))
3200 InsertText(atLoc, "// ");
3202 // FIXME: If there are cases where '<
' is used in ivar declaration part
3203 // of user code, then scan the ivar list and use needToScanForQualifiers
3204 // for type checking.
3205 else if (*cursor == '<
') {
3206 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3207 InsertText(atLoc, "/* ");
3208 cursor = strchr(cursor, '>
');
3210 atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3211 InsertText(atLoc, " */");
3212 } else if (*cursor == '^
') { // rewrite block specifier.
3213 SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf);
3214 ReplaceText(caretLoc, 1, "*");
3218 // Don't forget to add a
';'!!
3221 endBuf += Lexer::MeasureTokenLength(LocEnd, *
SM, LangOpts);
3222 Result +=
" {\n struct ";
3226 Result +=
"_IVARS;\n};\n";
3227 ReplaceText(LocStart, endBuf-startBuf, Result);
3230 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3231 llvm_unreachable(
"struct already synthesize- SynthesizeObjCInternalStruct");
3242 void RewriteObjC::RewriteImplementations() {
3243 int ClsDefCount = ClassImplementation.size();
3244 int CatDefCount = CategoryImplementation.size();
3247 for (
int i = 0; i < ClsDefCount; i++)
3248 RewriteImplementationDecl(ClassImplementation[i]);
3250 for (
int i = 0; i < CatDefCount; i++)
3251 RewriteImplementationDecl(CategoryImplementation[i]);
3254 void RewriteObjC::RewriteByRefString(std::string &ResultStr,
3255 const std::string &Name,
3257 assert(BlockByRefDeclNo.count(VD) &&
3258 "RewriteByRefString: ByRef decl missing");
3260 ResultStr +=
"struct ";
3261 ResultStr +=
"__Block_byref_" + Name +
3262 "_" + utostr(BlockByRefDeclNo[VD]) ;
3265 static bool HasLocalVariableExternalStorage(
ValueDecl *VD) {
3266 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3267 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3271 std::string RewriteObjC::SynthesizeBlockFunc(
BlockExpr *CE,
int i,
3276 std::string StructRef =
"struct " + Tag;
3278 funcName.str() +
"_" +
"block_func_" + utostr(i);
3282 if (isa<FunctionNoProtoType>(AFT)) {
3285 S +=
"(" + StructRef +
" *__cself)";
3287 S +=
"(" + StructRef +
" *__cself)";
3290 assert(FT &&
"SynthesizeBlockFunc: No function proto");
3293 S += StructRef +
" *__cself, ";
3294 std::string ParamStr;
3298 ParamStr = (*AI)->getNameAsString();
3300 (void)convertBlockPointerToFunctionPointer(QT);
3314 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
3315 E = BlockByRefDecls.end(); I != E; ++I) {
3317 std::string Name = (*I)->getNameAsString();
3318 std::string TypeString;
3319 RewriteByRefString(TypeString, Name, (*I));
3321 Name = TypeString + Name;
3322 S += Name +
" = __cself->" + (*I)->getNameAsString() +
"; // bound by ref\n";
3325 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
3326 E = BlockByCopyDecls.end(); I != E; ++I) {
3338 if (isTopLevelBlockPointerType((*I)->getType())) {
3339 RewriteBlockPointerTypeVariable(S, (*I));
3341 RewriteBlockPointerType(S, (*I)->getType());
3343 S +=
"__cself->" + (*I)->getNameAsString() +
"; // bound by copy\n";
3346 std::string Name = (*I)->getNameAsString();
3348 if (HasLocalVariableExternalStorage(*I))
3351 S += Name +
" = __cself->" +
3352 (*I)->getNameAsString() +
"; // bound by copy\n";
3355 std::string RewrittenStr = RewrittenBlockExprs[CE];
3356 const char *cstr = RewrittenStr.c_str();
3357 while (*cstr++ !=
'{') ;
3363 std::string RewriteObjC::SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
3366 std::string StructRef =
"struct " + Tag;
3367 std::string S =
"static void __";
3370 S +=
"_block_copy_" + utostr(i);
3371 S +=
"(" + StructRef;
3372 S +=
"*dst, " + StructRef;
3374 for (
ValueDecl *VD : ImportedBlockDecls) {
3375 S +=
"_Block_object_assign((void*)&dst->";
3377 S +=
", (void*)src->";
3379 if (BlockByRefDeclsPtrSet.count(VD))
3388 S +=
"\nstatic void __";
3390 S +=
"_block_dispose_" + utostr(i);
3391 S +=
"(" + StructRef;
3393 for (
ValueDecl *VD : ImportedBlockDecls) {
3394 S +=
"_Block_object_dispose((void*)src->";
3396 if (BlockByRefDeclsPtrSet.count(VD))
3407 std::string RewriteObjC::SynthesizeBlockImpl(
BlockExpr *CE, std::string Tag,
3409 std::string S =
"\nstruct " + Tag;
3410 std::string Constructor =
" " + Tag;
3412 S +=
" {\n struct __block_impl impl;\n";
3413 S +=
" struct " + Desc;
3416 Constructor +=
"(void *fp, ";
3417 Constructor +=
"struct " + Desc;
3418 Constructor +=
" *desc";
3420 if (BlockDeclRefs.size()) {
3422 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
3423 E = BlockByCopyDecls.end(); I != E; ++I) {
3425 std::string FieldName = (*I)->getNameAsString();
3426 std::string ArgName =
"_" + FieldName;
3437 if (isTopLevelBlockPointerType((*I)->getType())) {
3438 S +=
"struct __block_impl *";
3439 Constructor +=
", void *" + ArgName;
3442 if (HasLocalVariableExternalStorage(*I))
3446 Constructor +=
", " + ArgName;
3448 S += FieldName +
";\n";
3451 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
3452 E = BlockByRefDecls.end(); I != E; ++I) {
3454 std::string FieldName = (*I)->getNameAsString();
3455 std::string ArgName =
"_" + FieldName;
3457 std::string TypeString;
3458 RewriteByRefString(TypeString, FieldName, (*I));
3460 FieldName = TypeString + FieldName;
3461 ArgName = TypeString + ArgName;
3462 Constructor +=
", " + ArgName;
3464 S += FieldName +
"; // by ref\n";
3467 Constructor +=
", int flags=0)";
3469 bool firsTime =
true;
3470 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
3471 E = BlockByCopyDecls.end(); I != E; ++I) {
3472 std::string Name = (*I)->getNameAsString();
3474 Constructor +=
" : ";
3478 Constructor +=
", ";
3479 if (isTopLevelBlockPointerType((*I)->getType()))
3480 Constructor += Name +
"((struct __block_impl *)_" + Name +
")";
3482 Constructor += Name +
"(_" + Name +
")";
3485 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
3486 E = BlockByRefDecls.end(); I != E; ++I) {
3487 std::string Name = (*I)->getNameAsString();
3489 Constructor +=
" : ";
3493 Constructor +=
", ";
3494 Constructor += Name +
"(_" + Name +
"->__forwarding)";
3497 Constructor +=
" {\n";
3499 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3501 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3502 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3504 Constructor +=
" Desc = desc;\n";
3507 Constructor +=
", int flags=0) {\n";
3509 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3511 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3512 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3513 Constructor +=
" Desc = desc;\n";
3516 Constructor +=
"}\n";
3522 std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
3523 std::string ImplTag,
int i,
3526 std::string S =
"\nstatic struct " + DescTag;
3528 S +=
" {\n unsigned long reserved;\n";
3529 S +=
" unsigned long Block_size;\n";
3531 S +=
" void (*copy)(struct ";
3532 S += ImplTag; S +=
"*, struct ";
3533 S += ImplTag; S +=
"*);\n";
3535 S +=
" void (*dispose)(struct ";
3536 S += ImplTag; S +=
"*);\n";
3540 S += DescTag +
"_DATA = { 0, sizeof(struct ";
3543 S +=
", __" + FunName.str() +
"_block_copy_" + utostr(i);
3544 S +=
", __" + FunName.str() +
"_block_dispose_" + utostr(i);
3550 void RewriteObjC::SynthesizeBlockLiterals(
SourceLocation FunLocStart,
3551 StringRef FunName) {
3553 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3554 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3555 bool RewriteSC = (GlobalVarDecl &&
3557 GlobalVarDecl->getStorageClass() ==
SC_Static &&
3558 GlobalVarDecl->getType().getCVRQualifiers());
3560 std::string SC(
" void __");
3561 SC += GlobalVarDecl->getNameAsString();
3563 InsertText(FunLocStart, SC);
3567 for (
unsigned i = 0, count=0; i < Blocks.size(); i++) {
3568 CollectBlockDeclRefInfo(Blocks[i]);
3571 for (
int j = 0; j < InnerDeclRefsCount[i]; j++) {
3574 BlockDeclRefs.push_back(Exp);
3575 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
3576 BlockByCopyDeclsPtrSet.insert(VD);
3577 BlockByCopyDecls.push_back(VD);
3579 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
3580 BlockByRefDeclsPtrSet.insert(VD);
3581 BlockByRefDecls.push_back(VD);
3585 if (VD->
hasAttr<BlocksAttr>() ||
3588 ImportedBlockDecls.insert(VD);
3591 std::string ImplTag =
"__" + FunName.str() +
"_block_impl_" + utostr(i);
3592 std::string DescTag =
"__" + FunName.str() +
"_block_desc_" + utostr(i);
3594 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3596 InsertText(FunLocStart, CI);
3598 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3600 InsertText(FunLocStart, CF);
3602 if (ImportedBlockDecls.size()) {
3603 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3604 InsertText(FunLocStart, HF);
3606 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3607 ImportedBlockDecls.size() > 0);
3608 InsertText(FunLocStart, BD);
3610 BlockDeclRefs.clear();
3611 BlockByRefDecls.clear();
3612 BlockByRefDeclsPtrSet.clear();
3613 BlockByCopyDecls.clear();
3614 BlockByCopyDeclsPtrSet.clear();
3615 ImportedBlockDecls.clear();
3621 if (GlobalVarDecl->getStorageClass() ==
SC_Static)
3623 if (GlobalVarDecl->getType().isConstQualified())
3625 if (GlobalVarDecl->getType().isVolatileQualified())
3627 if (GlobalVarDecl->getType().isRestrictQualified())
3629 InsertText(FunLocStart, SC);
3633 InnerDeclRefsCount.clear();
3634 InnerDeclRefs.clear();
3635 RewrittenBlockExprs.clear();
3638 void RewriteObjC::InsertBlockLiteralsWithinFunction(
FunctionDecl *FD) {
3640 StringRef FuncName = FD->
getName();
3642 SynthesizeBlockLiterals(FunLocStart, FuncName);
3645 static void BuildUniqueMethodName(std::string &Name,
3651 std::string::size_type loc = 0;
3652 while ((loc = Name.find(
":", loc)) != std::string::npos)
3653 Name.replace(loc, 1,
"_");
3656 void RewriteObjC::InsertBlockLiteralsWithinMethod(
ObjCMethodDecl *MD) {
3660 std::string FuncName;
3661 BuildUniqueMethodName(FuncName, MD);
3662 SynthesizeBlockLiterals(FunLocStart, FuncName);
3665 void RewriteObjC::GetBlockDeclRefExprs(
Stmt *S) {
3666 for (
Stmt *SubStmt : S->children())
3668 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
3669 GetBlockDeclRefExprs(CBE->getBody());
3671 GetBlockDeclRefExprs(SubStmt);
3676 HasLocalVariableExternalStorage(DRE->
getDecl()))
3678 BlockDeclRefs.push_back(DRE);
3683 void RewriteObjC::GetInnerBlockDeclRefExprs(
Stmt *S,
3684 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
3685 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
3686 for (
Stmt *SubStmt : S->children())
3688 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
3689 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
3690 GetInnerBlockDeclRefExprs(CBE->getBody(),
3695 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
3698 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3700 HasLocalVariableExternalStorage(DRE->
getDecl())) {
3702 InnerBlockDeclRefs.push_back(DRE);
3704 if (Var->isFunctionOrMethodVarDecl())
3705 ImportedLocalExternalDecls.insert(Var);
3720 SmallVector<QualType, 8> ArgTypes;
3722 bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
3728 if (convertBlockPointerToFunctionPointer(t))
3729 HasBlockType =
true;
3730 ArgTypes.push_back(t);
3737 FuncType = getSimpleFunctionType(Res, ArgTypes);
3742 Stmt *RewriteObjC::SynthesizeBlockCall(
CallExpr *Exp,
const Expr *BlockExp) {
3746 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3748 }
else if (
const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3751 else if (
const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3752 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3754 else if (
const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3757 dyn_cast<ConditionalOperator>(BlockExp)) {
3758 Expr *LHSExp = CEXPR->getLHS();
3759 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3760 Expr *RHSExp = CEXPR->getRHS();
3761 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3762 Expr *CONDExp = CEXPR->getCond();
3769 }
else if (
const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3772 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
3775 assert(1 &&
"RewriteBlockClass: Bad type");
3777 assert(CPT &&
"RewriteBlockClass: Bad type");
3779 assert(FT &&
"RewriteBlockClass: Bad type");
3789 SmallVector<QualType, 8> ArgTypes;
3792 ArgTypes.push_back(PtrBlock);
3797 if (!convertBlockPointerToFunctionPointer(t))
3798 convertToUnqualifiedObjCType(t);
3799 ArgTypes.push_back(t);
3803 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->
getType(), ArgTypes);
3809 const_cast<Expr*>(BlockExp));
3825 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(
Context, PtrToFuncCastType,
3829 SmallVector<Expr*, 8> BlkExprs;
3831 BlkExprs.push_back(BlkCast);
3834 E = Exp->
arg_end(); I != E; ++I) {
3835 BlkExprs.push_back(*I);
3861 HasLocalVariableExternalStorage(DeclRefExp->
getDecl());
3873 StringRef Name = VD->
getName();
3887 ReplaceStmt(DeclRefExp, PE);
3894 Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(
DeclRefExpr *DRE) {
3896 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3897 if (!ImportedLocalExternalDecls.count(Var))
3905 ReplaceStmt(DRE, PE);
3917 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
3923 const Type* TypePtr = QT->
getAs<Type>();
3924 if (isa<TypeOfExprType>(TypePtr)) {
3925 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
3927 std::string TypeAsString =
"(";
3928 RewriteBlockPointerType(TypeAsString, QT);
3929 TypeAsString +=
")";
3930 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
3934 const char *argPtr = startBuf;
3936 while (*argPtr++ && (argPtr < endBuf)) {
3941 ReplaceText(LocStart, 1,
"*");
3948 void RewriteObjC::RewriteBlockPointerFunctionArgs(
FunctionDecl *FD) {
3950 unsigned parenCount = 0;
3954 const char *startArgList = strchr(startBuf,
'(');
3956 assert((*startArgList ==
'(') &&
"Rewriter fuzzy parser confused");
3961 assert((DeclLoc.
isValid()) &&
"Invalid DeclLoc");
3963 const char *argPtr = startArgList;
3965 while (*argPtr++ && parenCount) {
3970 ReplaceText(DeclLoc, 1,
"*");
3983 bool RewriteObjC::PointerTypeTakesAnyBlockArguments(
QualType QT) {
3990 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3995 if (isTopLevelBlockPointerType(I))
4001 bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(
QualType QT) {
4008 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
4013 if (I->isObjCQualifiedIdType())
4015 if (I->isObjCObjectPointerType() &&
4016 I->getPointeeType()->isObjCQualifiedInterfaceType())
4024 void RewriteObjC::GetExtentOfArgList(
const char *Name,
const char *&LParen,
4025 const char *&RParen) {
4026 const char *argPtr = strchr(Name,
'(');
4027 assert((*argPtr ==
'(') &&
"Rewriter fuzzy parser confused");
4031 unsigned parenCount = 1;
4033 while (*argPtr && parenCount) {
4035 case '(': parenCount++;
break;
4036 case ')': parenCount--;
break;
4039 if (parenCount) argPtr++;
4041 assert((*argPtr ==
')') &&
"Rewriter fuzzy parser confused");
4045 void RewriteObjC::RewriteBlockPointerDecl(
NamedDecl *ND) {
4047 RewriteBlockPointerFunctionArgs(FD);
4053 if (
VarDecl *VD = dyn_cast<VarDecl>(ND))
4056 DeclT = TDD->getUnderlyingType();
4057 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4060 llvm_unreachable(
"RewriteBlockPointerDecl(): Decl type not yet handled");
4063 const char *endBuf = startBuf;
4065 while (*startBuf !=
'^' && *startBuf !=
';' && startBuf != MainFileStart)
4069 unsigned OrigLength=0;
4072 if (*startBuf ==
'^') {
4078 while (*startBuf !=
')') {
4086 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4087 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4092 const char *argListBegin, *argListEnd;
4093 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4094 while (argListBegin < argListEnd) {
4095 if (*argListBegin ==
'^')
4097 else if (*argListBegin ==
'<') {
4099 buf += *argListBegin++;
4101 while (*argListBegin !=
'>') {
4102 buf += *argListBegin++;
4105 buf += *argListBegin;
4109 buf += *argListBegin;
4116 ReplaceText(Start, OrigLength, buf);
4142 std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
4145 if (CopyDestroyCache.count(flag))
4147 CopyDestroyCache.insert(flag);
4148 S =
"static void __Block_byref_id_object_copy_";
4150 S +=
"(void *dst, void *src) {\n";
4156 unsigned VoidPtrSize =
4160 S +=
" _Block_object_assign((char*)dst + ";
4161 S += utostr(offset);
4162 S +=
", *(void * *) ((char*)src + ";
4163 S += utostr(offset);
4168 S +=
"static void __Block_byref_id_object_dispose_";
4170 S +=
"(void *src) {\n";
4171 S +=
" _Block_object_dispose(*(void * *) ((char*)src + ";
4172 S += utostr(offset);
4197 void RewriteObjC::RewriteByRefVar(
VarDecl *ND) {
4200 if (CurFunctionDeclToDeclareForBlock)
4201 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4214 std::string ByrefType;
4215 RewriteByRefString(ByrefType, Name, ND,
true);
4216 ByrefType +=
" {\n";
4217 ByrefType +=
" void *__isa;\n";
4218 RewriteByRefString(ByrefType, Name, ND);
4219 ByrefType +=
" *__forwarding;\n";
4220 ByrefType +=
" int __flags;\n";
4221 ByrefType +=
" int __size;\n";
4226 if (HasCopyAndDispose) {
4227 ByrefType +=
" void (*__Block_byref_id_object_copy)(void*, void*);\n";
4228 ByrefType +=
" void (*__Block_byref_id_object_dispose)(void*);\n";
4232 (void)convertBlockPointerToFunctionPointer(T);
4235 ByrefType +=
" " + Name +
";\n";
4236 ByrefType +=
"};\n";
4240 FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
4242 assert(CurMethodDef &&
"RewriteByRefVar - CurMethodDef is null");
4243 FunLocStart = CurMethodDef->getLocStart();
4245 InsertText(FunLocStart, ByrefType);
4251 if (HasCopyAndDispose) {
4259 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4261 InsertText(FunLocStart, HF);
4267 bool hasInit = (ND->
getInit() !=
nullptr);
4269 if (HasCopyAndDispose)
4273 RewriteByRefString(ByrefType, Name, ND);
4274 std::string ForwardingCastType(
"(");
4275 ForwardingCastType += ByrefType +
" *)";
4277 ByrefType +=
" " + Name +
" = {(void*)";
4278 ByrefType += utostr(isa);
4279 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4280 ByrefType += utostr(flags);
4282 ByrefType +=
"sizeof(";
4283 RewriteByRefString(ByrefType, Name, ND);
4285 if (HasCopyAndDispose) {
4286 ByrefType +=
", __Block_byref_id_object_copy_";
4287 ByrefType += utostr(flag);
4288 ByrefType +=
", __Block_byref_id_object_dispose_";
4289 ByrefType += utostr(flag);
4291 ByrefType +=
"};\n";
4292 unsigned nameSize = Name.size();
4297 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4303 startLoc = ECE->getLParenLoc();
4305 startLoc = E->getLocStart();
4308 ByrefType +=
" " + Name;
4309 ByrefType +=
" = {(void*)";
4310 ByrefType += utostr(isa);
4311 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4312 ByrefType += utostr(flags);
4314 ByrefType +=
"sizeof(";
4315 RewriteByRefString(ByrefType, Name, ND);
4317 if (HasCopyAndDispose) {
4318 ByrefType +=
"__Block_byref_id_object_copy_";
4319 ByrefType += utostr(flag);
4320 ByrefType +=
", __Block_byref_id_object_dispose_";
4321 ByrefType += utostr(flag);
4324 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4335 const char *semiBuf = strchr(startInitializerBuf,
';');
4336 assert((*semiBuf ==
';') &&
"RewriteByRefVar: can't find ';'");
4340 InsertText(semiLoc,
"}");
4345 void RewriteObjC::CollectBlockDeclRefInfo(
BlockExpr *Exp) {
4347 GetBlockDeclRefExprs(Exp->
getBody());
4348 if (BlockDeclRefs.size()) {
4350 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4351 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4352 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4353 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4354 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
4358 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4359 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4360 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4361 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4362 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
4366 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4367 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4368 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4369 BlockDeclRefs[i]->getType()->isBlockPointerType())
4370 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4374 FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
4383 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {
4385 Blocks.push_back(Exp);
4387 CollectBlockDeclRefInfo(Exp);
4390 int countOfInnerDecls = 0;
4391 if (!InnerBlockDeclRefs.empty()) {
4392 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
4395 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
4399 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4400 BlockDeclRefs.push_back(Exp);
4401 BlockByCopyDeclsPtrSet.insert(VD);
4402 BlockByCopyDecls.push_back(VD);
4404 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
4405 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4406 BlockDeclRefs.push_back(Exp);
4407 BlockByRefDeclsPtrSet.insert(VD);
4408 BlockByRefDecls.push_back(VD);
4412 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
4413 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4414 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4415 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
4416 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4418 InnerDeclRefsCount.push_back(countOfInnerDecls);
4420 std::string FuncName;
4424 else if (CurMethodDef)
4425 BuildUniqueMethodName(FuncName, CurMethodDef);
4426 else if (GlobalVarDecl)
4427 FuncName = std::string(GlobalVarDecl->getNameAsString());
4429 std::string BlockNumber = utostr(Blocks.size()-1);
4431 std::string Tag =
"__" + FuncName +
"_block_impl_" + BlockNumber;
4432 std::string Func =
"__" + FuncName +
"_block_func_" + BlockNumber;
4435 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
4442 FD = SynthBlockInitFunctionDecl(Tag);
4446 SmallVector<Expr*, 4> InitExprs;
4449 FD = SynthBlockInitFunctionDecl(Func);
4454 InitExprs.push_back(castExpr);
4457 std::string DescData =
"__" + FuncName +
"_block_desc_" + BlockNumber +
"_DATA";
4473 InitExprs.push_back(DescRefExpr);
4476 if (BlockDeclRefs.size()) {
4479 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
4480 E = BlockByCopyDecls.end(); I != E; ++I) {
4481 if (isObjCType((*I)->getType())) {
4483 FD = SynthBlockInitFunctionDecl((*I)->getName());
4486 if (HasLocalVariableExternalStorage(*I)) {
4492 }
else if (isTopLevelBlockPointerType((*I)->getType())) {
4493 FD = SynthBlockInitFunctionDecl((*I)->getName());
4499 FD = SynthBlockInitFunctionDecl((*I)->getName());
4502 if (HasLocalVariableExternalStorage(*I)) {
4510 InitExprs.push_back(Exp);
4513 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
4514 E = BlockByRefDecls.end(); I != E; ++I) {
4517 std::string RecName;
4518 RewriteByRefString(RecName, Name, ND,
true);
4520 +
sizeof(
"struct"));
4524 assert(RD &&
"SynthBlockInitExpr(): Can't find RecordDecl");
4527 FD = SynthBlockInitFunctionDecl((*I)->getName());
4530 bool isNestedCapturedVar =
false;
4532 for (
const auto &CI : block->
captures()) {
4533 const VarDecl *variable = CI.getVariable();
4534 if (variable == ND && CI.isNested()) {
4535 assert (CI.isByRef() &&
4536 "SynthBlockInitExpr - captured block variable is not byref");
4537 isNestedCapturedVar =
true;
4543 if (!isNestedCapturedVar)
4548 InitExprs.push_back(Exp);
4551 if (ImportedBlockDecls.size()) {
4558 InitExprs.push_back(FlagExp);
4567 BlockDeclRefs.clear();
4568 BlockByRefDecls.clear();
4569 BlockByRefDeclsPtrSet.clear();
4570 BlockByCopyDecls.clear();
4571 BlockByCopyDeclsPtrSet.clear();
4572 ImportedBlockDecls.clear();
4576 bool RewriteObjC::IsDeclStmtInForeachHeader(
DeclStmt *DS) {
4578 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4579 return CS->getElement() == DS;
4587 Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(
Stmt *S) {
4588 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4589 isa<DoStmt>(S) || isa<ForStmt>(S))
4591 else if (isa<ObjCForCollectionStmt>(S)) {
4593 ObjCBcLabelNo.push_back(++BcLabelCount);
4600 return RewritePropertyOrImplicitSetter(PseudoOp);
4602 return RewritePropertyOrImplicitGetter(PseudoOp);
4604 }
else if (
ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4605 return RewriteObjCIvarRefExpr(IvarRefExpr);
4611 for (
Stmt *&childStmt : S->children())
4613 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4615 childStmt = newStmt;
4619 if (
BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
4620 SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;
4621 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
4622 InnerContexts.insert(BE->getBlockDecl());
4623 ImportedLocalExternalDecls.clear();
4624 GetInnerBlockDeclRefExprs(BE->getBody(),
4625 InnerBlockDeclRefs, InnerContexts);
4627 Stmt *SaveCurrentBody = CurrentBody;
4628 CurrentBody = BE->getBody();
4629 PropParentMap =
nullptr;
4635 bool saveDisableReplaceStmt = DisableReplaceStmt;
4636 DisableReplaceStmt =
false;
4637 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4638 DisableReplaceStmt = saveDisableReplaceStmt;
4639 CurrentBody = SaveCurrentBody;
4640 PropParentMap =
nullptr;
4641 ImportedLocalExternalDecls.clear();
4643 std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
4644 RewrittenBlockExprs[BE] = Str;
4646 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4649 ReplaceStmt(S, blockTranscribed);
4650 return blockTranscribed;
4654 return RewriteAtEncode(AtEncode);
4657 return RewriteAtSelector(AtSelector);
4660 return RewriteObjCStringLiteral(AtString);
4671 std::string messString;
4672 messString +=
"// ";
4673 messString.append(startBuf, endBuf-startBuf+1);
4682 return RewriteMessageExpr(MessExpr);
4686 return RewriteObjCTryStmt(StmtTry);
4689 return RewriteObjCSynchronizedStmt(StmtTry);
4692 return RewriteObjCThrowStmt(StmtThrow);
4695 return RewriteObjCProtocolExpr(ProtocolExp);
4698 dyn_cast<ObjCForCollectionStmt>(S))
4699 return RewriteObjCForCollectionStmt(StmtForCollection,
4702 dyn_cast<BreakStmt>(S))
4703 return RewriteBreakStmt(StmtBreakStmt);
4705 dyn_cast<ContinueStmt>(S))
4706 return RewriteContinueStmt(StmtContinueStmt);
4710 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4720 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4721 RewriteObjCQualifiedInterfaceTypes(*DS->
decl_begin());
4724 for (
auto *SD : DS->
decls()) {
4725 if (
ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4726 if (isTopLevelBlockPointerType(ND->
getType()))
4727 RewriteBlockPointerDecl(ND);
4729 CheckFunctionPointerDecl(ND->
getType(), ND);
4730 if (
VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4731 if (VD->
hasAttr<BlocksAttr>()) {
4732 static unsigned uniqueByrefDeclCount = 0;
4733 assert(!BlockByRefDeclNo.count(ND) &&
4734 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4735 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4736 RewriteByRefVar(VD);
4739 RewriteTypeOfDecl(VD);
4743 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4744 RewriteBlockPointerDecl(TD);
4745 else if (TD->getUnderlyingType()->isFunctionPointerType())
4746 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4752 RewriteObjCQualifiedInterfaceTypes(CE);
4754 if (isa<SwitchStmt>(S) || isa<WhileStmt>(
S) ||
4755 isa<DoStmt>(S) || isa<ForStmt>(
S)) {
4756 assert(!Stmts.empty() &&
"Statement stack is empty");
4757 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
4758 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
4759 &&
"Statement stack mismatch");
4763 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4765 if (VD->
hasAttr<BlocksAttr>())
4766 return RewriteBlockDeclRefExpr(DRE);
4767 if (HasLocalVariableExternalStorage(VD))
4768 return RewriteLocalVariableExternalStorage(DRE);
4771 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
4774 ReplaceStmt(S, BlockCall);
4779 RewriteCastExpr(CE);
4788 llvm::raw_string_ostream Buf(SStr);
4789 Replacement->printPretty(Buf);
4790 const std::string &Str = Buf.str();
4792 printf(
"CAST = %s\n", &Str[0]);
4793 InsertText(ICE->
getSubExpr()->getLocStart(), &Str[0], Str.size());
4802 void RewriteObjC::RewriteRecordBody(
RecordDecl *RD) {
4803 for (
auto *FD : RD->
fields()) {
4804 if (isTopLevelBlockPointerType(FD->
getType()))
4805 RewriteBlockPointerDecl(FD);
4808 RewriteObjCQualifiedInterfaceTypes(FD);
4814 void RewriteObjC::HandleDeclInMainFile(
Decl *D) {
4816 case Decl::Function: {
4824 RewriteBlocksInFunctionProtoType(FD->
getType(), FD);
4831 CurFunctionDef = FD;
4832 CurFunctionDeclToDeclareForBlock = FD;
4835 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4837 CurrentBody =
nullptr;
4838 if (PropParentMap) {
4839 delete PropParentMap;
4840 PropParentMap =
nullptr;
4844 InsertBlockLiteralsWithinFunction(FD);
4845 CurFunctionDef =
nullptr;
4846 CurFunctionDeclToDeclareForBlock =
nullptr;
4850 case Decl::ObjCMethod: {
4856 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4858 CurrentBody =
nullptr;
4859 if (PropParentMap) {
4860 delete PropParentMap;
4861 PropParentMap =
nullptr;
4863 InsertBlockLiteralsWithinMethod(MD);
4864 CurMethodDef =
nullptr;
4868 case Decl::ObjCImplementation: {
4870 ClassImplementation.push_back(CI);
4873 case Decl::ObjCCategoryImpl: {
4875 CategoryImplementation.push_back(CI);
4879 VarDecl *VD = cast<VarDecl>(D);
4880 RewriteObjCQualifiedInterfaceTypes(VD);
4881 if (isTopLevelBlockPointerType(VD->
getType()))
4882 RewriteBlockPointerDecl(VD);
4884 CheckFunctionPointerDecl(VD->
getType(), VD);
4887 RewriteCastExpr(CE);
4893 RewriteRecordBody(RD);
4898 RewriteFunctionBodyOrGlobalInitializer(VD->
getInit());
4899 CurrentBody =
nullptr;
4900 if (PropParentMap) {
4901 delete PropParentMap;
4902 PropParentMap =
nullptr;
4905 GlobalVarDecl =
nullptr;
4909 RewriteCastExpr(CE);
4914 case Decl::TypeAlias:
4915 case Decl::Typedef: {
4917 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4918 RewriteBlockPointerDecl(TD);
4919 else if (TD->getUnderlyingType()->isFunctionPointerType())
4920 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4924 case Decl::CXXRecord:
4925 case Decl::Record: {
4928 RewriteRecordBody(RD);
4937 void RewriteObjC::HandleTranslationUnit(
ASTContext &
C) {
4938 if (Diags.hasErrorOccurred())
4946 RewriteObjCProtocolMetaData(ProtDecl,
"",
"", Preamble);
4949 if (ClassImplementation.size() || CategoryImplementation.size())
4950 RewriteImplementations();
4955 Rewrite.getRewriteBufferFor(MainFileID)) {
4957 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
4959 llvm::errs() <<
"No changes\n";
4962 if (ClassImplementation.size() || CategoryImplementation.size() ||
4963 ProtocolExprDecls.size()) {
4965 std::string ResultStr;
4966 RewriteMetaDataIntoBuffer(ResultStr);
4968 *OutFile << ResultStr;
4973 void RewriteObjCFragileABI::Initialize(
ASTContext &context) {
4974 InitializeCommon(context);
4979 Preamble =
"#pragma once\n";
4980 Preamble +=
"struct objc_selector; struct objc_class;\n";
4981 Preamble +=
"struct __rw_objc_super { struct objc_object *object; ";
4982 Preamble +=
"struct objc_object *superClass; ";
4983 if (LangOpts.MicrosoftExt) {
4985 Preamble +=
"__rw_objc_super(struct objc_object *o, struct objc_object *s) "
4987 Preamble +=
"object(o), superClass(s) {} ";
4990 Preamble +=
"#ifndef _REWRITER_typedef_Protocol\n";
4991 Preamble +=
"typedef struct objc_object Protocol;\n";
4992 Preamble +=
"#define _REWRITER_typedef_Protocol\n";
4993 Preamble +=
"#endif\n";
4994 if (LangOpts.MicrosoftExt) {
4995 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
4996 Preamble +=
"#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
4998 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern\n";
4999 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
5000 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
5001 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
5002 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
5003 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
5004 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
5005 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
5006 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
5007 Preamble +=
"__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
5008 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
5009 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
5010 Preamble +=
"(const char *);\n";
5011 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
5012 Preamble +=
"(struct objc_class *);\n";
5013 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
5014 Preamble +=
"(const char *);\n";
5015 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
5016 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
5017 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
5018 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
5019 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_exception_match";
5020 Preamble +=
"(struct objc_class *, struct objc_object *);\n";
5022 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
5023 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
5024 Preamble +=
"__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
5025 Preamble +=
"#ifndef __FASTENUMERATIONSTATE\n";
5026 Preamble +=
"struct __objcFastEnumerationState {\n\t";
5027 Preamble +=
"unsigned long state;\n\t";
5028 Preamble +=
"void **itemsPtr;\n\t";
5029 Preamble +=
"unsigned long *mutationsPtr;\n\t";
5030 Preamble +=
"unsigned long extra[5];\n};\n";
5031 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
5032 Preamble +=
"#define __FASTENUMERATIONSTATE\n";
5033 Preamble +=
"#endif\n";
5034 Preamble +=
"#ifndef __NSCONSTANTSTRINGIMPL\n";
5035 Preamble +=
"struct __NSConstantStringImpl {\n";
5036 Preamble +=
" int *isa;\n";
5037 Preamble +=
" int flags;\n";
5038 Preamble +=
" char *str;\n";
5039 Preamble +=
" long length;\n";
5041 Preamble +=
"#ifdef CF_EXPORT_CONSTANT_STRING\n";
5042 Preamble +=
"extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5043 Preamble +=
"#else\n";
5044 Preamble +=
"__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5045 Preamble +=
"#endif\n";
5046 Preamble +=
"#define __NSCONSTANTSTRINGIMPL\n";
5047 Preamble +=
"#endif\n";
5049 Preamble +=
"#ifndef BLOCK_IMPL\n";
5050 Preamble +=
"#define BLOCK_IMPL\n";
5051 Preamble +=
"struct __block_impl {\n";
5052 Preamble +=
" void *isa;\n";
5053 Preamble +=
" int Flags;\n";
5054 Preamble +=
" int Reserved;\n";
5055 Preamble +=
" void *FuncPtr;\n";
5057 Preamble +=
"// Runtime copy/destroy helper functions (from Block_private.h)\n";
5058 Preamble +=
"#ifdef __OBJC_EXPORT_BLOCKS\n";
5059 Preamble +=
"extern \"C\" __declspec(dllexport) "
5060 "void _Block_object_assign(void *, const void *, const int);\n";
5061 Preamble +=
"extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5062 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5063 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5064 Preamble +=
"#else\n";
5065 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5066 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5067 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5068 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5069 Preamble +=
"#endif\n";
5070 Preamble +=
"#endif\n";
5071 if (LangOpts.MicrosoftExt) {
5072 Preamble +=
"#undef __OBJC_RW_DLLIMPORT\n";
5073 Preamble +=
"#undef __OBJC_RW_STATICIMPORT\n";
5074 Preamble +=
"#ifndef KEEP_ATTRIBUTES\n";
5075 Preamble +=
"#define __attribute__(X)\n";
5076 Preamble +=
"#endif\n";
5077 Preamble +=
"#define __weak\n";
5080 Preamble +=
"#define __block\n";
5081 Preamble +=
"#define __weak\n";
5085 Preamble +=
"\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5090 void RewriteObjCFragileABI::RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
5091 std::string &Result) {
5097 Result +=
"__OFFSETOFIVAR__(struct ";
5099 if (LangOpts.MicrosoftExt)
5108 void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
5110 StringRef ClassName, std::string &Result) {
5111 static bool objc_protocol_methods =
false;
5120 Result +=
"\nstruct _protocol_methods {\n";
5121 Result +=
"\tstruct objc_selector *_cmd;\n";
5122 Result +=
"\tchar *method_types;\n";
5125 objc_protocol_methods =
true;
5142 Result +=
"\nstatic struct {\n";
5143 Result +=
"\tint protocol_method_count;\n";
5144 Result +=
"\tstruct _protocol_methods protocol_methods[";
5145 Result += utostr(NumMethods);
5146 Result +=
"];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
5148 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
5149 "{\n\t" + utostr(NumMethods) +
"\n";
5152 for (ObjCProtocolDecl::instmeth_iterator
5156 Result +=
"\t ,{{(struct objc_selector *)\"";
5158 Result +=
"\t ,{(struct objc_selector *)\"";
5159 Result += (*I)->getSelector().getAsString();
5160 std::string MethodTypeString;
5163 Result += MethodTypeString;
5166 Result +=
"\t }\n};\n";
5172 if (NumMethods > 0) {
5178 Result +=
"\nstatic struct {\n";
5179 Result +=
"\tint protocol_method_count;\n";
5180 Result +=
"\tstruct _protocol_methods protocol_methods[";
5181 Result += utostr(NumMethods);
5182 Result +=
"];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
5184 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
5186 Result += utostr(NumMethods);
5190 for (ObjCProtocolDecl::classmeth_iterator
5194 Result +=
"\t ,{{(struct objc_selector *)\"";
5196 Result +=
"\t ,{(struct objc_selector *)\"";
5197 Result += (*I)->getSelector().getAsString();
5198 std::string MethodTypeString;
5201 Result += MethodTypeString;
5204 Result +=
"\t }\n};\n";
5217 static bool objc_protocol =
false;
5218 if (!objc_protocol) {
5219 Result +=
"\nstruct _objc_protocol {\n";
5220 Result +=
"\tstruct _objc_protocol_extension *isa;\n";
5221 Result +=
"\tchar *protocol_name;\n";
5222 Result +=
"\tstruct _objc_protocol **protocol_list;\n";
5223 Result +=
"\tstruct _objc_protocol_method_list *instance_methods;\n";
5224 Result +=
"\tstruct _objc_protocol_method_list *class_methods;\n";
5227 objc_protocol =
true;
5230 Result +=
"\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
5232 Result +=
" __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
5235 Result +=
"\", 0, ";
5237 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
5244 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
5254 llvm_unreachable(
"protocol already synthesized");
5258 void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
5260 StringRef prefix, StringRef ClassName,
5261 std::string &Result) {
5262 if (Protocols.
empty())
return;
5264 for (
unsigned i = 0; i != Protocols.
size(); i++)
5265 RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
5274 Result +=
"\nstatic struct {\n";
5275 Result +=
"\tstruct _objc_protocol_list *next;\n";
5276 Result +=
"\tint protocol_count;\n";
5277 Result +=
"\tstruct _objc_protocol *class_protocols[";
5278 Result += utostr(Protocols.
size());
5279 Result +=
"];\n} _OBJC_";
5281 Result +=
"_PROTOCOLS_";
5282 Result += ClassName;
5283 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
5285 Result += utostr(Protocols.
size());
5288 Result +=
"\t,{&_OBJC_PROTOCOL_";
5289 Result += Protocols[0]->getNameAsString();
5292 for (
unsigned i = 1; i != Protocols.
size(); i++) {
5293 Result +=
"\t ,&_OBJC_PROTOCOL_";
5294 Result += Protocols[i]->getNameAsString();
5297 Result +=
"\t }\n};\n";
5301 std::string &Result) {
5308 RewriteObjCInternalStruct(CDecl, Result);
5316 static bool objc_ivar =
false;
5324 Result +=
"\nstruct _objc_ivar {\n";
5325 Result +=
"\tchar *ivar_name;\n";
5326 Result +=
"\tchar *ivar_type;\n";
5327 Result +=
"\tint ivar_offset;\n";
5338 Result +=
"\nstatic struct {\n";
5339 Result +=
"\tint ivar_count;\n";
5340 Result +=
"\tstruct _objc_ivar ivar_list[";
5341 Result += utostr(NumIvars);
5342 Result +=
"];\n} _OBJC_INSTANCE_VARIABLES_";
5344 Result +=
" __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
5346 Result += utostr(NumIvars);
5350 SmallVector<ObjCIvarDecl *, 8> IVars;
5352 for (
auto *IV : IDecl->
ivars())
5353 IVars.push_back(IV);
5360 Result +=
"\t,{{\"";
5361 Result += IVI->getNameAsString();
5363 std::string TmpString, StrEncoding;
5365 QuoteDoublequotes(TmpString, StrEncoding);
5366 Result += StrEncoding;
5368 RewriteIvarOffsetComputation(*IVI, Result);
5370 for (++IVI; IVI != IVE; ++IVI) {
5371 Result +=
"\t ,{\"";
5372 Result += IVI->getNameAsString();
5374 std::string TmpString, StrEncoding;
5376 QuoteDoublequotes(TmpString, StrEncoding);
5377 Result += StrEncoding;
5379 RewriteIvarOffsetComputation(*IVI, Result);
5383 Result +=
"\t }\n};\n";
5387 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->
instance_methods());
5392 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
5394 if (!Prop->getPropertyIvarDecl())
5400 if (!Getter->isDefined())
5401 InstanceMethods.push_back(Getter);
5405 if (!Setter->isDefined())
5406 InstanceMethods.push_back(Setter);
5408 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5409 true,
"", IDecl->
getName(), Result);
5413 false,
"", IDecl->
getName(), Result);
5417 "CLASS", CDecl->
getName(), Result);
5435 static bool objc_class =
false;
5437 Result +=
"\nstruct _objc_class {\n";
5438 Result +=
"\tstruct _objc_class *isa;\n";
5439 Result +=
"\tconst char *super_class_name;\n";
5440 Result +=
"\tchar *name;\n";
5441 Result +=
"\tlong version;\n";
5442 Result +=
"\tlong info;\n";
5443 Result +=
"\tlong instance_size;\n";
5444 Result +=
"\tstruct _objc_ivar_list *ivars;\n";
5445 Result +=
"\tstruct _objc_method_list *methods;\n";
5446 Result +=
"\tstruct objc_cache *cache;\n";
5447 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5448 Result +=
"\tconst char *ivar_layout;\n";
5449 Result +=
"\tstruct _objc_class_ext *ext;\n";
5457 while (SuperClass) {
5458 RootClass = SuperClass;
5463 Result +=
"\nstatic struct _objc_class _OBJC_METACLASS_";
5465 Result +=
" __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
5466 "{\n\t(struct _objc_class *)\"";
5478 Result +=
", 0, \"";
5484 Result +=
", 0,2, sizeof(struct _objc_class), 0";
5486 Result +=
"\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
5493 Result +=
"\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
5498 Result +=
"\t,0,0,0,0\n";
5502 Result +=
"\nstatic struct _objc_class _OBJC_CLASS_";
5504 Result +=
" __attribute__ ((used, section (\"__OBJC, __class\")))= "
5505 "{\n\t&_OBJC_METACLASS_";
5515 Result +=
", 0, \"";
5521 if (!ObjCSynthesizedStructs.count(CDecl))
5525 Result +=
",sizeof(struct ";
5527 if (LangOpts.MicrosoftExt)
5532 Result +=
", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
5539 Result +=
", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
5541 Result +=
", 0\n\t";
5546 Result +=
", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
5548 Result +=
", 0,0\n";
5551 Result +=
",0,0,0\n";
5555 void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
5556 int ClsDefCount = ClassImplementation.size();
5557 int CatDefCount = CategoryImplementation.size();
5560 for (
int i = 0; i < ClsDefCount; i++)
5561 RewriteObjCClassMetaData(ClassImplementation[i], Result);
5564 for (
int i = 0; i < CatDefCount; i++)
5565 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
5579 Result +=
"\nstruct _objc_symtab {\n";
5580 Result +=
"\tlong sel_ref_cnt;\n";
5581 Result +=
"\tSEL *refs;\n";
5582 Result +=
"\tshort cls_def_cnt;\n";
5583 Result +=
"\tshort cat_def_cnt;\n";
5584 Result +=
"\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+
"];\n";
5587 Result +=
"static struct _objc_symtab "
5588 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
5589 Result +=
"\t0, 0, " + utostr(ClsDefCount)
5590 +
", " + utostr(CatDefCount) +
"\n";
5591 for (
int i = 0; i < ClsDefCount; i++) {
5592 Result +=
"\t,&_OBJC_CLASS_";
5593 Result += ClassImplementation[i]->getNameAsString();
5597 for (
int i = 0; i < CatDefCount; i++) {
5598 Result +=
"\t,&_OBJC_CATEGORY_";
5599 Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
5601 Result += CategoryImplementation[i]->getNameAsString();
5618 Result +=
"\nstruct _objc_module {\n";
5619 Result +=
"\tlong version;\n";
5620 Result +=
"\tlong size;\n";
5621 Result +=
"\tconst char *name;\n";
5622 Result +=
"\tstruct _objc_symtab *symtab;\n";
5624 Result +=
"static struct _objc_module "
5625 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
5626 Result +=
"\t" + utostr(OBJC_ABI_VERSION) +
5627 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
5630 if (LangOpts.MicrosoftExt) {
5631 if (ProtocolExprDecls.size()) {
5632 Result +=
"#pragma section(\".objc_protocol$B\",long,read,write)\n";
5633 Result +=
"#pragma data_seg(push, \".objc_protocol$B\")\n";
5635 Result +=
"static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
5636 Result += ProtDecl->getNameAsString();
5637 Result +=
" = &_OBJC_PROTOCOL_";
5638 Result += ProtDecl->getNameAsString();
5641 Result +=
"#pragma data_seg(pop)\n\n";
5643 Result +=
"#pragma section(\".objc_module_info$B\",long,read,write)\n";
5644 Result +=
"#pragma data_seg(push, \".objc_module_info$B\")\n";
5645 Result +=
"static struct _objc_module *_POINTER_OBJC_MODULES = ";
5646 Result +=
"&_OBJC_MODULES;\n";
5647 Result +=
"#pragma data_seg(pop)\n\n";
5654 std::string &Result) {
5661 FullCategoryName +=
'_';
5665 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->
instance_methods());
5670 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
5672 if (!Prop->getPropertyIvarDecl())
5678 InstanceMethods.push_back(Getter);
5682 InstanceMethods.push_back(Setter);
5684 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5685 true,
"CATEGORY_", FullCategoryName.c_str(),
5690 false,
"CATEGORY_", FullCategoryName.c_str(),
5697 FullCategoryName, Result);
5711 static bool objc_category =
false;
5712 if (!objc_category) {
5713 Result +=
"\nstruct _objc_category {\n";
5714 Result +=
"\tchar *category_name;\n";
5715 Result +=
"\tchar *class_name;\n";
5716 Result +=
"\tstruct _objc_method_list *instance_methods;\n";
5717 Result +=
"\tstruct _objc_method_list *class_methods;\n";
5718 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5719 Result +=
"\tunsigned int size;\n";
5720 Result +=
"\tstruct _objc_property_list *instance_properties;\n";
5722 objc_category =
true;
5724 Result +=
"\nstatic struct _objc_category _OBJC_CATEGORY_";
5725 Result += FullCategoryName;
5726 Result +=
" __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
5728 Result +=
"\"\n\t, \"";
5733 Result +=
"\t, (struct _objc_method_list *)"
5734 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
5735 Result += FullCategoryName;
5739 Result +=
"\t, 0\n";
5741 Result +=
"\t, (struct _objc_method_list *)"
5742 "&_OBJC_CATEGORY_CLASS_METHODS_";
5743 Result += FullCategoryName;
5747 Result +=
"\t, 0\n";
5750 Result +=
"\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
5751 Result += FullCategoryName;
5755 Result +=
"\t, 0\n";
5756 Result +=
"\t, sizeof(struct _objc_category), 0\n};\n";
5761 template<
typename MethodIterator>
5762 void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5763 MethodIterator MethodEnd,
5764 bool IsInstanceMethod,
5766 StringRef ClassName,
5767 std::string &Result) {
5768 if (MethodBegin == MethodEnd)
return;
5770 if (!objc_impl_method) {
5777 Result +=
"\nstruct _objc_method {\n";
5778 Result +=
"\tSEL _cmd;\n";
5779 Result +=
"\tchar *method_types;\n";
5780 Result +=
"\tvoid *_imp;\n";
5783 objc_impl_method =
true;
5794 unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
5795 Result +=
"\nstatic struct {\n";
5796 Result +=
"\tstruct _objc_method_list *next_method;\n";
5797 Result +=
"\tint method_count;\n";
5798 Result +=
"\tstruct _objc_method method_list[";
5799 Result += utostr(NumMethods);
5800 Result +=
"];\n} _OBJC_";
5802 Result += IsInstanceMethod ?
"INSTANCE" :
"CLASS";
5803 Result +=
"_METHODS_";
5804 Result += ClassName;
5805 Result +=
" __attribute__ ((used, section (\"__OBJC, __";
5806 Result += IsInstanceMethod ?
"inst" :
"cls";
5807 Result +=
"_meth\")))= ";
5808 Result +=
"{\n\t0, " + utostr(NumMethods) +
"\n";
5810 Result +=
"\t,{{(SEL)\"";
5811 Result += (*MethodBegin)->getSelector().getAsString().c_str();
5812 std::string MethodTypeString;
5815 Result += MethodTypeString;
5816 Result +=
"\", (void *)";
5817 Result += MethodInternalNames[*MethodBegin];
5819 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
5820 Result +=
"\t ,{(SEL)\"";
5821 Result += (*MethodBegin)->getSelector().getAsString().c_str();
5822 std::string MethodTypeString;
5825 Result += MethodTypeString;
5826 Result +=
"\", (void *)";
5827 Result += MethodInternalNames[*MethodBegin];
5830 Result +=
"\t }\n};\n";
5839 DisableReplaceStmtScope
S(*
this);
5840 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
5846 Expr *Replacement = IV;
5851 assert(iFaceDecl &&
"RewriteObjCIvarRefExpr - iFaceDecl is null");
5856 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5865 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5885 assert(!IV->
isFreeIvar() &&
"Cannot have a free standing ivar outside a method");
5896 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5899 std::string RecName = clsDeclared->getIdentifier()->getName();
5905 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5920 ReplaceStmtWithRange(IV, Replacement, OldRange);
SourceLocation getEnd() const
const Expr * getBase() const
ObjCInterfaceDecl * getDecl() const
getDecl - Get the declaration of this interface.
classmeth_iterator classmeth_end() const
StringRef getName() const
Expr * getSyntacticForm()
SourceLocation getLocStart() const LLVM_READONLY
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
ObjCInterfaceDecl * getClassInterface()
bool isBitField() const
Determines whether this field is a bitfield.
SourceLocation getLocation() const
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
IdentifierInfo * getIdentifier() const
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
Defines the SourceManager interface.
bool isRecordType() const
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
param_iterator param_end()
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
void getSelectorLocs(SmallVectorImpl< SourceLocation > &SelLocs) const
std::string getAsString() const
FullSourceLoc getFullLoc(SourceLocation Loc) const
bool isObjCQualifiedClassType() const
Represents Objective-C's @throw statement.
SourceLocation getLocStart() const LLVM_READONLY
instmeth_iterator instmeth_begin() const
const Expr * getInit() const
bool isBooleanType() const
A container of type source information.
bool isBlockPointerType() const
static StringLiteral * Create(const ASTContext &C, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumStrs)
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getLocEnd() const LLVM_READONLY
ExtProtoInfo - Extra information about a function prototype.
SourceLocation getLocStart() const LLVM_READONLY
QualType getObjCClassType() const
Represents the Objective-C Class type.
const FunctionProtoType * getFunctionType() const
getFunctionType - Return the underlying function type for this block.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Expr * IgnoreImplicit() LLVM_READONLY
Describes how types, statements, expressions, and declarations should be printed. ...
void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const
ParmVarDecl - Represents a parameter to a function.
SourceLocation getLocation() const
QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
IdentifierInfo * getIdentifier() const
SourceLocation getLocStart() const LLVM_READONLY
QualType withConst() const
Retrieves a version of this type with const applied. Note that this does not always yield a canonical...
unsigned getNumParams() const
Kind getPropertyImplementation() const
unsigned ivar_size() const
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
ObjCProtocolDecl * getProtocol() const
const ObjCInterfaceDecl * getContainingInterface() const
Return the class interface that this ivar is logically contained in; this is either the interface whe...
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getNumSemanticExprs() const
protocol_iterator protocol_begin() const
std::string getNameAsString() const
Get the name of the class associated with this interface.
bool isCompleteDefinition() const
StringLiteral * getString()
const Stmt * getBody() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super', otherwise an invalid source location.
const VarDecl * getCatchParamDecl() const
Represents Objective-C's @catch statement.
const CompoundStmt * getSynchBody() const
Describes an C or C++ initializer list.
QualType getCallResultType(ASTContext &Context) const
Determine the type of an expression that calls a function of this type.
param_type_range param_types() const
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
const LangOptions & getLangOpts() const
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
protocol_iterator protocol_end() const
QualType getReturnType() const
QualType getSuperType() const
Retrieve the type referred to by 'super'.
field_range fields() const
Concrete class used by the front-end to report problems and issues.
TypeOfExprType (GCC extension).
A builtin binary operation expression such as "x + y" or "x <= y".
Selector getSelector() const
bool isOverloadedOperator() const
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep)
Creates clause with a list of variables VL and a linear step Step.
std::string getNameAsString() const
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.
const Stmt * getCatchBody() const
CompoundStmt * getCompoundBody()
Represents an Objective-C protocol declaration.
const ObjCAtCatchStmt * getCatchStmt(unsigned I) const
Retrieve a @catch statement.
SourceLocation getLocEnd() const LLVM_READONLY
An ordinary object is located at an address in memory.
Represents an ObjC class declaration.
SourceLocation getLocEnd() const LLVM_READONLY
propimpl_range property_impls() const
Represents a linkage specification.
PropertyAttributeKind getPropertyAttributes() const
SourceLocation getAtStartLoc() const
SourceLocation getAtLoc() const
SourceRange getAtEndRange() const
bool isThisDeclarationADefinition() const
Determine whether this particular declaration is also the definition.
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getLocEnd() const LLVM_READONLY
QualType getParamType(unsigned i) const
CastKind
CastKind - The kind of operation required for a conversion.
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.
SourceLocation getTypeSpecStartLoc() const
ID
Defines the set of possible language-specific address spaces.
QualType getPointeeType() const
bool isFunctionPointerType() const
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
bool isRealFloatingType() const
Floating point categories.
const ObjCMethodDecl * getMethodDecl() const
SourceLocation getLocStart() const LLVM_READONLY
QualType getPointeeType() const
StringRef getName() const
Return the actual identifier string.
ObjCIvarDecl * getPropertyIvarDecl() const
protocol_iterator protocol_begin() const
SourceLocation getRParenLoc() const
TranslationUnitDecl * getTranslationUnitDecl() const
bool isObjCGCWeak() const
isObjCGCWeak true when Type is objc's weak.
Expr * getUnderlyingExpr() const
DeclContext * getDeclContext()
Represents Objective-C's @synchronized statement.
ObjCSelectorExpr used for @selector in Objective-C.
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
bool isWrittenInMainFile(SourceLocation Loc) const
Returns true if the spelling location for the given location is in the main file buffer.
classmeth_iterator classmeth_begin() const
Selector getSelector() const
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
ObjCIvarDecl * lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared)
bool isInstanceMethod() const
QualType getObjCIdType() const
Represents the Objective-CC id type.
An expression that sends a message to the given Objective-C object or class.
instmeth_iterator instmeth_end() const
unsigned ivar_size() const
The result type of a method or function.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
const clang::PrintingPolicy & getPrintingPolicy() const
SourceLocation getRightLoc() const
ivar_iterator ivar_begin() const
ivar_iterator ivar_begin() const
param_iterator param_begin()
Stmt * getBody(const FunctionDecl *&Definition) const
SourceLocation getLocStart() const LLVM_READONLY
ivar_iterator ivar_end() const
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
StringRef getName() const
static LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
ivar_iterator ivar_end() const
bool isValid() const
Return true if this is a valid SourceLocation object.
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.
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
TypeSourceInfo * getClassReceiverTypeInfo() const
Returns a type-source information of a class message send, or NULL if the message is not a class mess...
SourceLocation getLocStart() const LLVM_READONLY
const ObjCInterfaceDecl * getClassInterface() const
decl_iterator decl_begin()
std::string getAsString() const
Derive the full selector name (e.g. "foo:bar:") and return it as an std::string.
Represents one property declaration in an Objective-C interface.
QualType getReturnType() const
SourceLocation getBegin() const
FileID getMainFileID() const
Returns the FileID of the main source file.
const BlockDecl * getBlockDecl() const
SourceLocation getExprLoc() const LLVM_READONLY
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
QualType getPointeeType() const
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
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...
instmeth_range instance_methods() const
ObjCCategoryDecl * FindCategoryDeclaration(IdentifierInfo *CategoryId) const
SourceLocation getLParenLoc() const
unsigned getByteLength() const
prop_range properties() const
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
SourceLocation getLocStart() const LLVM_READONLY
std::string getNameAsString() const
Get the name of the class associated with this interface.
static __inline__ uint32_t volatile uint32_t * p
QualType IgnoreParens() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
std::unique_ptr< ASTConsumer > CreateObjCRewriter(const std::string &InFile, raw_ostream *OS, DiagnosticsEngine &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning)
const Expr * getSynchExpr() const
bool hasDefinition() const
Determine whether this protocol has a definition.
bool isThisDeclarationADefinition() const
Selector getSelector() const
SourceLocation getEndOfDefinitionLoc() const
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Defines the Diagnostic-related interfaces.
SourceLocation getRParenLoc() const
ObjCMethodDecl * getGetterMethodDecl() const
SourceLocation getLeftLoc() const
Represents Objective-C's collection statement.
ObjCMethodDecl * getSetterMethodDecl() const
static CStyleCastExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R)
bool isObjCQualifiedIdType() const
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
Represents Objective-C's @finally statement.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
const ObjCProtocolList & getReferencedProtocols() const
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver. ...
protocol_iterator protocol_end() const
QualType getTagDeclType(const TagDecl *Decl) const
Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl...
bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S, bool Extended=false) const
Emit the encoded type for the method declaration Decl into S.
unsigned getNumCatchStmts() const
Retrieve the number of @catch statements in this try-catch-finally block.
SourceLocation getRParenLoc() const
ObjCIvarRefExpr - A reference to an ObjC instance variable.
SourceManager & getSourceManager()
ObjCPropertyDecl * getPropertyDecl() const
classmeth_range class_methods() const
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
bool isImplicitInterfaceDecl() const
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
bool isObjCObjectPointerType() const
QualType getEncodedType() const
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation. If false, it was written explicitly in the source code.
Represents Objective-C's @try ... @catch ... @finally statement.
const Expr * getThrowExpr() const
ObjCInterfaceDecl * getSuperClass() const
const Stmt * getTryBody() const
Retrieve the @try body.
TranslationUnitDecl - The top declaration context.
A reference to a declared variable, function, enum, etc. [C99 6.5.1p2].
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
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...
Expr * getSemanticExpr(unsigned index)
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
An l-value expression is a reference to an object with independent storage.
A trivial tuple used to represent a source range.
SourceLocation getLocation() const
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
SourceLocation getLocStart() const LLVM_READONLY
bool isNull() const
isNull - Return true if this QualType doesn't point to a type yet.
const ObjCObjectPointerType * getAsObjCInterfacePointerType() const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
bool isIntegralType(ASTContext &Ctx) const
Determine whether this type is an integral type.
This class handles loading and caching of source files into memory.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool isObjCQualifiedInterfaceType() const
bool BlockRequiresCopying(QualType Ty, const VarDecl *D)
Returns true iff we need copy/dispose helpers for the given type.
const ObjCProtocolList & getReferencedProtocols() const
bool isPointerType() const