22 #include "clang/Config/config.h" 25 #include "llvm/ADT/DenseSet.h" 26 #include "llvm/ADT/SmallPtrSet.h" 27 #include "llvm/ADT/StringExtras.h" 28 #include "llvm/Support/MemoryBuffer.h" 29 #include "llvm/Support/raw_ostream.h" 32 #if CLANG_ENABLE_OBJC_REWRITER 34 using namespace clang;
54 BLOCK_NEEDS_FREE = (1 << 24),
57 BLOCK_IS_GC = (1 << 27),
59 BLOCK_HAS_DESCRIPTOR = (1 << 29)
61 static const int OBJC_ABI_VERSION = 7;
70 const char *MainFileStart, *MainFileEnd;
73 std::string InFileName;
74 std::unique_ptr<raw_ostream> OutFile;
79 unsigned RewriteFailedDiag;
81 unsigned NumObjCStringLiterals;
82 VarDecl *ConstantStringClassReference;
88 unsigned TryFinallyContainsReturnDiag;
111 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
112 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
113 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
114 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
118 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
131 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
133 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
134 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
135 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
136 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
138 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
143 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
147 bool SilenceRewriteMacroWarning;
148 bool objc_impl_method;
150 bool DisableReplaceStmt;
151 class DisableReplaceStmtScope {
157 : R(R), SavedValue(R.DisableReplaceStmt) {
158 R.DisableReplaceStmt =
true;
161 ~DisableReplaceStmtScope() {
162 R.DisableReplaceStmt = SavedValue;
173 if (!
Class->isThisDeclarationADefinition()) {
174 RewriteForwardClassDecl(D);
180 if (!Proto->isThisDeclarationADefinition()) {
181 RewriteForwardProtocolDecl(D);
186 HandleTopLevelSingleDecl(*I);
191 void HandleTopLevelSingleDecl(
Decl *D);
192 void HandleDeclInMainFile(
Decl *D);
193 RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
195 bool silenceMacroWarn);
199 void HandleTranslationUnit(
ASTContext &
C)
override;
201 void ReplaceStmt(
Stmt *Old,
Stmt *New) {
206 assert(Old !=
nullptr && New !=
nullptr &&
"Expected non-null Stmt's");
208 Stmt *ReplacingStmt = ReplacedNodes[Old];
212 if (DisableReplaceStmt)
224 llvm::raw_string_ostream S(SStr);
226 const std::string &Str = S.str();
230 ReplacedNodes[Old] = New;
233 if (SilenceRewriteMacroWarning)
240 bool InsertAfter =
true) {
242 if (!Rewrite.
InsertText(Loc, Str, InsertAfter) ||
243 SilenceRewriteMacroWarning)
252 if (!Rewrite.
ReplaceText(Start, OrigLength, Str) ||
253 SilenceRewriteMacroWarning)
261 void RewriteInclude();
265 const std::string &typedefString);
266 void RewriteImplementations();
271 void RewriteImplementationDecl(
Decl *Dcl);
274 void RewriteTypeIntoString(
QualType T, std::string &ResultStr,
276 void RewriteByRefString(std::string &ResultStr,
const std::string &Name,
285 void RewriteBlockPointerType(std::string& Str,
QualType Type);
286 void RewriteBlockPointerTypeVariable(std::string& Str,
ValueDecl *VD);
288 void RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl);
289 void RewriteTypeOfDecl(
VarDecl *VD);
290 void RewriteObjCQualifiedInterfaceTypes(
Expr *E);
293 Stmt *RewriteFunctionBodyOrGlobalInitializer(
Stmt *S);
301 void RewriteTryReturnStmts(
Stmt *S);
302 void RewriteSyncReturnStmts(
Stmt *S, std::string buf);
316 void RewriteBlockPointerDecl(
NamedDecl *VD);
317 void RewriteByRefVar(
VarDecl *VD);
325 void Initialize(
ASTContext &context)
override = 0;
328 virtual void RewriteMetaDataIntoBuffer(std::string &
Result) = 0;
344 virtual void RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
363 void SynthCountByEnumWithState(std::string &buf);
364 void SynthMsgSendFunctionDecl();
365 void SynthMsgSendSuperFunctionDecl();
366 void SynthMsgSendStretFunctionDecl();
367 void SynthMsgSendFpretFunctionDecl();
368 void SynthMsgSendSuperStretFunctionDecl();
369 void SynthGetClassFunctionDecl();
370 void SynthGetMetaClassFunctionDecl();
371 void SynthGetSuperClassFunctionDecl();
372 void SynthSelGetUidFunctionDecl();
373 void SynthSuperConstructorFunctionDecl();
375 std::string SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
int flag);
376 std::string SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
377 StringRef funcName, std::string Tag);
378 std::string SynthesizeBlockFunc(
BlockExpr *CE,
int i,
379 StringRef funcName, std::string Tag);
380 std::string SynthesizeBlockImpl(
BlockExpr *CE,
381 std::string Tag, std::string Desc);
382 std::string SynthesizeBlockDescriptor(std::string DescTag,
384 int i, StringRef funcName,
395 void WarnAboutReturnGotoStmts(
Stmt *S);
396 void HasReturnStmts(
Stmt *S,
bool &hasReturns);
398 void InsertBlockLiteralsWithinFunction(
FunctionDecl *FD);
401 bool IsDeclStmtInForeachHeader(
DeclStmt *DS);
402 void CollectBlockDeclRefInfo(
BlockExpr *Exp);
403 void GetBlockDeclRefExprs(
Stmt *S);
404 void GetInnerBlockDeclRefExprs(
Stmt *S,
406 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
410 bool isTopLevelBlockPointerType(
QualType T) {
411 return isa<BlockPointerType>(T);
417 bool convertBlockPointerToFunctionPointer(
QualType &T) {
418 if (isTopLevelBlockPointerType(T)) {
426 bool needToScanForQualifiers(
QualType T);
428 QualType getConstantStringStructType();
430 bool BufferContainsPPDirectives(
const char *startBuf,
const char *endBuf);
432 void convertToUnqualifiedObjCType(
QualType &T) {
460 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
461 PT->getPointeeType()->isObjCQualifiedIdType())
466 bool PointerTypeTakesAnyBlockArguments(
QualType QT);
467 bool PointerTypeTakesAnyObjCQualifiedType(
QualType QT);
468 void GetExtentOfArgList(
const char *Name,
const char *&LParen,
469 const char *&RParen);
471 void QuoteDoublequotes(std::string &From, std::string &To) {
472 for (
unsigned i = 0;
i < From.length();
i++) {
482 bool variadic =
false) {
509 RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
511 bool silenceMacroWarn)
512 :
RewriteObjC(inFile,
std::move(OS), D, LOpts, silenceMacroWarn) {}
514 ~RewriteObjCFragileABI()
override {}
515 void Initialize(
ASTContext &context)
override;
518 template<
typename MethodIterator>
519 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
520 MethodIterator MethodEnd,
521 bool IsInstanceMethod,
526 StringRef prefix, StringRef ClassName,
527 std::string &
Result)
override;
528 void RewriteObjCProtocolListMetaData(
530 StringRef prefix, StringRef ClassName, std::string &
Result)
override;
532 std::string &
Result)
override;
533 void RewriteMetaDataIntoBuffer(std::string &
Result)
override;
535 std::string &
Result)
override;
539 std::string &
Result)
override;
544 void RewriteObjC::RewriteBlocksInFunctionProtoType(
QualType funcType,
547 = dyn_cast<FunctionProtoType>(funcType.
IgnoreParens())) {
548 for (
const auto &I : fproto->param_types())
549 if (isTopLevelBlockPointerType(I)) {
551 RewriteBlockPointerDecl(D);
559 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
564 std::string::size_type DotPos = Filename.rfind(
'.');
566 if (DotPos == std::string::npos) {
571 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
574 return Ext ==
"h" || Ext ==
"hh" || Ext ==
"H";
579 bool silenceMacroWarn)
580 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
581 SilenceRewriteMacroWarning(silenceMacroWarn) {
584 "rewriting sub-expression within a macro (may not be correct)");
587 "rewriter doesn't support user-specified control flow semantics " 588 "for @try/@finally (code may not execute properly)");
591 std::unique_ptr<ASTConsumer>
593 std::unique_ptr<raw_ostream> OS,
595 bool SilenceRewriteMacroWarning) {
596 return llvm::make_unique<RewriteObjCFragileABI>(
597 InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);
600 void RewriteObjC::InitializeCommon(
ASTContext &context) {
604 MsgSendFunctionDecl =
nullptr;
605 MsgSendSuperFunctionDecl =
nullptr;
606 MsgSendStretFunctionDecl =
nullptr;
607 MsgSendSuperStretFunctionDecl =
nullptr;
608 MsgSendFpretFunctionDecl =
nullptr;
609 GetClassFunctionDecl =
nullptr;
610 GetMetaClassFunctionDecl =
nullptr;
611 GetSuperClassFunctionDecl =
nullptr;
612 SelGetUidFunctionDecl =
nullptr;
613 CFStringFunctionDecl =
nullptr;
614 ConstantStringClassReference =
nullptr;
615 NSStringRecord =
nullptr;
616 CurMethodDef =
nullptr;
617 CurFunctionDef =
nullptr;
618 CurFunctionDeclToDeclareForBlock =
nullptr;
619 GlobalVarDecl =
nullptr;
620 SuperStructDecl =
nullptr;
621 ProtocolTypeDecl =
nullptr;
622 ConstantStringDecl =
nullptr;
624 SuperConstructorFunctionDecl =
nullptr;
625 NumObjCStringLiterals = 0;
626 PropParentMap =
nullptr;
627 CurrentBody =
nullptr;
628 DisableReplaceStmt =
false;
629 objc_impl_method =
false;
633 const llvm::MemoryBuffer *MainBuf = SM->
getBuffer(MainFileID);
634 MainFileStart = MainBuf->getBufferStart();
635 MainFileEnd = MainBuf->getBufferEnd();
644 void RewriteObjC::HandleTopLevelSingleDecl(
Decl *D) {
659 RewriteFunctionDecl(FD);
660 }
else if (
VarDecl *FVD = dyn_cast<VarDecl>(D)) {
662 if (FVD->getName() ==
"_NSConstantStringClassReference") {
663 ConstantStringClassReference = FVD;
667 if (
ID->isThisDeclarationADefinition())
668 RewriteInterfaceDecl(
ID);
670 RewriteCategoryDecl(CD);
672 if (PD->isThisDeclarationADefinition())
673 RewriteProtocolDecl(PD);
677 DIEnd = LSD->decls_end();
680 if (!IFace->isThisDeclarationADefinition()) {
684 if (isa<ObjCInterfaceDecl>(*DI) &&
685 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
686 StartLoc == (*DI)->getBeginLoc())
692 }
while (DI != DIEnd);
693 RewriteForwardClassDecl(DG);
699 if (!Proto->isThisDeclarationADefinition()) {
703 if (isa<ObjCProtocolDecl>(*DI) &&
704 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
705 StartLoc == (*DI)->getBeginLoc())
711 }
while (DI != DIEnd);
712 RewriteForwardProtocolDecl(DG);
717 HandleTopLevelSingleDecl(*DI);
723 return HandleDeclInMainFile(D);
730 void RewriteObjC::RewriteInclude() {
733 const char *MainBufStart = MainBuf.begin();
734 const char *MainBufEnd = MainBuf.end();
735 size_t ImportLen = strlen(
"import");
738 for (
const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
739 if (*BufPtr ==
'#') {
740 if (++BufPtr == MainBufEnd)
742 while (*BufPtr ==
' ' || *BufPtr ==
'\t')
743 if (++BufPtr == MainBufEnd)
745 if (!strncmp(BufPtr,
"import", ImportLen)) {
749 ReplaceText(ImportLoc, ImportLen,
"include");
761 S +=
"_IMPL *)self)->";
769 static bool objcGetPropertyDefined =
false;
770 static bool objcSetPropertyDefined =
false;
772 InsertText(startLoc,
"// ");
774 assert((*startBuf ==
'@') &&
"bogus @synthesize location");
775 const char *semiBuf = strchr(startBuf,
';');
776 assert((*semiBuf ==
';') &&
"@synthesize: can't find ';'");
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);
843 InsertText(onePastSemiLoc, Getr);
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);
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";
925 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
929 std::string typedefString;
930 for (
unsigned i = 0;
i < D.size();
i++) {
933 typedefString +=
"// @class ";
935 typedefString +=
";\n";
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,
"// ");
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->
parameters()) {
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())
1163 void RewriteObjC::RewriteImplementationDecl(
Decl *OID) {
1167 InsertText(IMD ? IMD->
getBeginLoc() : CID->getBeginLoc(),
"// ");
1169 for (
auto *OMD : IMD ? IMD->
instance_methods() : CID->instance_methods()) {
1170 std::string ResultStr;
1177 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1180 for (
auto *OMD : IMD ? IMD->
class_methods() : CID->class_methods()) {
1181 std::string ResultStr;
1188 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1190 for (
auto *I : IMD ? IMD->
property_impls() : CID->property_impls())
1191 RewritePropertyImplDecl(I, IMD, CID);
1193 InsertText(IMD ? IMD->
getEndLoc() : CID->getEndLoc(),
"// ");
1197 std::string ResultStr;
1200 ResultStr =
"#ifndef _REWRITER_typedef_";
1203 ResultStr +=
"#define _REWRITER_typedef_";
1206 ResultStr +=
"typedef struct objc_object ";
1208 ResultStr +=
";\n#endif\n";
1212 RewriteObjCInternalStruct(ClassDecl, ResultStr);
1217 RewriteMethodDeclaration(I);
1219 RewriteMethodDeclaration(I);
1239 DisableReplaceStmtScope S(*
this);
1245 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1246 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1251 RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
1252 RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1304 Stmt *Replacement = SynthMessageExpr(NewMsg);
1305 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1321 DisableReplaceStmtScope S(*
this);
1326 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1327 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1380 Stmt *Replacement = SynthMessageExpr(NewMsg);
1381 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1394 void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1395 buf +=
"((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 1396 "id *, unsigned int))(void *)objc_msgSend)";
1398 buf +=
"((id)l_collection,\n\t\t";
1399 buf +=
"sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1401 buf +=
"&enumState, " 1402 "(id *)__rw_items, (unsigned int)16)";
1409 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1415 buf =
"goto __break_label_";
1416 buf += utostr(ObjCBcLabelNo.back());
1417 ReplaceText(startLoc, strlen(
"break"), buf);
1426 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1432 buf =
"goto __continue_label_";
1433 buf += utostr(ObjCBcLabelNo.back());
1434 ReplaceText(startLoc, strlen(
"continue"), buf);
1473 assert(!Stmts.empty() &&
"ObjCForCollectionStmt - Statement stack empty");
1474 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1475 "ObjCForCollectionStmt Statement stack mismatch");
1476 assert(!ObjCBcLabelNo.empty() &&
1477 "ObjCForCollectionStmt - Label No stack empty");
1481 StringRef elementName;
1482 std::string elementTypeAsString;
1487 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1488 QualType ElementType = cast<ValueDecl>(D)->getType();
1489 if (ElementType->isObjCQualifiedIdType() ||
1490 ElementType->isObjCQualifiedInterfaceType())
1492 elementTypeAsString =
"id";
1495 buf += elementTypeAsString;
1508 elementTypeAsString =
"id";
1514 buf +=
"struct __objcFastEnumerationState enumState = { 0 };\n\t";
1516 buf +=
"id __rw_items[16];\n\t";
1518 buf +=
"id l_collection = (id)";
1520 const char *startCollectionBuf = startBuf;
1521 startCollectionBuf += 3;
1522 startCollectionBuf = strchr(startCollectionBuf,
'(');
1523 startCollectionBuf++;
1525 while (*startCollectionBuf !=
' ' ||
1526 *(startCollectionBuf+1) !=
'i' || *(startCollectionBuf+2) !=
'n' ||
1527 (*(startCollectionBuf+3) !=
' ' &&
1528 *(startCollectionBuf+3) !=
'[' && *(startCollectionBuf+3) !=
'('))
1529 startCollectionBuf++;
1530 startCollectionBuf += 3;
1533 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1551 buf +=
"unsigned long limit =\n\t\t";
1552 SynthCountByEnumWithState(buf);
1562 buf +=
"if (limit) {\n\t";
1563 buf +=
"unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1564 buf +=
"do {\n\t\t";
1565 buf +=
"unsigned long counter = 0;\n\t\t";
1566 buf +=
"do {\n\t\t\t";
1567 buf +=
"if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1568 buf +=
"objc_enumerationMutation(l_collection);\n\t\t\t";
1571 buf += elementTypeAsString;
1572 buf +=
")enumState.itemsPtr[counter++];";
1574 ReplaceText(lparenLoc, 1, buf);
1588 buf +=
"__continue_label_";
1589 buf += utostr(ObjCBcLabelNo.back());
1592 buf +=
"} while (counter < limit);\n\t";
1593 buf +=
"} while (limit = ";
1594 SynthCountByEnumWithState(buf);
1598 buf += elementTypeAsString;
1600 buf +=
"__break_label_";
1601 buf += utostr(ObjCBcLabelNo.back());
1604 buf +=
"else\n\t\t";
1607 buf += elementTypeAsString;
1613 if (isa<CompoundStmt>(S->
getBody())) {
1615 InsertText(endBodyLoc, buf);
1625 const char *semiBuf = strchr(stmtBuf,
';');
1626 assert(semiBuf &&
"Can't find ';'");
1628 InsertText(endBodyLoc, buf);
1631 ObjCBcLabelNo.pop_back();
1646 assert((*startBuf ==
'@') &&
"bogus @synchronized location");
1649 buf =
"objc_sync_enter((id)";
1650 const char *lparenBuf = startBuf;
1651 while (*lparenBuf !=
'(') lparenBuf++;
1652 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1658 while (*endBuf !=
')') endBuf--;
1662 buf +=
"/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1663 buf +=
"int buf[18/*32-bit i386*/];\n";
1664 buf +=
"char *pointers[4];} _stack;\n";
1665 buf +=
"id volatile _rethrow = 0;\n";
1666 buf +=
"objc_exception_try_enter(&_stack);\n";
1667 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1668 ReplaceText(rparenLoc, 1, buf);
1672 assert((*startBuf ==
'}') &&
"bogus @synchronized block");
1674 buf =
"}\nelse {\n";
1675 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1677 buf +=
"{ /* implicit finally clause */\n";
1678 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1680 std::string syncBuf;
1681 syncBuf +=
" objc_sync_exit(";
1687 ? CK_BlockPointerToObjCPointerCast
1688 : CK_CPointerToObjCPointerCast;
1689 syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
1691 std::string syncExprBufS;
1692 llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1693 assert(syncExpr !=
nullptr &&
"Expected non-null Expr");
1695 syncBuf += syncExprBuf.str();
1699 buf +=
"\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1703 ReplaceText(lastCurlyLoc, 1, buf);
1705 bool hasReturns =
false;
1713 void RewriteObjC::WarnAboutReturnGotoStmts(
Stmt *S)
1718 WarnAboutReturnGotoStmts(SubStmt);
1720 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1722 TryFinallyContainsReturnDiag);
1726 void RewriteObjC::HasReturnStmts(
Stmt *S,
bool &hasReturns)
1731 HasReturnStmts(SubStmt, hasReturns);
1733 if (isa<ReturnStmt>(S))
1737 void RewriteObjC::RewriteTryReturnStmts(
Stmt *S) {
1741 RewriteTryReturnStmts(SubStmt);
1743 if (isa<ReturnStmt>(S)) {
1746 const char *semiBuf = strchr(startBuf,
';');
1747 assert((*semiBuf ==
';') &&
"RewriteTryReturnStmts: can't find ';'");
1751 buf =
"{ objc_exception_try_exit(&_stack); return";
1753 ReplaceText(startLoc, 6, buf);
1754 InsertText(onePastSemiLoc,
"}");
1758 void RewriteObjC::RewriteSyncReturnStmts(
Stmt *S, std::string syncExitBuf) {
1762 RewriteSyncReturnStmts(SubStmt, syncExitBuf);
1764 if (isa<ReturnStmt>(S)) {
1768 const char *semiBuf = strchr(startBuf,
';');
1769 assert((*semiBuf ==
';') &&
"RewriteSyncReturnStmts: can't find ';'");
1773 buf =
"{ objc_exception_try_exit(&_stack);";
1777 ReplaceText(startLoc, 6, buf);
1778 InsertText(onePastSemiLoc,
"}");
1787 assert((*startBuf ==
'@') &&
"bogus @try location");
1791 buf =
"/* @try scope begin */ { struct _objc_exception_data {\n";
1792 buf +=
"int buf[18/*32-bit i386*/];\n";
1793 buf +=
"char *pointers[4];} _stack;\n";
1794 buf +=
"id volatile _rethrow = 0;\n";
1795 buf +=
"objc_exception_try_enter(&_stack);\n";
1796 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1798 ReplaceText(startLoc, 4, buf);
1803 assert((*startBuf ==
'}') &&
"bogus @try block");
1808 buf =
" /* @catch begin */ else {\n";
1809 buf +=
" id _caught = objc_exception_extract(&_stack);\n";
1810 buf +=
" objc_exception_try_enter (&_stack);\n";
1811 buf +=
" if (_setjmp(_stack.buf))\n";
1812 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1813 buf +=
" else { /* @catch continue */";
1815 InsertText(startLoc, buf);
1817 buf =
"}\nelse {\n";
1818 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1820 ReplaceText(lastCurlyLoc, 1, buf);
1822 Stmt *lastCatchBody =
nullptr;
1834 assert((*startBuf ==
'@') &&
"bogus @catch location");
1836 const char *lParenLoc = strchr(startBuf,
'(');
1844 "bogus @catch paren location");
1845 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1847 buf +=
"1) { id _tmp = _caught;";
1848 Rewrite.
ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
1849 }
else if (catchDecl) {
1853 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1859 buf +=
"objc_exception_match((struct objc_class *)objc_getClass(\"";
1861 buf +=
"\"), (struct objc_object *)_caught)) { ";
1862 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1871 assert((*rParenBuf ==
')') &&
"bogus @catch paren location");
1872 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1876 ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
" = _caught;");
1878 llvm_unreachable(
"@catch rewrite bug");
1882 if (lastCatchBody) {
1885 "bogus @catch body location");
1889 buf =
"} /* last catch end */\n";
1891 buf +=
" _rethrow = _caught;\n";
1892 buf +=
" objc_exception_try_exit(&_stack);\n";
1893 buf +=
"} } /* @catch end */\n";
1896 InsertText(bodyLoc, buf);
1899 lastCurlyLoc = lastCatchBody->
getEndLoc();
1902 startLoc = finalStmt->getBeginLoc();
1904 assert((*startBuf ==
'@') &&
"bogus @finally start");
1906 ReplaceText(startLoc, 8,
"/* @finally */");
1908 Stmt *body = finalStmt->getFinallyBody();
1912 "bogus @finally body location");
1914 "bogus @finally body location");
1917 InsertText(startLoc,
" if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1919 InsertText(endLoc,
" if (_rethrow) objc_exception_throw(_rethrow);\n");
1927 buf =
"{ /* implicit finally clause */\n";
1928 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1929 buf +=
" if (_rethrow) objc_exception_throw(_rethrow);\n";
1931 ReplaceText(lastCurlyLoc, 1, buf);
1936 bool hasReturns =
false;
1943 InsertText(lastCurlyLoc,
" } /* @try scope end */\n");
1955 assert((*startBuf ==
'@') &&
"bogus @throw location");
1960 buf =
"objc_exception_throw(";
1962 buf =
"objc_exception_throw(_caught";
1965 const char *wBuf = strchr(startBuf,
'w');
1966 assert((*wBuf ==
'w') &&
"@throw: can't find 'w'");
1967 ReplaceText(startLoc, wBuf-startBuf+1, buf);
1969 const char *semiBuf = strchr(startBuf,
';');
1970 assert((*semiBuf ==
';') &&
"@throw: can't find ';'");
1972 ReplaceText(semiLoc, 1,
");");
1978 std::string StrEncoding;
1980 Expr *Replacement = getStringLiteral(StrEncoding);
1981 ReplaceStmt(Exp, Replacement);
1989 if (!SelGetUidFunctionDecl)
1990 SynthSelGetUidFunctionDecl();
1991 assert(SelGetUidFunctionDecl &&
"Can't find sel_registerName() decl");
1995 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
1997 ReplaceStmt(Exp, SelExp);
2003 RewriteObjC::SynthesizeCallToFunctionDecl(
FunctionDecl *FD,
2028 const char *&startRef,
const char *&endRef) {
2029 while (startBuf < endBuf) {
2030 if (*startBuf ==
'<')
2031 startRef = startBuf;
2032 if (*startBuf ==
'>') {
2033 if (startRef && *startRef ==
'<') {
2046 while (*argRef !=
')' && (*argRef !=
',' || angle > 0)) {
2049 else if (*argRef ==
'>')
2053 assert(angle == 0 &&
"scanToNextArgument - bad protocol type syntax");
2056 bool RewriteObjC::needToScanForQualifiers(
QualType T) {
2069 return needToScanForQualifiers(ElemTy);
2074 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Expr *E) {
2076 if (needToScanForQualifiers(Type)) {
2080 Loc = ECE->getLParenLoc();
2081 EndLoc = ECE->getRParenLoc();
2092 const char *startRef =
nullptr, *endRef =
nullptr;
2098 InsertText(LessLoc,
"/*");
2099 InsertText(GreaterLoc,
"*/");
2104 void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl) {
2108 if (
VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2109 Loc = VD->getLocation();
2110 Type = VD->getType();
2112 else if (
FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2117 assert(funcType &&
"missing function type");
2123 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2130 if (needToScanForQualifiers(Type)) {
2134 const char *startBuf = endBuf;
2135 while (*startBuf !=
';' && *startBuf !=
'<' && startBuf != MainFileStart)
2137 const char *startRef =
nullptr, *endRef =
nullptr;
2143 InsertText(LessLoc,
"/*");
2144 InsertText(GreaterLoc,
"*/");
2151 const char *startFuncBuf = startBuf;
2156 const char *endBuf = startBuf;
2159 const char *startRef =
nullptr, *endRef =
nullptr;
2167 InsertText(LessLoc,
"/*");
2168 InsertText(GreaterLoc,
"*/");
2170 startBuf = ++endBuf;
2175 while (*startBuf && *startBuf !=
')' && *startBuf !=
',')
2182 void RewriteObjC::RewriteTypeOfDecl(
VarDecl *ND) {
2185 if (!isa<TypeOfExprType>(TypePtr))
2187 while (isa<TypeOfExprType>(TypePtr)) {
2188 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2199 TypeAsString +=
" " + Name +
" = ";
2203 startLoc = ECE->getLParenLoc();
2208 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2214 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2219 void RewriteObjC::SynthSelGetUidFunctionDecl() {
2228 SelGetUidIdent, getFuncType,
2232 void RewriteObjC::RewriteFunctionDecl(
FunctionDecl *FD) {
2235 FD->
getName() ==
"sel_registerName") {
2236 SelGetUidFunctionDecl = FD;
2239 RewriteObjCQualifiedInterfaceTypes(FD);
2242 void RewriteObjC::RewriteBlockPointerType(std::string& Str,
QualType Type) {
2244 const char *argPtr = TypeString.c_str();
2245 if (!strchr(argPtr,
'^')) {
2250 Str += (*argPtr ==
'^' ?
'*' : *argPtr);
2256 void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2260 const char *argPtr = TypeString.c_str();
2285 void RewriteObjC::RewriteBlockLiteralFunctionDecl(
FunctionDecl *FD) {
2291 QualType Type = proto->getReturnType();
2296 unsigned numArgs = proto->getNumParams();
2297 for (
unsigned i = 0;
i < numArgs;
i++) {
2298 QualType ArgType = proto->getParamType(
i);
2299 RewriteBlockPointerType(FdStr, ArgType);
2304 InsertText(FunLocStart, FdStr);
2305 CurFunctionDeclToDeclareForBlock =
nullptr;
2309 void RewriteObjC::SynthSuperConstructorFunctionDecl() {
2310 if (SuperConstructorFunctionDecl)
2315 assert(!argT.
isNull() &&
"Can't find 'id' type");
2316 ArgTys.push_back(argT);
2317 ArgTys.push_back(argT);
2323 msgSendIdent, msgSendType,
2328 void RewriteObjC::SynthMsgSendFunctionDecl() {
2332 assert(!argT.
isNull() &&
"Can't find 'id' type");
2333 ArgTys.push_back(argT);
2335 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2336 ArgTys.push_back(argT);
2342 msgSendIdent, msgSendType,
2347 void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2354 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2355 ArgTys.push_back(argT);
2357 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2358 ArgTys.push_back(argT);
2364 msgSendIdent, msgSendType,
2369 void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2373 assert(!argT.
isNull() &&
"Can't find 'id' type");
2374 ArgTys.push_back(argT);
2376 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2377 ArgTys.push_back(argT);
2383 msgSendIdent, msgSendType,
2389 void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2391 &Context->
Idents.
get(
"objc_msgSendSuper_stret");
2397 assert(!argT.isNull() &&
"Can't build 'struct objc_super *' type");
2398 ArgTys.push_back(argT);
2400 assert(!argT.isNull() &&
"Can't find 'SEL' type");
2401 ArgTys.push_back(argT);
2408 msgSendType,
nullptr,
2413 void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2417 assert(!argT.
isNull() &&
"Can't find 'id' type");
2418 ArgTys.push_back(argT);
2420 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2421 ArgTys.push_back(argT);
2427 msgSendIdent, msgSendType,
2432 void RewriteObjC::SynthGetClassFunctionDecl() {
2441 getClassIdent, getClassType,
2446 void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2448 &Context->
Idents.
get(
"class_getSuperclass");
2457 getClassType,
nullptr,
2462 void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2471 getClassIdent, getClassType,
2476 assert(Exp !=
nullptr &&
"Expected non-null ObjCStringLiteral");
2477 QualType strType = getConstantStringStructType();
2479 std::string S =
"__NSConstantStringImpl_";
2481 std::string tmpName = InFileName;
2483 for (i=0; i < tmpName.length(); i++) {
2484 char c = tmpName.at(i);
2491 S += utostr(NumObjCStringLiterals++);
2493 Preamble +=
"static __NSConstantStringImpl " + S;
2494 Preamble +=
" __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2495 Preamble +=
"0x000007c8,";
2497 std::string prettyBufS;
2498 llvm::raw_string_ostream prettyBuf(prettyBufS);
2500 Preamble += prettyBuf.str();
2509 Expr *Unop =
new (Context)
2514 CK_CPointerToObjCPointerCast, Unop);
2515 ReplaceStmt(Exp, cast);
2521 QualType RewriteObjC::getSuperStructType() {
2522 if (!SuperStructDecl) {
2534 for (
unsigned i = 0;
i < 2; ++
i) {
2538 FieldTypes[
i],
nullptr,
2549 QualType RewriteObjC::getConstantStringStructType() {
2550 if (!ConstantStringDecl) {
2553 &Context->
Idents.
get(
"__NSConstantStringImpl"));
2559 FieldTypes[1] = Context->
IntTy;
2563 FieldTypes[3] = Context->
LongTy;
2566 for (
unsigned i = 0;
i < 4; ++
i) {
2571 FieldTypes[
i],
nullptr,
2590 new (Context)
DeclRefExpr(*Context, MsgSendStretFlavor,
false,
2597 QualType castType = getSimpleFunctionType(returnType, ArgTypes,
2601 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2616 if (!SelGetUidFunctionDecl)
2617 SynthSelGetUidFunctionDecl();
2618 if (!MsgSendFunctionDecl)
2619 SynthMsgSendFunctionDecl();
2620 if (!MsgSendSuperFunctionDecl)
2621 SynthMsgSendSuperFunctionDecl();
2622 if (!MsgSendStretFunctionDecl)
2623 SynthMsgSendStretFunctionDecl();
2624 if (!MsgSendSuperStretFunctionDecl)
2625 SynthMsgSendSuperStretFunctionDecl();
2626 if (!MsgSendFpretFunctionDecl)
2627 SynthMsgSendFpretFunctionDecl();
2628 if (!GetClassFunctionDecl)
2629 SynthGetClassFunctionDecl();
2630 if (!GetSuperClassFunctionDecl)
2631 SynthGetSuperClassFunctionDecl();
2632 if (!GetMetaClassFunctionDecl)
2633 SynthGetMetaClassFunctionDecl();
2640 QualType resultType = mDecl->getReturnType();
2642 MsgSendStretFlavor = MsgSendStretFunctionDecl;
2644 MsgSendFlavor = MsgSendFpretFunctionDecl;
2651 MsgSendFlavor = MsgSendSuperFunctionDecl;
2652 if (MsgSendStretFlavor)
2653 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2654 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2661 InitExprs.push_back(
2675 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2676 ClsExprs, StartLoc, EndLoc);
2678 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2682 ClsExprs.push_back(ArgExpr);
2683 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2687 InitExprs.push_back(
2688 NoTypeInfoCStyleCastExpr(Context,
2692 QualType superType = getSuperStructType();
2695 if (LangOpts.MicrosoftExt) {
2696 SynthSuperConstructorFunctionDecl();
2699 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2713 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2715 CK_BitCast, SuperRep);
2732 MsgExprs.push_back(SuperRep);
2741 ClsExprs.push_back(getStringLiteral(clsName->
getName()));
2742 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2744 MsgExprs.push_back(Cls);
2749 MsgSendFlavor = MsgSendSuperFunctionDecl;
2750 if (MsgSendStretFlavor)
2751 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2752 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2756 InitExprs.push_back(
2769 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2772 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2776 ClsExprs.push_back(ArgExpr);
2777 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2782 InitExprs.push_back(
2787 QualType superType = getSuperStructType();
2790 if (LangOpts.MicrosoftExt) {
2791 SynthSuperConstructorFunctionDecl();
2794 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2808 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2810 CK_BitCast, SuperRep);
2822 MsgExprs.push_back(SuperRep);
2831 recExpr = CE->getSubExpr();
2834 ? CK_BlockPointerToObjCPointerCast
2835 : CK_CPointerToObjCPointerCast;
2837 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
2839 MsgExprs.push_back(recExpr);
2847 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2848 SelExprs, StartLoc, EndLoc);
2849 MsgExprs.push_back(SelExp);
2858 if (needToScanForQualifiers(type))
2861 (void)convertBlockPointerToFunctionPointer(type);
2866 CK = CK_IntegralToBoolean;
2869 CK = CK_BlockPointerToObjCPointerCast;
2871 CK = CK_CPointerToObjCPointerCast;
2879 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2882 else if (
CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2883 if (CE->getType()->isObjCQualifiedIdType()) {
2884 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2885 userExpr = CE->getSubExpr();
2888 CK = CK_IntegralToPointer;
2890 CK = CK_BlockPointerToObjCPointerCast;
2892 CK = CK_CPointerToObjCPointerCast;
2896 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->
getObjCIdType(),
2900 MsgExprs.push_back(userExpr);
2912 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2913 ArgTypes.push_back(Context->
getPointerType(getSuperStructType()));
2920 QualType t = PI->getType()->isObjCQualifiedIdType()
2924 (void)convertBlockPointerToFunctionPointer(t);
2925 ArgTypes.push_back(t);
2928 convertToUnqualifiedObjCType(returnType);
2929 (void)convertBlockPointerToFunctionPointer(returnType);
2944 cast = NoTypeInfoCStyleCastExpr(Context,
2952 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() :
true);
2954 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2963 Stmt *ReplacingStmt = CE;
2964 if (MsgSendStretFlavor) {
2970 CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
2971 msgSendType, returnType,
2988 llvm::APInt(IntSize, 8),
3005 return ReplacingStmt;
3009 Stmt *ReplacingStmt =
3013 ReplaceStmt(Exp, ReplacingStmt);
3016 return ReplacingStmt;
3020 QualType RewriteObjC::getProtocolType() {
3021 if (!ProtocolTypeDecl) {
3050 ReplaceStmt(Exp, castExpr);
3056 bool RewriteObjC::BufferContainsPPDirectives(
const char *startBuf,
3057 const char *endBuf) {
3058 while (startBuf < endBuf) {
3059 if (*startBuf ==
'#') {
3061 for (++startBuf; startBuf[0] ==
' ' || startBuf[0] ==
'\t'; ++startBuf)
3063 if (!strncmp(startBuf,
"if", strlen(
"if")) ||
3064 !strncmp(startBuf,
"ifdef", strlen(
"ifdef")) ||
3065 !strncmp(startBuf,
"ifndef", strlen(
"ifndef")) ||
3066 !strncmp(startBuf,
"define", strlen(
"define")) ||
3067 !strncmp(startBuf,
"undef", strlen(
"undef")) ||
3068 !strncmp(startBuf,
"else", strlen(
"else")) ||
3069 !strncmp(startBuf,
"elif", strlen(
"elif")) ||
3070 !strncmp(startBuf,
"endif", strlen(
"endif")) ||
3071 !strncmp(startBuf,
"pragma", strlen(
"pragma")) ||
3072 !strncmp(startBuf,
"include", strlen(
"include")) ||
3073 !strncmp(startBuf,
"import", strlen(
"import")) ||
3074 !strncmp(startBuf,
"include_next", strlen(
"include_next")))
3086 assert(CDecl &&
"Class missing in SynthesizeObjCInternalStruct");
3087 assert(CDecl->
getName() !=
"" &&
3088 "Name missing in SynthesizeObjCInternalStruct");
3090 if (ObjCSynthesizedStructs.count(CDecl))
3103 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3105 ReplaceText(LocStart, endBuf-startBuf, Result);
3111 Result +=
"\nstruct ";
3113 if (LangOpts.MicrosoftExt)
3117 const char *cursor = strchr(startBuf,
'{');
3118 assert((cursor && endBuf)
3119 &&
"SynthesizeObjCInternalStruct - malformed @interface");
3135 if (BufferContainsPPDirectives(startBuf, cursor)) {
3143 while (endHeader < cursor && *endHeader != '>
') endHeader++; 3146 // rewrite the original header 3147 ReplaceText(LocStart, endHeader-startBuf, Result); 3149 // rewrite the original header *without* disturbing the '{
' 3150 ReplaceText(LocStart, cursor-startBuf, Result); 3152 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 3153 Result = "\n struct "; 3154 Result += RCDecl->getNameAsString(); 3156 Result += RCDecl->getNameAsString(); 3157 Result += "_IVARS;\n"; 3159 // insert the super class structure definition. 3160 SourceLocation OnePastCurly = 3161 LocStart.getLocWithOffset(cursor-startBuf+1); 3162 InsertText(OnePastCurly, Result); 3164 cursor++; // past '{
' 3166 // Now comment out any visibility specifiers. 3167 while (cursor < endBuf) { 3168 if (*cursor == '@
') { 3169 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3171 for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor) 3174 // FIXME: presence of @public, etc. inside comment results in 3175 // this transformation as well, which is still correct c-code. 3176 if (!strncmp(cursor, "public", strlen("public")) || 3177 !strncmp(cursor, "private", strlen("private")) || 3178 !strncmp(cursor, "package", strlen("package")) || 3179 !strncmp(cursor, "protected", strlen("protected"))) 3180 InsertText(atLoc, "// "); 3182 // FIXME: If there are cases where '<
' is used in ivar declaration part 3183 // of user code, then scan the ivar list and use needToScanForQualifiers 3184 // for type checking. 3185 else if (*cursor == '<
') { 3186 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3187 InsertText(atLoc, "/* "); 3188 cursor = strchr(cursor, '>
'); 3190 atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3191 InsertText(atLoc, " */"); 3192 } else if (*cursor == '^
') { // rewrite block specifier. 3193 SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf); 3194 ReplaceText(caretLoc, 1, "*"); 3198 // Don't forget to add
a ';'!!
3202 Result +=
" {\n struct ";
3206 Result +=
"_IVARS;\n};\n";
3207 ReplaceText(LocStart, endBuf-startBuf, Result);
3210 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3211 llvm_unreachable(
"struct already synthesize- SynthesizeObjCInternalStruct");
3221 void RewriteObjC::RewriteImplementations() {
3222 int ClsDefCount = ClassImplementation.size();
3223 int CatDefCount = CategoryImplementation.size();
3226 for (
int i = 0;
i < ClsDefCount;
i++)
3227 RewriteImplementationDecl(ClassImplementation[
i]);
3229 for (
int i = 0; i < CatDefCount; i++)
3230 RewriteImplementationDecl(CategoryImplementation[i]);
3233 void RewriteObjC::RewriteByRefString(std::string &ResultStr,
3234 const std::string &Name,
3236 assert(BlockByRefDeclNo.count(VD) &&
3237 "RewriteByRefString: ByRef decl missing");
3239 ResultStr +=
"struct ";
3240 ResultStr +=
"__Block_byref_" + Name +
3241 "_" + utostr(BlockByRefDeclNo[VD]) ;
3245 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3246 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3250 std::string RewriteObjC::SynthesizeBlockFunc(
BlockExpr *CE,
int i,
3255 std::string StructRef =
"struct " + Tag;
3257 funcName.str() +
"_" +
"block_func_" + utostr(i);
3261 if (isa<FunctionNoProtoType>(AFT)) {
3264 S +=
"(" + StructRef +
" *__cself)";
3266 S +=
"(" + StructRef +
" *__cself)";
3269 assert(FT &&
"SynthesizeBlockFunc: No function proto");
3272 S += StructRef +
" *__cself, ";
3273 std::string ParamStr;
3277 ParamStr = (*AI)->getNameAsString();
3279 (void)convertBlockPointerToFunctionPointer(QT);
3294 E = BlockByRefDecls.end(); I != E; ++I) {
3296 std::string Name = (*I)->getNameAsString();
3297 std::string TypeString;
3298 RewriteByRefString(TypeString, Name, (*I));
3300 Name = TypeString + Name;
3301 S += Name +
" = __cself->" + (*I)->getNameAsString() +
"; // bound by ref\n";
3305 E = BlockByCopyDecls.end(); I != E; ++I) {
3317 if (isTopLevelBlockPointerType((*I)->getType())) {
3318 RewriteBlockPointerTypeVariable(S, (*I));
3320 RewriteBlockPointerType(S, (*I)->getType());
3322 S +=
"__cself->" + (*I)->getNameAsString() +
"; // bound by copy\n";
3325 std::string Name = (*I)->getNameAsString();
3330 S += Name +
" = __cself->" +
3331 (*I)->getNameAsString() +
"; // bound by copy\n";
3334 std::string RewrittenStr = RewrittenBlockExprs[CE];
3335 const char *cstr = RewrittenStr.c_str();
3336 while (*cstr++ !=
'{') ;
3342 std::string RewriteObjC::SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
3345 std::string StructRef =
"struct " + Tag;
3346 std::string S =
"static void __";
3349 S +=
"_block_copy_" + utostr(i);
3350 S +=
"(" + StructRef;
3351 S +=
"*dst, " + StructRef;
3353 for (
ValueDecl *VD : ImportedBlockDecls) {
3354 S +=
"_Block_object_assign((void*)&dst->";
3356 S +=
", (void*)src->";
3358 if (BlockByRefDeclsPtrSet.count(VD))
3367 S +=
"\nstatic void __";
3369 S +=
"_block_dispose_" + utostr(i);
3370 S +=
"(" + StructRef;
3372 for (
ValueDecl *VD : ImportedBlockDecls) {
3373 S +=
"_Block_object_dispose((void*)src->";
3375 if (BlockByRefDeclsPtrSet.count(VD))
3386 std::string RewriteObjC::SynthesizeBlockImpl(
BlockExpr *CE, std::string Tag,
3388 std::string S =
"\nstruct " + Tag;
3389 std::string Constructor =
" " + Tag;
3391 S +=
" {\n struct __block_impl impl;\n";
3392 S +=
" struct " + Desc;
3395 Constructor +=
"(void *fp, ";
3396 Constructor +=
"struct " + Desc;
3397 Constructor +=
" *desc";
3399 if (BlockDeclRefs.size()) {
3402 E = BlockByCopyDecls.end(); I != E; ++I) {
3404 std::string FieldName = (*I)->getNameAsString();
3405 std::string ArgName =
"_" + FieldName;
3416 if (isTopLevelBlockPointerType((*I)->getType())) {
3417 S +=
"struct __block_impl *";
3418 Constructor +=
", void *" + ArgName;
3425 Constructor +=
", " + ArgName;
3427 S += FieldName +
";\n";
3431 E = BlockByRefDecls.end(); I != E; ++I) {
3433 std::string FieldName = (*I)->getNameAsString();
3434 std::string ArgName =
"_" + FieldName;
3436 std::string TypeString;
3437 RewriteByRefString(TypeString, FieldName, (*I));
3439 FieldName = TypeString + FieldName;
3440 ArgName = TypeString + ArgName;
3441 Constructor +=
", " + ArgName;
3443 S += FieldName +
"; // by ref\n";
3446 Constructor +=
", int flags=0)";
3448 bool firsTime =
true;
3450 E = BlockByCopyDecls.end(); I != E; ++I) {
3451 std::string Name = (*I)->getNameAsString();
3453 Constructor +=
" : ";
3457 Constructor +=
", ";
3458 if (isTopLevelBlockPointerType((*I)->getType()))
3459 Constructor += Name +
"((struct __block_impl *)_" + Name +
")";
3461 Constructor += Name +
"(_" + Name +
")";
3465 E = BlockByRefDecls.end(); I != E; ++I) {
3466 std::string Name = (*I)->getNameAsString();
3468 Constructor +=
" : ";
3472 Constructor +=
", ";
3473 Constructor += Name +
"(_" + Name +
"->__forwarding)";
3476 Constructor +=
" {\n";
3478 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3480 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3481 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3483 Constructor +=
" Desc = desc;\n";
3486 Constructor +=
", int flags=0) {\n";
3488 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3490 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3491 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3492 Constructor +=
" Desc = desc;\n";
3495 Constructor +=
"}\n";
3501 std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
3502 std::string ImplTag,
int i,
3505 std::string S =
"\nstatic struct " + DescTag;
3507 S +=
" {\n unsigned long reserved;\n";
3508 S +=
" unsigned long Block_size;\n";
3510 S +=
" void (*copy)(struct ";
3511 S += ImplTag; S +=
"*, struct ";
3512 S += ImplTag; S +=
"*);\n";
3514 S +=
" void (*dispose)(struct ";
3515 S += ImplTag; S +=
"*);\n";
3519 S += DescTag +
"_DATA = { 0, sizeof(struct ";
3522 S +=
", __" + FunName.str() +
"_block_copy_" + utostr(i);
3523 S +=
", __" + FunName.str() +
"_block_dispose_" + utostr(i);
3529 void RewriteObjC::SynthesizeBlockLiterals(
SourceLocation FunLocStart,
3530 StringRef FunName) {
3532 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3533 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3534 bool RewriteSC = (GlobalVarDecl &&
3539 std::string SC(
" void __");
3542 InsertText(FunLocStart, SC);
3546 for (
unsigned i = 0, count=0; i < Blocks.size(); i++) {
3547 CollectBlockDeclRefInfo(Blocks[i]);
3550 for (
int j = 0; j < InnerDeclRefsCount[
i]; j++) {
3553 BlockDeclRefs.push_back(Exp);
3554 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
3555 BlockByCopyDeclsPtrSet.insert(VD);
3556 BlockByCopyDecls.push_back(VD);
3558 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
3559 BlockByRefDeclsPtrSet.insert(VD);
3560 BlockByRefDecls.push_back(VD);
3564 if (VD->
hasAttr<BlocksAttr>() ||
3567 ImportedBlockDecls.insert(VD);
3570 std::string ImplTag =
"__" + FunName.str() +
"_block_impl_" + utostr(i);
3571 std::string DescTag =
"__" + FunName.str() +
"_block_desc_" + utostr(i);
3573 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3575 InsertText(FunLocStart, CI);
3577 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3579 InsertText(FunLocStart, CF);
3581 if (ImportedBlockDecls.size()) {
3582 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3583 InsertText(FunLocStart, HF);
3585 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3586 ImportedBlockDecls.size() > 0);
3587 InsertText(FunLocStart, BD);
3589 BlockDeclRefs.clear();
3590 BlockByRefDecls.clear();
3591 BlockByRefDeclsPtrSet.clear();
3592 BlockByCopyDecls.clear();
3593 BlockByCopyDeclsPtrSet.clear();
3594 ImportedBlockDecls.clear();
3608 InsertText(FunLocStart, SC);
3612 InnerDeclRefsCount.clear();
3613 InnerDeclRefs.clear();
3614 RewrittenBlockExprs.clear();
3617 void RewriteObjC::InsertBlockLiteralsWithinFunction(
FunctionDecl *FD) {
3619 StringRef FuncName = FD->
getName();
3621 SynthesizeBlockLiterals(FunLocStart, FuncName);
3630 std::string::size_type loc = 0;
3631 while ((loc = Name.find(
':', loc)) != std::string::npos)
3632 Name.replace(loc, 1,
"_");
3635 void RewriteObjC::InsertBlockLiteralsWithinMethod(
ObjCMethodDecl *MD) {
3639 std::string FuncName;
3641 SynthesizeBlockLiterals(FunLocStart, FuncName);
3644 void RewriteObjC::GetBlockDeclRefExprs(
Stmt *S) {
3647 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
3648 GetBlockDeclRefExprs(CBE->getBody());
3650 GetBlockDeclRefExprs(SubStmt);
3654 if (DRE->refersToEnclosingVariableOrCapture() ||
3657 BlockDeclRefs.push_back(DRE);
3660 void RewriteObjC::GetInnerBlockDeclRefExprs(
Stmt *S,
3662 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
3665 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
3666 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
3667 GetInnerBlockDeclRefExprs(CBE->getBody(),
3672 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
3675 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3676 if (DRE->refersToEnclosingVariableOrCapture() ||
3678 if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
3679 InnerBlockDeclRefs.push_back(DRE);
3680 if (
VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
3681 if (Var->isFunctionOrMethodVarDecl())
3682 ImportedLocalExternalDecls.insert(Var);
3697 bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
3703 if (convertBlockPointerToFunctionPointer(t))
3704 HasBlockType =
true;
3705 ArgTypes.push_back(t);
3712 FuncType = getSimpleFunctionType(Res, ArgTypes);
3717 Stmt *RewriteObjC::SynthesizeBlockCall(
CallExpr *Exp,
const Expr *BlockExp) {
3721 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3723 }
else if (
const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3726 else if (
const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3727 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3729 else if (
const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3732 dyn_cast<ConditionalOperator>(BlockExp)) {
3733 Expr *LHSExp = CEXPR->getLHS();
3734 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3735 Expr *RHSExp = CEXPR->getRHS();
3736 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3737 Expr *CONDExp = CEXPR->getCond();
3744 }
else if (
const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3747 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
3750 assert(
false &&
"RewriteBlockClass: Bad type");
3752 assert(CPT &&
"RewriteBlockClass: Bad type");
3754 assert(FT &&
"RewriteBlockClass: Bad type");
3767 ArgTypes.push_back(PtrBlock);
3772 if (!convertBlockPointerToFunctionPointer(t))
3773 convertToUnqualifiedObjCType(t);
3774 ArgTypes.push_back(t);
3778 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->
getType(), ArgTypes);
3782 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
3784 const_cast<Expr*>(BlockExp));
3799 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
3805 BlkExprs.push_back(BlkCast);
3808 E = Exp->
arg_end(); I != E; ++I) {
3809 BlkExprs.push_back(*I);
3846 StringRef Name = VD->
getName();
3859 ReplaceStmt(DeclRefExp, PE);
3866 Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(
DeclRefExpr *DRE) {
3868 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3869 if (!ImportedLocalExternalDecls.count(Var))
3877 ReplaceStmt(DRE, PE);
3895 const Type* TypePtr = QT->
getAs<Type>();
3896 if (isa<TypeOfExprType>(TypePtr)) {
3897 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
3899 std::string TypeAsString =
"(";
3900 RewriteBlockPointerType(TypeAsString, QT);
3901 TypeAsString +=
")";
3902 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
3906 const char *argPtr = startBuf;
3908 while (*argPtr++ && (argPtr < endBuf)) {
3913 ReplaceText(LocStart, 1,
"*");
3919 void RewriteObjC::RewriteBlockPointerFunctionArgs(
FunctionDecl *FD) {
3921 unsigned parenCount = 0;
3925 const char *startArgList = strchr(startBuf,
'(');
3927 assert((*startArgList ==
'(') &&
"Rewriter fuzzy parser confused");
3932 assert((DeclLoc.
isValid()) &&
"Invalid DeclLoc");
3934 const char *argPtr = startArgList;
3936 while (*argPtr++ && parenCount) {
3941 ReplaceText(DeclLoc, 1,
"*");
3953 bool RewriteObjC::PointerTypeTakesAnyBlockArguments(
QualType QT) {
3960 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3965 if (isTopLevelBlockPointerType(I))
3971 bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(
QualType QT) {
3978 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3983 if (I->isObjCQualifiedIdType())
3985 if (I->isObjCObjectPointerType() &&
3986 I->getPointeeType()->isObjCQualifiedInterfaceType())
3994 void RewriteObjC::GetExtentOfArgList(
const char *Name,
const char *&LParen,
3995 const char *&RParen) {
3996 const char *argPtr = strchr(Name,
'(');
3997 assert((*argPtr ==
'(') &&
"Rewriter fuzzy parser confused");
4001 unsigned parenCount = 1;
4003 while (*argPtr && parenCount) {
4005 case '(': parenCount++;
break;
4006 case ')': parenCount--;
break;
4009 if (parenCount) argPtr++;
4011 assert((*argPtr ==
')') &&
"Rewriter fuzzy parser confused");
4015 void RewriteObjC::RewriteBlockPointerDecl(
NamedDecl *ND) {
4017 RewriteBlockPointerFunctionArgs(FD);
4023 if (
VarDecl *VD = dyn_cast<VarDecl>(ND))
4026 DeclT = TDD->getUnderlyingType();
4027 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4030 llvm_unreachable(
"RewriteBlockPointerDecl(): Decl type not yet handled");
4033 const char *endBuf = startBuf;
4035 while (*startBuf !=
'^' && *startBuf !=
';' && startBuf != MainFileStart)
4039 unsigned OrigLength=0;
4042 if (*startBuf ==
'^') {
4048 while (*startBuf !=
')') {
4056 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4057 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4062 const char *argListBegin, *argListEnd;
4063 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4064 while (argListBegin < argListEnd) {
4065 if (*argListBegin ==
'^')
4067 else if (*argListBegin ==
'<') {
4069 buf += *argListBegin++;
4071 while (*argListBegin !=
'>') {
4072 buf += *argListBegin++;
4075 buf += *argListBegin;
4079 buf += *argListBegin;
4086 ReplaceText(Start, OrigLength, buf);
4109 std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
4112 if (CopyDestroyCache.count(flag))
4114 CopyDestroyCache.insert(flag);
4115 S =
"static void __Block_byref_id_object_copy_";
4117 S +=
"(void *dst, void *src) {\n";
4123 unsigned VoidPtrSize =
4126 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->
getCharWidth();
4127 S +=
" _Block_object_assign((char*)dst + ";
4128 S += utostr(offset);
4129 S +=
", *(void * *) ((char*)src + ";
4130 S += utostr(offset);
4135 S +=
"static void __Block_byref_id_object_dispose_";
4137 S +=
"(void *src) {\n";
4138 S +=
" _Block_object_dispose(*(void * *) ((char*)src + ";
4139 S += utostr(offset);
4164 void RewriteObjC::RewriteByRefVar(
VarDecl *ND) {
4167 if (CurFunctionDeclToDeclareForBlock)
4168 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4181 std::string ByrefType;
4182 RewriteByRefString(ByrefType, Name, ND,
true);
4183 ByrefType +=
" {\n";
4184 ByrefType +=
" void *__isa;\n";
4185 RewriteByRefString(ByrefType, Name, ND);
4186 ByrefType +=
" *__forwarding;\n";
4187 ByrefType +=
" int __flags;\n";
4188 ByrefType +=
" int __size;\n";
4193 if (HasCopyAndDispose) {
4194 ByrefType +=
" void (*__Block_byref_id_object_copy)(void*, void*);\n";
4195 ByrefType +=
" void (*__Block_byref_id_object_dispose)(void*);\n";
4199 (void)convertBlockPointerToFunctionPointer(T);
4202 ByrefType +=
" " + Name +
";\n";
4203 ByrefType +=
"};\n";
4209 assert(CurMethodDef &&
"RewriteByRefVar - CurMethodDef is null");
4212 InsertText(FunLocStart, ByrefType);
4218 if (HasCopyAndDispose) {
4226 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4228 InsertText(FunLocStart, HF);
4234 bool hasInit = (ND->
getInit() !=
nullptr);
4236 if (HasCopyAndDispose)
4240 RewriteByRefString(ByrefType, Name, ND);
4241 std::string ForwardingCastType(
"(");
4242 ForwardingCastType += ByrefType +
" *)";
4244 ByrefType +=
" " + Name +
" = {(void*)";
4245 ByrefType += utostr(isa);
4246 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4247 ByrefType += utostr(flags);
4249 ByrefType +=
"sizeof(";
4250 RewriteByRefString(ByrefType, Name, ND);
4252 if (HasCopyAndDispose) {
4253 ByrefType +=
", __Block_byref_id_object_copy_";
4254 ByrefType += utostr(flag);
4255 ByrefType +=
", __Block_byref_id_object_dispose_";
4256 ByrefType += utostr(flag);
4258 ByrefType +=
"};\n";
4259 unsigned nameSize = Name.size();
4264 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4270 startLoc = ECE->getLParenLoc();
4275 ByrefType +=
" " + Name;
4276 ByrefType +=
" = {(void*)";
4277 ByrefType += utostr(isa);
4278 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4279 ByrefType += utostr(flags);
4281 ByrefType +=
"sizeof(";
4282 RewriteByRefString(ByrefType, Name, ND);
4284 if (HasCopyAndDispose) {
4285 ByrefType +=
"__Block_byref_id_object_copy_";
4286 ByrefType += utostr(flag);
4287 ByrefType +=
", __Block_byref_id_object_dispose_";
4288 ByrefType += utostr(flag);
4291 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4302 const char *semiBuf = strchr(startInitializerBuf,
';');
4303 assert((*semiBuf ==
';') &&
"RewriteByRefVar: can't find ';'");
4307 InsertText(semiLoc,
"}");
4311 void RewriteObjC::CollectBlockDeclRefInfo(
BlockExpr *Exp) {
4313 GetBlockDeclRefExprs(Exp->
getBody());
4314 if (BlockDeclRefs.size()) {
4316 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4317 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4318 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4319 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4320 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
4324 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4325 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4326 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4327 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4328 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
4332 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4333 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4334 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4335 BlockDeclRefs[
i]->getType()->isBlockPointerType())
4336 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4351 Blocks.push_back(Exp);
4353 CollectBlockDeclRefInfo(Exp);
4356 int countOfInnerDecls = 0;
4357 if (!InnerBlockDeclRefs.empty()) {
4358 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
4361 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
4365 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4366 BlockDeclRefs.push_back(Exp);
4367 BlockByCopyDeclsPtrSet.insert(VD);
4368 BlockByCopyDecls.push_back(VD);
4370 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
4371 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4372 BlockDeclRefs.push_back(Exp);
4373 BlockByRefDeclsPtrSet.insert(VD);
4374 BlockByRefDecls.push_back(VD);
4378 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
4379 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4380 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4381 InnerBlockDeclRefs[
i]->getType()->isBlockPointerType())
4382 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4384 InnerDeclRefsCount.push_back(countOfInnerDecls);
4386 std::string FuncName;
4390 else if (CurMethodDef)
4392 else if (GlobalVarDecl)
4395 std::string BlockNumber = utostr(Blocks.size()-1);
4397 std::string Tag =
"__" + FuncName +
"_block_impl_" + BlockNumber;
4398 std::string Func =
"__" + FuncName +
"_block_func_" + BlockNumber;
4408 FD = SynthBlockInitFunctionDecl(Tag);
4415 FD = SynthBlockInitFunctionDecl(Func);
4419 NoTypeInfoCStyleCastExpr(Context, Context->
VoidPtrTy, CK_BitCast, Arg);
4420 InitExprs.push_back(castExpr);
4423 std::string DescData =
"__" + FuncName +
"_block_desc_" + BlockNumber +
"_DATA";
4433 InitExprs.push_back(DescRefExpr);
4436 if (BlockDeclRefs.size()) {
4440 E = BlockByCopyDecls.end(); I != E; ++I) {
4441 if (isObjCType((*I)->getType())) {
4443 FD = SynthBlockInitFunctionDecl((*I)->getName());
4453 }
else if (isTopLevelBlockPointerType((*I)->getType())) {
4454 FD = SynthBlockInitFunctionDecl((*I)->getName());
4457 Exp = NoTypeInfoCStyleCastExpr(Context, Context->
VoidPtrTy, CK_BitCast,
4460 FD = SynthBlockInitFunctionDecl((*I)->getName());
4471 InitExprs.push_back(Exp);
4475 E = BlockByRefDecls.end(); I != E; ++I) {
4478 std::string RecName;
4479 RewriteByRefString(RecName, Name, ND,
true);
4481 +
sizeof(
"struct"));
4485 assert(RD &&
"SynthBlockInitExpr(): Can't find RecordDecl");
4488 FD = SynthBlockInitFunctionDecl((*I)->getName());
4491 bool isNestedCapturedVar =
false;
4493 for (
const auto &CI : block->
captures()) {
4494 const VarDecl *variable = CI.getVariable();
4495 if (variable == ND && CI.isNested()) {
4496 assert (CI.isByRef() &&
4497 "SynthBlockInitExpr - captured block variable is not byref");
4498 isNestedCapturedVar =
true;
4504 if (!isNestedCapturedVar)
4508 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
4509 InitExprs.push_back(Exp);
4512 if (ImportedBlockDecls.size()) {
4519 InitExprs.push_back(FlagExp);
4526 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
4528 BlockDeclRefs.clear();
4529 BlockByRefDecls.clear();
4530 BlockByRefDeclsPtrSet.clear();
4531 BlockByCopyDecls.clear();
4532 BlockByCopyDeclsPtrSet.clear();
4533 ImportedBlockDecls.clear();
4537 bool RewriteObjC::IsDeclStmtInForeachHeader(
DeclStmt *DS) {
4539 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4540 return CS->getElement() == DS;
4548 Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(
Stmt *S) {
4549 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4550 isa<DoStmt>(S) || isa<ForStmt>(S))
4552 else if (isa<ObjCForCollectionStmt>(S)) {
4554 ObjCBcLabelNo.push_back(++BcLabelCount);
4561 return RewritePropertyOrImplicitSetter(PseudoOp);
4563 return RewritePropertyOrImplicitGetter(PseudoOp);
4565 }
else if (
ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4566 return RewriteObjCIvarRefExpr(IvarRefExpr);
4574 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4576 childStmt = newStmt;
4580 if (
BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
4582 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
4583 InnerContexts.insert(BE->getBlockDecl());
4584 ImportedLocalExternalDecls.clear();
4585 GetInnerBlockDeclRefExprs(BE->getBody(),
4586 InnerBlockDeclRefs, InnerContexts);
4588 Stmt *SaveCurrentBody = CurrentBody;
4589 CurrentBody = BE->getBody();
4590 PropParentMap =
nullptr;
4596 bool saveDisableReplaceStmt = DisableReplaceStmt;
4597 DisableReplaceStmt =
false;
4598 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4599 DisableReplaceStmt = saveDisableReplaceStmt;
4600 CurrentBody = SaveCurrentBody;
4601 PropParentMap =
nullptr;
4602 ImportedLocalExternalDecls.clear();
4605 RewrittenBlockExprs[BE] = Str;
4607 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4610 ReplaceStmt(S, blockTranscribed);
4611 return blockTranscribed;
4615 return RewriteAtEncode(AtEncode);
4618 return RewriteAtSelector(AtSelector);
4621 return RewriteObjCStringLiteral(AtString);
4632 std::string messString;
4633 messString +=
"// ";
4634 messString.append(startBuf, endBuf-startBuf+1);
4643 return RewriteMessageExpr(MessExpr);
4647 return RewriteObjCTryStmt(StmtTry);
4650 return RewriteObjCSynchronizedStmt(StmtTry);
4653 return RewriteObjCThrowStmt(StmtThrow);
4656 return RewriteObjCProtocolExpr(ProtocolExp);
4659 dyn_cast<ObjCForCollectionStmt>(S))
4660 return RewriteObjCForCollectionStmt(StmtForCollection,
4663 dyn_cast<BreakStmt>(S))
4664 return RewriteBreakStmt(StmtBreakStmt);
4666 dyn_cast<ContinueStmt>(S))
4667 return RewriteContinueStmt(StmtContinueStmt);
4671 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4681 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4682 RewriteObjCQualifiedInterfaceTypes(*DS->
decl_begin());
4685 for (
auto *SD : DS->
decls()) {
4686 if (
ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4687 if (isTopLevelBlockPointerType(ND->
getType()))
4688 RewriteBlockPointerDecl(ND);
4690 CheckFunctionPointerDecl(ND->
getType(), ND);
4691 if (
VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4692 if (VD->
hasAttr<BlocksAttr>()) {
4693 static unsigned uniqueByrefDeclCount = 0;
4694 assert(!BlockByRefDeclNo.count(ND) &&
4695 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4696 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4697 RewriteByRefVar(VD);
4700 RewriteTypeOfDecl(VD);
4704 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4705 RewriteBlockPointerDecl(TD);
4706 else if (TD->getUnderlyingType()->isFunctionPointerType())
4707 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4713 RewriteObjCQualifiedInterfaceTypes(CE);
4715 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4716 isa<DoStmt>(S) || isa<ForStmt>(S)) {
4717 assert(!Stmts.empty() &&
"Statement stack is empty");
4718 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
4719 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
4720 &&
"Statement stack mismatch");
4724 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4726 if (VD->
hasAttr<BlocksAttr>())
4727 return RewriteBlockDeclRefExpr(DRE);
4729 return RewriteLocalVariableExternalStorage(DRE);
4732 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
4735 ReplaceStmt(S, BlockCall);
4740 RewriteCastExpr(CE);
4749 llvm::raw_string_ostream Buf(SStr);
4751 const std::string &Str = Buf.str();
4753 printf(
"CAST = %s\n", &Str[0]);
4754 InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
4763 void RewriteObjC::RewriteRecordBody(
RecordDecl *RD) {
4764 for (
auto *FD : RD->
fields()) {
4765 if (isTopLevelBlockPointerType(FD->
getType()))
4766 RewriteBlockPointerDecl(FD);
4769 RewriteObjCQualifiedInterfaceTypes(FD);
4775 void RewriteObjC::HandleDeclInMainFile(
Decl *D) {
4785 RewriteBlocksInFunctionProtoType(FD->
getType(), FD);
4792 CurFunctionDef = FD;
4793 CurFunctionDeclToDeclareForBlock = FD;
4796 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4798 CurrentBody =
nullptr;
4799 if (PropParentMap) {
4800 delete PropParentMap;
4801 PropParentMap =
nullptr;
4805 InsertBlockLiteralsWithinFunction(FD);
4806 CurFunctionDef =
nullptr;
4807 CurFunctionDeclToDeclareForBlock =
nullptr;
4811 case Decl::ObjCMethod: {
4817 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4819 CurrentBody =
nullptr;
4820 if (PropParentMap) {
4821 delete PropParentMap;
4822 PropParentMap =
nullptr;
4824 InsertBlockLiteralsWithinMethod(MD);
4825 CurMethodDef =
nullptr;
4829 case Decl::ObjCImplementation: {
4831 ClassImplementation.push_back(CI);
4834 case Decl::ObjCCategoryImpl: {
4836 CategoryImplementation.push_back(CI);
4840 VarDecl *VD = cast<VarDecl>(D);
4841 RewriteObjCQualifiedInterfaceTypes(VD);
4842 if (isTopLevelBlockPointerType(VD->
getType()))
4843 RewriteBlockPointerDecl(VD);
4845 CheckFunctionPointerDecl(VD->
getType(), VD);
4848 RewriteCastExpr(CE);
4854 RewriteRecordBody(RD);
4859 RewriteFunctionBodyOrGlobalInitializer(VD->
getInit());
4860 CurrentBody =
nullptr;
4861 if (PropParentMap) {
4862 delete PropParentMap;
4863 PropParentMap =
nullptr;
4866 GlobalVarDecl =
nullptr;
4870 RewriteCastExpr(CE);
4875 case Decl::TypeAlias:
4876 case Decl::Typedef: {
4878 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4879 RewriteBlockPointerDecl(TD);
4880 else if (TD->getUnderlyingType()->isFunctionPointerType())
4881 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4885 case Decl::CXXRecord:
4886 case Decl::Record: {
4889 RewriteRecordBody(RD);
4898 void RewriteObjC::HandleTranslationUnit(
ASTContext &
C) {
4907 RewriteObjCProtocolMetaData(ProtDecl,
"",
"", Preamble);
4910 if (ClassImplementation.size() || CategoryImplementation.size())
4911 RewriteImplementations();
4918 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
4920 llvm::errs() <<
"No changes\n";
4923 if (ClassImplementation.size() || CategoryImplementation.size() ||
4924 ProtocolExprDecls.size()) {
4926 std::string ResultStr;
4927 RewriteMetaDataIntoBuffer(ResultStr);
4929 *OutFile << ResultStr;
4934 void RewriteObjCFragileABI::Initialize(
ASTContext &context) {
4935 InitializeCommon(context);
4940 Preamble =
"#pragma once\n";
4941 Preamble +=
"struct objc_selector; struct objc_class;\n";
4942 Preamble +=
"struct __rw_objc_super { struct objc_object *object; ";
4943 Preamble +=
"struct objc_object *superClass; ";
4944 if (LangOpts.MicrosoftExt) {
4946 Preamble +=
"__rw_objc_super(struct objc_object *o, struct objc_object *s) " 4948 Preamble +=
"object(o), superClass(s) {} ";
4951 Preamble +=
"#ifndef _REWRITER_typedef_Protocol\n";
4952 Preamble +=
"typedef struct objc_object Protocol;\n";
4953 Preamble +=
"#define _REWRITER_typedef_Protocol\n";
4954 Preamble +=
"#endif\n";
4955 if (LangOpts.MicrosoftExt) {
4956 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
4957 Preamble +=
"#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
4959 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern\n";
4960 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
4961 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4962 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
4963 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4964 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
4965 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4966 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
4967 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4968 Preamble +=
"__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
4969 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4970 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
4971 Preamble +=
"(const char *);\n";
4972 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
4973 Preamble +=
"(struct objc_class *);\n";
4974 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
4975 Preamble +=
"(const char *);\n";
4976 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
4977 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
4978 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
4979 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
4980 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_exception_match";
4981 Preamble +=
"(struct objc_class *, struct objc_object *);\n";
4983 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
4984 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
4985 Preamble +=
"__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
4986 Preamble +=
"#ifndef __FASTENUMERATIONSTATE\n";
4987 Preamble +=
"struct __objcFastEnumerationState {\n\t";
4988 Preamble +=
"unsigned long state;\n\t";
4989 Preamble +=
"void **itemsPtr;\n\t";
4990 Preamble +=
"unsigned long *mutationsPtr;\n\t";
4991 Preamble +=
"unsigned long extra[5];\n};\n";
4992 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
4993 Preamble +=
"#define __FASTENUMERATIONSTATE\n";
4994 Preamble +=
"#endif\n";
4995 Preamble +=
"#ifndef __NSCONSTANTSTRINGIMPL\n";
4996 Preamble +=
"struct __NSConstantStringImpl {\n";
4997 Preamble +=
" int *isa;\n";
4998 Preamble +=
" int flags;\n";
4999 Preamble +=
" char *str;\n";
5000 Preamble +=
" long length;\n";
5002 Preamble +=
"#ifdef CF_EXPORT_CONSTANT_STRING\n";
5003 Preamble +=
"extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5004 Preamble +=
"#else\n";
5005 Preamble +=
"__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5006 Preamble +=
"#endif\n";
5007 Preamble +=
"#define __NSCONSTANTSTRINGIMPL\n";
5008 Preamble +=
"#endif\n";
5010 Preamble +=
"#ifndef BLOCK_IMPL\n";
5011 Preamble +=
"#define BLOCK_IMPL\n";
5012 Preamble +=
"struct __block_impl {\n";
5013 Preamble +=
" void *isa;\n";
5014 Preamble +=
" int Flags;\n";
5015 Preamble +=
" int Reserved;\n";
5016 Preamble +=
" void *FuncPtr;\n";
5018 Preamble +=
"// Runtime copy/destroy helper functions (from Block_private.h)\n";
5019 Preamble +=
"#ifdef __OBJC_EXPORT_BLOCKS\n";
5020 Preamble +=
"extern \"C\" __declspec(dllexport) " 5021 "void _Block_object_assign(void *, const void *, const int);\n";
5022 Preamble +=
"extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5023 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5024 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5025 Preamble +=
"#else\n";
5026 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5027 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5028 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5029 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5030 Preamble +=
"#endif\n";
5031 Preamble +=
"#endif\n";
5032 if (LangOpts.MicrosoftExt) {
5033 Preamble +=
"#undef __OBJC_RW_DLLIMPORT\n";
5034 Preamble +=
"#undef __OBJC_RW_STATICIMPORT\n";
5035 Preamble +=
"#ifndef KEEP_ATTRIBUTES\n";
5036 Preamble +=
"#define __attribute__(X)\n";
5037 Preamble +=
"#endif\n";
5038 Preamble +=
"#define __weak\n";
5041 Preamble +=
"#define __block\n";
5042 Preamble +=
"#define __weak\n";
5046 Preamble +=
"\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5051 void RewriteObjCFragileABI::RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
5052 std::string &Result) {
5058 Result +=
"__OFFSETOFIVAR__(struct ";
5060 if (LangOpts.MicrosoftExt)
5069 void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
5071 StringRef ClassName, std::string &Result) {
5072 static bool objc_protocol_methods =
false;
5081 Result +=
"\nstruct _protocol_methods {\n";
5082 Result +=
"\tstruct objc_selector *_cmd;\n";
5083 Result +=
"\tchar *method_types;\n";
5086 objc_protocol_methods =
true;
5103 Result +=
"\nstatic struct {\n";
5104 Result +=
"\tint protocol_method_count;\n";
5105 Result +=
"\tstruct _protocol_methods protocol_methods[";
5106 Result += utostr(NumMethods);
5107 Result +=
"];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
5109 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 5110 "{\n\t" + utostr(NumMethods) +
"\n";
5117 Result +=
"\t ,{{(struct objc_selector *)\"";
5119 Result +=
"\t ,{(struct objc_selector *)\"";
5120 Result += (*I)->getSelector().getAsString();
5123 Result += MethodTypeString;
5126 Result +=
"\t }\n};\n";
5132 if (NumMethods > 0) {
5138 Result +=
"\nstatic struct {\n";
5139 Result +=
"\tint protocol_method_count;\n";
5140 Result +=
"\tstruct _protocol_methods protocol_methods[";
5141 Result += utostr(NumMethods);
5142 Result +=
"];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
5144 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5146 Result += utostr(NumMethods);
5154 Result +=
"\t ,{{(struct objc_selector *)\"";
5156 Result +=
"\t ,{(struct objc_selector *)\"";
5157 Result += (*I)->getSelector().getAsString();
5160 Result += MethodTypeString;
5163 Result +=
"\t }\n};\n";
5176 static bool objc_protocol =
false;
5177 if (!objc_protocol) {
5178 Result +=
"\nstruct _objc_protocol {\n";
5179 Result +=
"\tstruct _objc_protocol_extension *isa;\n";
5180 Result +=
"\tchar *protocol_name;\n";
5181 Result +=
"\tstruct _objc_protocol **protocol_list;\n";
5182 Result +=
"\tstruct _objc_protocol_method_list *instance_methods;\n";
5183 Result +=
"\tstruct _objc_protocol_method_list *class_methods;\n";
5186 objc_protocol =
true;
5189 Result +=
"\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
5191 Result +=
" __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 5194 Result +=
"\", 0, ";
5196 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
5203 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
5213 llvm_unreachable(
"protocol already synthesized");
5216 void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
5218 StringRef prefix, StringRef ClassName,
5219 std::string &Result) {
5220 if (Protocols.
empty())
return;
5222 for (
unsigned i = 0; i != Protocols.
size(); i++)
5223 RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
5232 Result +=
"\nstatic struct {\n";
5233 Result +=
"\tstruct _objc_protocol_list *next;\n";
5234 Result +=
"\tint protocol_count;\n";
5235 Result +=
"\tstruct _objc_protocol *class_protocols[";
5236 Result += utostr(Protocols.
size());
5237 Result +=
"];\n} _OBJC_";
5239 Result +=
"_PROTOCOLS_";
5240 Result += ClassName;
5241 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5243 Result += utostr(Protocols.
size());
5246 Result +=
"\t,{&_OBJC_PROTOCOL_";
5247 Result += Protocols[0]->getNameAsString();
5250 for (
unsigned i = 1; i != Protocols.
size(); i++) {
5251 Result +=
"\t ,&_OBJC_PROTOCOL_";
5252 Result += Protocols[
i]->getNameAsString();
5255 Result +=
"\t }\n};\n";
5259 std::string &Result) {
5266 RewriteObjCInternalStruct(CDecl, Result);
5274 static bool objc_ivar =
false;
5282 Result +=
"\nstruct _objc_ivar {\n";
5283 Result +=
"\tchar *ivar_name;\n";
5284 Result +=
"\tchar *ivar_type;\n";
5285 Result +=
"\tint ivar_offset;\n";
5296 Result +=
"\nstatic struct {\n";
5297 Result +=
"\tint ivar_count;\n";
5298 Result +=
"\tstruct _objc_ivar ivar_list[";
5299 Result += utostr(NumIvars);
5300 Result +=
"];\n} _OBJC_INSTANCE_VARIABLES_";
5302 Result +=
" __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 5304 Result += utostr(NumIvars);
5310 for (
auto *IV : IDecl->
ivars())
5311 IVars.push_back(IV);
5318 Result +=
"\t,{{\"";
5319 Result += IVI->getNameAsString();
5321 std::string TmpString, StrEncoding;
5323 QuoteDoublequotes(TmpString, StrEncoding);
5324 Result += StrEncoding;
5326 RewriteIvarOffsetComputation(*IVI, Result);
5328 for (++IVI; IVI != IVE; ++IVI) {
5329 Result +=
"\t ,{\"";
5330 Result += IVI->getNameAsString();
5332 std::string TmpString, StrEncoding;
5334 QuoteDoublequotes(TmpString, StrEncoding);
5335 Result += StrEncoding;
5337 RewriteIvarOffsetComputation(*IVI, Result);
5341 Result +=
"\t }\n};\n";
5352 if (!Prop->getPropertyIvarDecl())
5358 if (!Getter->isDefined())
5359 InstanceMethods.push_back(Getter);
5363 if (!Setter->isDefined())
5364 InstanceMethods.push_back(Setter);
5366 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5393 static bool objc_class =
false;
5395 Result +=
"\nstruct _objc_class {\n";
5396 Result +=
"\tstruct _objc_class *isa;\n";
5397 Result +=
"\tconst char *super_class_name;\n";
5398 Result +=
"\tchar *name;\n";
5399 Result +=
"\tlong version;\n";
5400 Result +=
"\tlong info;\n";
5401 Result +=
"\tlong instance_size;\n";
5402 Result +=
"\tstruct _objc_ivar_list *ivars;\n";
5403 Result +=
"\tstruct _objc_method_list *methods;\n";
5404 Result +=
"\tstruct objc_cache *cache;\n";
5405 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5406 Result +=
"\tconst char *ivar_layout;\n";
5407 Result +=
"\tstruct _objc_class_ext *ext;\n";
5415 while (SuperClass) {
5416 RootClass = SuperClass;
5421 Result +=
"\nstatic struct _objc_class _OBJC_METACLASS_";
5423 Result +=
" __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 5424 "{\n\t(struct _objc_class *)\"";
5436 Result +=
", 0, \"";
5442 Result +=
", 0,2, sizeof(struct _objc_class), 0";
5444 Result +=
"\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
5451 Result +=
"\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
5456 Result +=
"\t,0,0,0,0\n";
5460 Result +=
"\nstatic struct _objc_class _OBJC_CLASS_";
5462 Result +=
" __attribute__ ((used, section (\"__OBJC, __class\")))= " 5463 "{\n\t&_OBJC_METACLASS_";
5473 Result +=
", 0, \"";
5479 if (!ObjCSynthesizedStructs.count(CDecl))
5483 Result +=
",sizeof(struct ";
5485 if (LangOpts.MicrosoftExt)
5490 Result +=
", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
5497 Result +=
", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
5499 Result +=
", 0\n\t";
5504 Result +=
", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
5506 Result +=
", 0,0\n";
5509 Result +=
",0,0,0\n";
5513 void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
5514 int ClsDefCount = ClassImplementation.size();
5515 int CatDefCount = CategoryImplementation.size();
5518 for (
int i = 0; i < ClsDefCount; i++)
5519 RewriteObjCClassMetaData(ClassImplementation[i], Result);
5522 for (
int i = 0; i < CatDefCount; i++)
5523 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
5537 Result +=
"\nstruct _objc_symtab {\n";
5538 Result +=
"\tlong sel_ref_cnt;\n";
5539 Result +=
"\tSEL *refs;\n";
5540 Result +=
"\tshort cls_def_cnt;\n";
5541 Result +=
"\tshort cat_def_cnt;\n";
5542 Result +=
"\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+
"];\n";
5545 Result +=
"static struct _objc_symtab " 5546 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
5547 Result +=
"\t0, 0, " + utostr(ClsDefCount)
5548 +
", " + utostr(CatDefCount) +
"\n";
5549 for (
int i = 0; i < ClsDefCount; i++) {
5550 Result +=
"\t,&_OBJC_CLASS_";
5551 Result += ClassImplementation[
i]->getNameAsString();
5555 for (
int i = 0; i < CatDefCount; i++) {
5556 Result +=
"\t,&_OBJC_CATEGORY_";
5557 Result += CategoryImplementation[
i]->getClassInterface()->getNameAsString();
5559 Result += CategoryImplementation[
i]->getNameAsString();
5576 Result +=
"\nstruct _objc_module {\n";
5577 Result +=
"\tlong version;\n";
5578 Result +=
"\tlong size;\n";
5579 Result +=
"\tconst char *name;\n";
5580 Result +=
"\tstruct _objc_symtab *symtab;\n";
5582 Result +=
"static struct _objc_module " 5583 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
5584 Result +=
"\t" + utostr(OBJC_ABI_VERSION) +
5585 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
5588 if (LangOpts.MicrosoftExt) {
5589 if (ProtocolExprDecls.size()) {
5590 Result +=
"#pragma section(\".objc_protocol$B\",long,read,write)\n";
5591 Result +=
"#pragma data_seg(push, \".objc_protocol$B\")\n";
5593 Result +=
"static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
5594 Result += ProtDecl->getNameAsString();
5595 Result +=
" = &_OBJC_PROTOCOL_";
5596 Result += ProtDecl->getNameAsString();
5599 Result +=
"#pragma data_seg(pop)\n\n";
5601 Result +=
"#pragma section(\".objc_module_info$B\",long,read,write)\n";
5602 Result +=
"#pragma data_seg(push, \".objc_module_info$B\")\n";
5603 Result +=
"static struct _objc_module *_POINTER_OBJC_MODULES = ";
5604 Result +=
"&_OBJC_MODULES;\n";
5605 Result +=
"#pragma data_seg(pop)\n\n";
5612 std::string &Result) {
5619 FullCategoryName +=
'_';
5630 if (!Prop->getPropertyIvarDecl())
5636 InstanceMethods.push_back(Getter);
5640 InstanceMethods.push_back(Setter);
5642 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5643 true,
"CATEGORY_", FullCategoryName,
Result);
5647 false,
"CATEGORY_", FullCategoryName,
Result);
5653 FullCategoryName,
Result);
5667 static bool objc_category =
false;
5668 if (!objc_category) {
5669 Result +=
"\nstruct _objc_category {\n";
5670 Result +=
"\tchar *category_name;\n";
5671 Result +=
"\tchar *class_name;\n";
5672 Result +=
"\tstruct _objc_method_list *instance_methods;\n";
5673 Result +=
"\tstruct _objc_method_list *class_methods;\n";
5674 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5675 Result +=
"\tunsigned int size;\n";
5676 Result +=
"\tstruct _objc_property_list *instance_properties;\n";
5678 objc_category =
true;
5680 Result +=
"\nstatic struct _objc_category _OBJC_CATEGORY_";
5681 Result += FullCategoryName;
5682 Result +=
" __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
5684 Result +=
"\"\n\t, \"";
5689 Result +=
"\t, (struct _objc_method_list *)" 5690 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
5691 Result += FullCategoryName;
5695 Result +=
"\t, 0\n";
5697 Result +=
"\t, (struct _objc_method_list *)" 5698 "&_OBJC_CATEGORY_CLASS_METHODS_";
5699 Result += FullCategoryName;
5703 Result +=
"\t, 0\n";
5706 Result +=
"\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
5707 Result += FullCategoryName;
5711 Result +=
"\t, 0\n";
5712 Result +=
"\t, sizeof(struct _objc_category), 0\n};\n";
5717 template<
typename MethodIterator>
5718 void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5719 MethodIterator MethodEnd,
5720 bool IsInstanceMethod,
5722 StringRef ClassName,
5723 std::string &Result) {
5724 if (MethodBegin == MethodEnd)
return;
5726 if (!objc_impl_method) {
5733 Result +=
"\nstruct _objc_method {\n";
5734 Result +=
"\tSEL _cmd;\n";
5735 Result +=
"\tchar *method_types;\n";
5736 Result +=
"\tvoid *_imp;\n";
5739 objc_impl_method =
true;
5750 unsigned NumMethods =
std::distance(MethodBegin, MethodEnd);
5751 Result +=
"\nstatic struct {\n";
5752 Result +=
"\tstruct _objc_method_list *next_method;\n";
5753 Result +=
"\tint method_count;\n";
5754 Result +=
"\tstruct _objc_method method_list[";
5755 Result += utostr(NumMethods);
5756 Result +=
"];\n} _OBJC_";
5758 Result += IsInstanceMethod ?
"INSTANCE" :
"CLASS";
5759 Result +=
"_METHODS_";
5760 Result += ClassName;
5761 Result +=
" __attribute__ ((used, section (\"__OBJC, __";
5762 Result += IsInstanceMethod ?
"inst" :
"cls";
5763 Result +=
"_meth\")))= ";
5764 Result +=
"{\n\t0, " + utostr(NumMethods) +
"\n";
5766 Result +=
"\t,{{(SEL)\"";
5767 Result += (*MethodBegin)->getSelector().getAsString();
5768 std::string MethodTypeString =
5771 Result += MethodTypeString;
5772 Result +=
"\", (void *)";
5773 Result += MethodInternalNames[*MethodBegin];
5775 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
5776 Result +=
"\t ,{(SEL)\"";
5777 Result += (*MethodBegin)->getSelector().getAsString();
5778 std::string MethodTypeString =
5781 Result += MethodTypeString;
5782 Result +=
"\", (void *)";
5783 Result += MethodInternalNames[*MethodBegin];
5786 Result +=
"\t }\n};\n";
5795 DisableReplaceStmtScope S(*
this);
5796 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
5802 Expr *Replacement = IV;
5807 assert(iFaceDecl &&
"RewriteObjCIvarRefExpr - iFaceDecl is null");
5812 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5821 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5841 assert(!IV->
isFreeIvar() &&
"Cannot have a free standing ivar outside a method");
5852 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5855 std::string RecName = clsDeclared->getIdentifier()->getName();
5861 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5876 ReplaceStmtWithRange(IV, Replacement, OldRange);
5880 #endif // CLANG_ENABLE_OBJC_REWRITER unsigned getNumSemanticExprs() const
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
The receiver is the instance of the superclass object.
const BlockDecl * getBlockDecl() const
QualType withConst() const
Retrieves a version of this type with const applied.
Represents a function declaration or definition.
The receiver is an object instance.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=CSK_unspecified)
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
bool hasErrorOccurred() const
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
const FunctionProtoType * getFunctionType() const
getFunctionType - Return the underlying function type for this block.
QualType getObjCIdType() const
Represents the Objective-CC id type.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isBlockPointerType() const
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Selector getSelector() const
ObjCInterfaceDecl * getClassInterface()
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
ObjCIvarDecl * getPropertyIvarDecl() const
SourceLocation getRParenLoc() const
ObjCProtocolDecl * getProtocol() const
Stmt - This represents one statement.
const ObjCProtocolList & getReferencedProtocols() const
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
bool isRealFloatingType() const
Floating point categories.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Defines the SourceManager interface.
bool isRecordType() const
Decl - This represents one declaration (or definition), e.g.
bool isVariadic() const
Whether this function prototype is variadic.
SourceLocation getBeginLoc() const LLVM_READONLY
param_iterator param_end()
ParenExpr - This represents a parethesized expression, e.g.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
The base class of the type hierarchy.
Represents Objective-C's @throw statement.
static bool IsHeaderFile(const std::string &Filename)
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
const ObjCObjectPointerType * getAsObjCInterfacePointerType() const
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
protocol_iterator protocol_begin() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getLParenLoc() const
A container of type source information.
instmeth_iterator instmeth_end() const
Floating point control options.
constexpr XRayInstrMask Function
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
MutableArrayRef< ParmVarDecl * >::iterator param_iterator
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
Represents a variable declaration or definition.
CompoundLiteralExpr - [C99 6.5.2.5].
unsigned getNumParams() const
const T * getAs() const
Member-template getAs<specific type>'.
Extra information about a function prototype.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on...
ObjCMethodDecl - Represents an instance or class method declaration.
SourceLocation getLeftLoc() const
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
std::string getRewrittenText(CharSourceRange Range) const
getRewrittenText - Return the rewritten form of the text in the specified range.
QualType getObjCClassType() const
Represents the Objective-C Class type.
Describes how types, statements, expressions, and declarations should be printed. ...
classmeth_range class_methods() const
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represents a struct/union/class.
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
instprop_range instance_properties() const
One of these records is kept for each identifier that is lexed.
QualType IgnoreParens() const
Returns the specified type after dropping any outer-level parentheses.
Represents a class type in Objective C.
static RecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl=nullptr)
QualType getPointeeType() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
field_range fields() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a member of a struct/union/class.
static ObjCMessageExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, ArrayRef< SourceLocation > SelLocs, ObjCMethodDecl *Method, ArrayRef< Expr *> Args, SourceLocation RBracLoc, bool isImplicit)
Create a message send to super.
instmeth_range instance_methods() const
StringLiteral * getString()
std::string getNameAsString() const
Get the name of the class associated with this interface.
SourceLocation getRParenLoc() const
ObjCMethodDecl * getSetterMethodDecl() const
protocol_iterator protocol_end() const
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isObjCQualifiedClassType() const
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
Selector getSelector() const
Represents Objective-C's @catch statement.
Describes an C or C++ initializer list.
bool isBitField() const
Determines whether this field is a bitfield.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
const Expr * getThrowExpr() const
filtered_decl_iterator< ObjCMethodDecl, &ObjCMethodDecl::isInstanceMethod > instmeth_iterator
unsigned ivar_size() const
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
PropertyAttributeKind getPropertyAttributes() const
Concrete class used by the front-end to report problems and issues.
Represents a typeof (or typeof) expression (a GCC extension).
const clang::PrintingPolicy & getPrintingPolicy() const
Represents a declaration of a type.
A builtin binary operation expression such as "x + y" or "x <= y".
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
std::unique_ptr< ASTConsumer > CreateObjCRewriter(const std::string &InFile, std::unique_ptr< raw_ostream > OS, DiagnosticsEngine &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning)
SourceLocation getBeginLoc() const LLVM_READONLY
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
Defines the Diagnostic-related interfaces.
ObjCStringLiteral, used for Objective-C string literals i.e.
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CompoundStmt * getCompoundBody()
Represents an Objective-C protocol declaration.
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
An ordinary object is located at an address in memory.
Represents an ObjC class declaration.
Represents a linkage specification.
QualType getReturnType() const
SourceLocation getTypeSpecStartLoc() const
const Stmt * getBody() const
SourceLocation getAtStartLoc() const
std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended=false) const
Emit the encoded type for the method declaration Decl into S.
const ObjCAtCatchStmt * getCatchStmt(unsigned I) const
Retrieve a @catch statement.
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
ConditionalOperator - The ?: ternary operator.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Represents a prototype with parameter type info, e.g.
CastKind
CastKind - The kind of operation required for a conversion.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat)
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
SourceLocation getLocation() const
SourceLocation getEndLoc() const LLVM_READONLY
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location, which defaults to the empty location.
unsigned ivar_size() const
bool hasDefinition() const
Determine whether this protocol has a definition.
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated)
This is the "fully general" constructor that allows representation of strings formed from multiple co...
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr *> Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
ivar_iterator ivar_end() const
ivar_iterator ivar_begin() const
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
const T * castAs() const
Member-template castAs<specific type>.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration is also the definition.
SourceLocation getEndLoc() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
QualType getTagDeclType(const TagDecl *Decl) const
Return the unique reference to the type for the specified TagDecl (struct/union/class/enum) decl...
const CompoundStmt * getSynchBody() const
DeclContext * getDeclContext()
bool isWrittenInMainFile(SourceLocation Loc) const
Returns true if the spelling location for the given location is in the main file buffer.
Represents Objective-C's @synchronized statement.
ObjCInterfaceDecl * getSuperClass() const
ObjCSelectorExpr used for @selector in Objective-C.
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
SourceLocation getBeginLoc() const LLVM_READONLY
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
ObjCIvarDecl * lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared)
propimpl_range property_impls() const
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type...
const Stmt * getTryBody() const
Retrieve the @try body.
QualType getEncodedType() const
bool isa(CodeGen::Address addr)
An expression that sends a message to the given Objective-C object or class.
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl...
SourceLocation getEnd() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
bool isInstanceMethod() const
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
int getRangeSize(SourceRange Range, RewriteOptions opts=RewriteOptions()) const
getRangeSize - Return the size in bytes of the specified range if they are in the same file...
Selector getSelector() const
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
The result type of a method or function.
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
SourceLocation getBeginLoc() const LLVM_READONLY
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr.cast]), which uses the syntax (Type)expr.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
ImplicitParamDecl * getSelfDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getEndLoc() const
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Expr * getUnderlyingExpr() const
SourceLocation getEndLoc() const LLVM_READONLY
unsigned getCVRQualifiers() const
Retrieve the set of CVR (const-volatile-restrict) qualifiers applied to this type.
static std::string getIvarAccessString(ObjCIvarDecl *OID)
bool isConstQualified() const
Determine whether this type is const-qualified.
param_iterator param_begin()
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver. ...
std::string getAsString() const
Derive the full selector name (e.g.
void setSourceMgr(SourceManager &SM, const LangOptions &LO)
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
param_type_range param_types() const
ivar_iterator ivar_begin() const
classmeth_iterator classmeth_end() const
Encodes a location in the source.
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
QualType getReturnType() const
ivar_iterator ivar_end() const
const Stmt * getCatchBody() const
Interfaces are the core concept in Objective-C for object oriented design.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
const RewriteBuffer * getRewriteBufferFor(FileID FID) const
getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
InsertText - Insert the specified string at the specified location in the original buffer...
static bool HasLocalVariableExternalStorage(ValueDecl *VD)
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super', otherwise an invalid source location.
ObjCCategoryDecl - Represents a category declaration.
decl_iterator decl_begin()
ObjCProtocolExpr used for protocol expression in Objective-C.
bool isObjCObjectPointerType() const
Represents one property declaration in an Objective-C interface.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
bool isImplicitInterfaceDecl() const
isImplicitInterfaceDecl - check that this is an implicitly declared ObjCInterfaceDecl node...
const ObjCMethodDecl * getMethodDecl() const
SourceLocation getBeginLoc() const
classmeth_iterator classmeth_begin() const
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
StringRef getName() const
Return the actual identifier string.
decl_iterator - Iterates through the declarations stored within this context.
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
bool isObjCGCWeak() const
true when Type is objc's weak.
Base class for declarations which introduce a typedef-name.
Expr * getResultExpr()
Return the result-bearing expression, or null if there is none.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
const llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
const ObjCInterfaceDecl * getClassInterface() const
Dataflow Directional Tag Classes.
bool isObjCQualifiedInterfaceType() const
bool isValid() const
Return true if this is a valid SourceLocation object.
ArrayRef< Capture > captures() const
static void scanToNextArgument(const char *&argRef)
Kind getPropertyImplementation() const
SourceLocation getAtLoc() const
QualType getSuperType() const
Retrieve the type referred to by 'super'.
static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, std::string &typedefString)
const ObjCProtocolList & getReferencedProtocols() const
const Expr * getInit() const
FileID getMainFileID() const
Returns the FileID of the main source file.
SourceLocation getBeginLoc() const LLVM_READONLY
int printf(__constant const char *st,...) __attribute__((format(printf
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
bool isBooleanType() const
QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const
Return a K&R style C function type like 'int()'.
U cast(CodeGen::Address addr)
const Expr * getSynchExpr() const
const ObjCInterfaceDecl * getContainingInterface() const
Return the class interface that this ivar is logically contained in; this is either the interface whe...
QualType getCallResultType(const ASTContext &Context) const
Determine the type of an expression that calls a function of this type.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext, providing only those that are of type SpecificDecl (or a class derived from it).
static bool scanForProtocolRefs(const char *startBuf, const char *endBuf, const char *&startRef, const char *&endRef)
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
Represents a pointer to an Objective C object.
unsigned getByteLength() const
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point...
SourceLocation getRParenLoc() const
static void BuildUniqueMethodName(std::string &Name, ObjCMethodDecl *MD)
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Iterator for iterating over Stmt * arrays that contain only T *.
Represents Objective-C's collection statement.
ObjCEncodeExpr, used for @encode in Objective-C.
static CStyleCastExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R)
uint64_t getCharWidth() const
Return the size of the character type, in bits.
protocol_iterator protocol_begin() const
void getObjCEncodingForType(QualType T, std::string &S, const FieldDecl *Field=nullptr, QualType *NotEncodedT=nullptr) const
Emit the Objective-CC type encoding for the given type T into S.
bool isObjCQualifiedIdType() const
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
Represents Objective-C's @finally statement.
void addDecl(Decl *D)
Add the declaration D into this context.
const Expr * getBase() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
SourceManager & getSourceManager()
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
SourceRange getAtEndRange() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
SourceLocation getBeginLoc() const
Rewriter - This is the main interface to the rewrite buffers.
QualType getParamType(unsigned i) const
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\, const ASTContext *Context=nullptr) const
TranslationUnitDecl * getTranslationUnitDecl() const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ContinueStmt - This represents a continue.
SourceLocation getBeginLoc() const LLVM_READONLY
filtered_decl_iterator< ObjCMethodDecl, &ObjCMethodDecl::isClassMethod > classmeth_iterator
ObjCIvarDecl - Represents an ObjC instance variable.
static bool isRewritable(SourceLocation Loc)
isRewritable - Return true if this location is a raw file location, which is rewritable.
static TypedefDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
Represents Objective-C's @try ... @catch ... @finally statement.
protocol_iterator protocol_end() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
unsigned getNumCatchStmts() const
Retrieve the number of @catch statements in this try-catch-finally block.
StringLiteral - This represents a string literal expression, e.g.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
SourceLocation getBeginLoc() const LLVM_READONLY
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
StringRef getName() const
getName - Get the name of identifier for the class interface associated with this implementation as a...
The top declaration context.
A reference to a declared variable, function, enum, etc.
ObjCPropertyDecl * getPropertyDecl() const
SourceLocation getBeginLoc() const
bool isPointerType() const
BreakStmt - This represents a break.
Expr * getSemanticExpr(unsigned index)
const VarDecl * getCatchParamDecl() const
An l-value expression is a reference to an object with independent storage.
A trivial tuple used to represent a source range.
instmeth_iterator instmeth_begin() const
ObjCMethodDecl * getGetterMethodDecl() const
This represents a decl that may have a name.
SourceLocation getEndOfDefinitionLoc() const
SourceLocation getRightLoc() const
bool isFunctionPointerType() const
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
The receiver is a superclass.
void getSelectorLocs(SmallVectorImpl< SourceLocation > &SelLocs) const
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
FullSourceLoc getFullLoc(SourceLocation Loc) const
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
SourceLocation getBeginLoc() const LLVM_READONLY
This class handles loading and caching of source files into memory.
bool BlockRequiresCopying(QualType Ty, const VarDecl *D)
Returns true iff we need copy/dispose helpers for the given type.
SourceLocation getLocation() const
ArrayRef< ParmVarDecl * > parameters() const
TypeSourceInfo * getClassReceiverTypeInfo() const
Returns a type-source information of a class message send, or nullptr if the message is not a class m...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
ObjCCategoryDecl * FindCategoryDeclaration(IdentifierInfo *CategoryId) const
FindCategoryDeclaration - Finds category declaration in the list of categories for this class and ret...