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
35using llvm::RewriteBuffer;
55 BLOCK_NEEDS_FREE = (1 << 24),
56 BLOCK_HAS_COPY_DISPOSE = (1 << 25),
58 BLOCK_IS_GC = (1 << 27),
60 BLOCK_HAS_DESCRIPTOR = (1 << 29)
62 static const int OBJC_ABI_VERSION = 7;
71 const char *MainFileStart, *MainFileEnd;
74 std::string InFileName;
75 std::unique_ptr<raw_ostream> OutFile;
80 unsigned RewriteFailedDiag;
82 unsigned NumObjCStringLiterals;
83 VarDecl *ConstantStringClassReference;
89 unsigned TryFinallyContainsReturnDiag;
115 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
121 llvm::DenseSet<uint64_t> CopyDestroyCache;
135 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
139 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
144 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
148 bool SilenceRewriteMacroWarning;
149 bool objc_impl_method;
151 bool DisableReplaceStmt;
152 class DisableReplaceStmtScope {
157 DisableReplaceStmtScope(RewriteObjC &R)
158 : R(R), SavedValue(R.DisableReplaceStmt) {
159 R.DisableReplaceStmt =
true;
162 ~DisableReplaceStmtScope() {
163 R.DisableReplaceStmt = SavedValue;
174 if (!
Class->isThisDeclarationADefinition()) {
175 RewriteForwardClassDecl(
D);
181 if (!Proto->isThisDeclarationADefinition()) {
182 RewriteForwardProtocolDecl(
D);
187 HandleTopLevelSingleDecl(*I);
192 void HandleTopLevelSingleDecl(
Decl *
D);
193 void HandleDeclInMainFile(
Decl *
D);
194 RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
196 bool silenceMacroWarn);
198 ~RewriteObjC()
override {}
200 void HandleTranslationUnit(
ASTContext &C)
override;
202 void ReplaceStmt(
Stmt *Old,
Stmt *New) {
207 assert(Old !=
nullptr && New !=
nullptr &&
"Expected non-null Stmt's");
209 Stmt *ReplacingStmt = ReplacedNodes[Old];
213 if (DisableReplaceStmt)
225 llvm::raw_string_ostream S(SStr);
227 const std::string &Str = S.str();
231 ReplacedNodes[Old] = New;
234 if (SilenceRewriteMacroWarning)
241 bool InsertAfter =
true) {
243 if (!
Rewrite.InsertText(
Loc, Str, InsertAfter) ||
244 SilenceRewriteMacroWarning)
247 Diags.
Report(Context->getFullLoc(
Loc), RewriteFailedDiag);
253 if (!
Rewrite.ReplaceText(Start, OrigLength, Str) ||
254 SilenceRewriteMacroWarning)
257 Diags.
Report(Context->getFullLoc(Start), RewriteFailedDiag);
262 void RewriteInclude();
266 const std::string &typedefString);
267 void RewriteImplementations();
272 void RewriteImplementationDecl(
Decl *Dcl);
275 void RewriteTypeIntoString(
QualType T, std::string &ResultStr,
277 void RewriteByRefString(std::string &ResultStr,
const std::string &Name,
286 void RewriteBlockPointerType(std::string& Str,
QualType Type);
287 void RewriteBlockPointerTypeVariable(std::string& Str,
ValueDecl *VD);
289 void RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl);
290 void RewriteTypeOfDecl(
VarDecl *VD);
291 void RewriteObjCQualifiedInterfaceTypes(
Expr *
E);
294 Stmt *RewriteFunctionBodyOrGlobalInitializer(
Stmt *S);
302 void RewriteTryReturnStmts(
Stmt *S);
303 void RewriteSyncReturnStmts(
Stmt *S, std::string buf);
317 void RewriteBlockPointerDecl(
NamedDecl *VD);
318 void RewriteByRefVar(
VarDecl *VD);
324 std::string &Result);
326 void Initialize(
ASTContext &context)
override = 0;
329 virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;
333 std::string &Result) = 0;
335 std::string &Result) = 0;
339 std::string &Result) = 0;
341 std::string &Result) = 0;
345 virtual void RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
346 std::string &Result) = 0;
364 void SynthCountByEnumWithState(std::string &buf);
365 void SynthMsgSendFunctionDecl();
366 void SynthMsgSendSuperFunctionDecl();
367 void SynthMsgSendStretFunctionDecl();
368 void SynthMsgSendFpretFunctionDecl();
369 void SynthMsgSendSuperStretFunctionDecl();
370 void SynthGetClassFunctionDecl();
371 void SynthGetMetaClassFunctionDecl();
372 void SynthGetSuperClassFunctionDecl();
373 void SynthSelGetUidFunctionDecl();
374 void SynthSuperConstructorFunctionDecl();
376 std::string SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
int flag);
377 std::string SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
378 StringRef funcName, std::string Tag);
379 std::string SynthesizeBlockFunc(
BlockExpr *CE,
int i,
380 StringRef funcName, std::string Tag);
381 std::string SynthesizeBlockImpl(
BlockExpr *CE,
382 std::string Tag, std::string Desc);
383 std::string SynthesizeBlockDescriptor(std::string DescTag,
385 int i, StringRef funcName,
390 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
396 void WarnAboutReturnGotoStmts(
Stmt *S);
397 void HasReturnStmts(
Stmt *S,
bool &hasReturns);
399 void InsertBlockLiteralsWithinFunction(
FunctionDecl *FD);
402 bool IsDeclStmtInForeachHeader(
DeclStmt *DS);
403 void CollectBlockDeclRefInfo(
BlockExpr *Exp);
404 void GetBlockDeclRefExprs(
Stmt *S);
405 void GetInnerBlockDeclRefExprs(
Stmt *S,
407 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
411 bool isTopLevelBlockPointerType(
QualType T) {
412 return isa<BlockPointerType>(T);
418 bool convertBlockPointerToFunctionPointer(
QualType &T) {
419 if (isTopLevelBlockPointerType(T)) {
421 T = Context->getPointerType(BPT->getPointeeType());
427 bool needToScanForQualifiers(
QualType T);
429 QualType getConstantStringStructType();
431 bool BufferContainsPPDirectives(
const char *startBuf,
const char *endBuf);
433 void convertToUnqualifiedObjCType(
QualType &T) {
435 T = Context->getObjCIdType();
437 T = Context->getObjCClassType();
444 T = Context->getPointerType(T);
454 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
456 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
457 OCT == Context->getCanonicalType(Context->getObjCClassType()))
461 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
462 PT->getPointeeType()->isObjCQualifiedIdType())
467 bool PointerTypeTakesAnyBlockArguments(
QualType QT);
468 bool PointerTypeTakesAnyObjCQualifiedType(
QualType QT);
469 void GetExtentOfArgList(
const char *Name,
const char *&LParen,
470 const char *&RParen);
472 void QuoteDoublequotes(std::string &From, std::string &To) {
473 for (
unsigned i = 0; i < From.length(); i++) {
483 bool variadic =
false) {
484 if (result == Context->getObjCInstanceType())
485 result = Context->getObjCIdType();
488 return Context->getFunctionType(result, args, fpi);
495 return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue,
Kind,
E,
nullptr,
501 QualType StrType = Context->getConstantArrayType(
502 Context->CharTy, llvm::APInt(32, Str.size() + 1),
nullptr,
503 ArraySizeModifier::Normal, 0);
504 return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,
511 RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
513 bool silenceMacroWarn)
516 ~RewriteObjCFragileABI()
override {}
517 void Initialize(
ASTContext &context)
override;
520 template<
typename MethodIterator>
521 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
522 MethodIterator MethodEnd,
523 bool IsInstanceMethod,
526 std::string &Result);
528 StringRef prefix, StringRef ClassName,
529 std::string &Result)
override;
530 void RewriteObjCProtocolListMetaData(
532 StringRef prefix, StringRef ClassName, std::string &Result)
override;
534 std::string &Result)
override;
535 void RewriteMetaDataIntoBuffer(std::string &Result)
override;
537 std::string &Result)
override;
541 std::string &Result)
override;
546void RewriteObjC::RewriteBlocksInFunctionProtoType(
QualType funcType,
549 = dyn_cast<FunctionProtoType>(funcType.
IgnoreParens())) {
550 for (
const auto &I : fproto->param_types())
551 if (isTopLevelBlockPointerType(I)) {
553 RewriteBlockPointerDecl(
D);
561 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
565static bool IsHeaderFile(
const std::string &
Filename) {
566 std::string::size_type DotPos =
Filename.rfind(
'.');
568 if (DotPos == std::string::npos) {
573 std::string Ext =
Filename.substr(DotPos + 1);
576 return Ext ==
"h" || Ext ==
"hh" || Ext ==
"H";
579RewriteObjC::RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
581 bool silenceMacroWarn)
582 : Diags(
D), LangOpts(LOpts), InFileName(inFile), OutFile(
std::move(OS)),
583 SilenceRewriteMacroWarning(silenceMacroWarn) {
584 IsHeader = IsHeaderFile(inFile);
586 "rewriting sub-expression within a macro (may not be correct)");
588 DiagnosticsEngine::Warning,
589 "rewriter doesn't support user-specified control flow semantics "
590 "for @try/@finally (code may not execute properly)");
593std::unique_ptr<ASTConsumer>
595 std::unique_ptr<raw_ostream> OS,
597 bool SilenceRewriteMacroWarning) {
598 return std::make_unique<RewriteObjCFragileABI>(
599 InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);
602void RewriteObjC::InitializeCommon(
ASTContext &context) {
604 SM = &Context->getSourceManager();
605 TUDecl = Context->getTranslationUnitDecl();
606 MsgSendFunctionDecl =
nullptr;
607 MsgSendSuperFunctionDecl =
nullptr;
608 MsgSendStretFunctionDecl =
nullptr;
609 MsgSendSuperStretFunctionDecl =
nullptr;
610 MsgSendFpretFunctionDecl =
nullptr;
611 GetClassFunctionDecl =
nullptr;
612 GetMetaClassFunctionDecl =
nullptr;
613 GetSuperClassFunctionDecl =
nullptr;
614 SelGetUidFunctionDecl =
nullptr;
615 CFStringFunctionDecl =
nullptr;
616 ConstantStringClassReference =
nullptr;
617 NSStringRecord =
nullptr;
618 CurMethodDef =
nullptr;
619 CurFunctionDef =
nullptr;
620 CurFunctionDeclToDeclareForBlock =
nullptr;
621 GlobalVarDecl =
nullptr;
622 SuperStructDecl =
nullptr;
623 ProtocolTypeDecl =
nullptr;
624 ConstantStringDecl =
nullptr;
626 SuperConstructorFunctionDecl =
nullptr;
627 NumObjCStringLiterals = 0;
628 PropParentMap =
nullptr;
629 CurrentBody =
nullptr;
630 DisableReplaceStmt =
false;
631 objc_impl_method =
false;
634 MainFileID =
SM->getMainFileID();
635 llvm::MemoryBufferRef MainBuf =
SM->getBufferOrFake(MainFileID);
636 MainFileStart = MainBuf.getBufferStart();
637 MainFileEnd = MainBuf.getBufferEnd();
639 Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
646void RewriteObjC::HandleTopLevelSingleDecl(
Decl *
D) {
657 if (
Loc.isInvalid())
return;
661 RewriteFunctionDecl(FD);
662 }
else if (
VarDecl *FVD = dyn_cast<VarDecl>(
D)) {
664 if (FVD->getName() ==
"_NSConstantStringClassReference") {
665 ConstantStringClassReference = FVD;
669 if (
ID->isThisDeclarationADefinition())
670 RewriteInterfaceDecl(
ID);
672 RewriteCategoryDecl(CD);
674 if (PD->isThisDeclarationADefinition())
675 RewriteProtocolDecl(PD);
679 DIEnd = LSD->decls_end();
682 if (!IFace->isThisDeclarationADefinition()) {
686 if (isa<ObjCInterfaceDecl>(*DI) &&
687 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
688 StartLoc == (*DI)->getBeginLoc())
694 }
while (DI != DIEnd);
695 RewriteForwardClassDecl(DG);
701 if (!Proto->isThisDeclarationADefinition()) {
705 if (isa<ObjCProtocolDecl>(*DI) &&
706 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
707 StartLoc == (*DI)->getBeginLoc())
713 }
while (DI != DIEnd);
714 RewriteForwardProtocolDecl(DG);
719 HandleTopLevelSingleDecl(*DI);
724 if (
SM->isWrittenInMainFile(
Loc))
725 return HandleDeclInMainFile(
D);
732void RewriteObjC::RewriteInclude() {
734 StringRef MainBuf =
SM->getBufferData(MainFileID);
735 const char *MainBufStart = MainBuf.begin();
736 const char *MainBufEnd = MainBuf.end();
737 size_t ImportLen = strlen(
"import");
740 for (
const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
741 if (*BufPtr ==
'#') {
742 if (++BufPtr == MainBufEnd)
744 while (*BufPtr ==
' ' || *BufPtr ==
'\t')
745 if (++BufPtr == MainBufEnd)
747 if (!strncmp(BufPtr,
"import", ImportLen)) {
751 ReplaceText(ImportLoc, ImportLen,
"include");
758static std::string getIvarAccessString(
ObjCIvarDecl *OID) {
763 S +=
"_IMPL *)self)->";
771 static bool objcGetPropertyDefined =
false;
772 static bool objcSetPropertyDefined =
false;
774 InsertText(startLoc,
"// ");
775 const char *startBuf =
SM->getCharacterData(startLoc);
776 assert((*startBuf ==
'@') &&
"bogus @synthesize location");
777 const char *semiBuf = strchr(startBuf,
';');
778 assert((*semiBuf ==
';') &&
"@synthesize: can't find ';'");
794 bool GenGetProperty =
795 !(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&
796 (Attributes & (ObjCPropertyAttribute::kind_retain |
797 ObjCPropertyAttribute::kind_copy));
799 if (GenGetProperty && !objcGetPropertyDefined) {
800 objcGetPropertyDefined =
true;
802 Getr =
"\nextern \"C\" __declspec(dllimport) "
803 "id objc_getProperty(id, SEL, long, bool);\n";
810 if (GenGetProperty) {
823 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
825 std::string ParamStr =
826 FT->getParamType(i).getAsString(Context->getPrintingPolicy());
829 if (FT->isVariadic()) {
830 if (FT->getNumParams())
839 Getr +=
"return (_TYPE)";
840 Getr +=
"objc_getProperty(self, _cmd, ";
841 RewriteIvarOffsetComputation(OID, Getr);
845 Getr +=
"return " + getIvarAccessString(OID);
847 InsertText(onePastSemiLoc, Getr);
856 bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |
857 ObjCPropertyAttribute::kind_copy);
858 if (GenSetProperty && !objcSetPropertyDefined) {
859 objcSetPropertyDefined =
true;
861 Setr =
"\nextern \"C\" __declspec(dllimport) "
862 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
870 if (GenSetProperty) {
871 Setr +=
"objc_setProperty (self, _cmd, ";
872 RewriteIvarOffsetComputation(OID, Setr);
876 if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
880 if (Attributes & ObjCPropertyAttribute::kind_copy)
886 Setr += getIvarAccessString(OID) +
" = ";
890 InsertText(onePastSemiLoc, Setr);
894 std::string &typedefString) {
895 typedefString +=
"#ifndef _REWRITER_typedef_";
897 typedefString +=
"\n";
898 typedefString +=
"#define _REWRITER_typedef_";
900 typedefString +=
"\n";
901 typedefString +=
"typedef struct objc_object ";
903 typedefString +=
";\n#endif\n";
907 const std::string &typedefString) {
909 const char *startBuf =
SM->getCharacterData(startLoc);
910 const char *semiPtr = strchr(startBuf,
';');
912 ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);
916 std::string typedefString;
919 if (I ==
D.begin()) {
923 typedefString +=
"// @class ";
925 typedefString +=
";\n";
927 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
930 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
934 std::string typedefString;
935 for (
unsigned i = 0; i <
D.size(); i++) {
938 typedefString +=
"// @class ";
940 typedefString +=
";\n";
942 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
944 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(
D[0]), typedefString);
947void RewriteObjC::RewriteMethodDeclaration(
ObjCMethodDecl *Method) {
955 if (
SM->getExpansionLineNumber(LocEnd) >
956 SM->getExpansionLineNumber(LocStart)) {
957 InsertText(LocStart,
"#if 0\n");
958 ReplaceText(LocEnd, 1,
";\n#endif\n");
960 InsertText(LocStart,
"// ");
967 ReplaceText(
Loc, 0,
"// ");
975 ReplaceText(LocStart, 0,
"// ");
980 RewriteMethodDeclaration(I);
982 RewriteMethodDeclaration(I);
986 strlen(
"@end"),
"/* @end */");
994 ReplaceText(LocStart, 0,
"// ");
997 RewriteMethodDeclaration(I);
999 RewriteMethodDeclaration(I);
1005 ReplaceText(LocEnd, strlen(
"@end"),
"/* @end */");
1008 const char *startBuf =
SM->getCharacterData(LocStart);
1009 const char *endBuf =
SM->getCharacterData(LocEnd);
1010 for (
const char *p = startBuf; p < endBuf; p++) {
1011 if (*p ==
'@' && !strncmp(p+1,
"optional", strlen(
"optional"))) {
1013 ReplaceText(OptionalLoc, strlen(
"@optional"),
"/* @optional */");
1016 else if (*p ==
'@' && !strncmp(p+1,
"required", strlen(
"required"))) {
1018 ReplaceText(OptionalLoc, strlen(
"@required"),
"/* @required */");
1024void RewriteObjC::RewriteForwardProtocolDecl(
DeclGroupRef D) {
1027 llvm_unreachable(
"Invalid SourceLocation");
1029 ReplaceText(LocStart, 0,
"// ");
1036 llvm_unreachable(
"Invalid SourceLocation");
1038 ReplaceText(LocStart, 0,
"// ");
1041void RewriteObjC::RewriteTypeIntoString(
QualType T, std::string &ResultStr,
1061 ResultStr +=
T.getAsString(Context->getPrintingPolicy());
1066 std::string &ResultStr) {
1069 ResultStr +=
"\nstatic ";
1070 RewriteTypeIntoString(OMD->
getReturnType(), ResultStr, FPRetType);
1074 std::string NameStr;
1092 int len = selString.size();
1093 for (
int i = 0; i < len; i++)
1094 if (selString[i] ==
':')
1096 NameStr += selString;
1099 MethodInternalNames[OMD] = NameStr;
1100 ResultStr += NameStr;
1107 QualType selfTy = Context->getObjCInterfaceType(IDecl);
1108 selfTy = Context->getPointerType(selfTy);
1109 if (!LangOpts.MicrosoftExt) {
1111 ResultStr +=
"struct ";
1118 ResultStr += Context->getObjCClassType().getAsString(
1119 Context->getPrintingPolicy());
1121 ResultStr +=
" self, ";
1122 ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
1123 ResultStr +=
" _cmd";
1126 for (
const auto *PDecl : OMD->
parameters()) {
1128 if (PDecl->getType()->isObjCQualifiedIdType()) {
1135 (void)convertBlockPointerToFunctionPointer(QT);
1141 ResultStr +=
", ...";
1150 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
1151 if (i) ResultStr +=
", ";
1152 std::string ParamStr =
1153 FT->getParamType(i).getAsString(Context->getPrintingPolicy());
1154 ResultStr += ParamStr;
1156 if (FT->isVariadic()) {
1157 if (FT->getNumParams())
1168void RewriteObjC::RewriteImplementationDecl(
Decl *OID) {
1171 assert((IMD || CID) &&
"Unknown ImplementationDecl");
1178 std::string ResultStr;
1183 const char *startBuf =
SM->getCharacterData(LocStart);
1184 const char *endBuf =
SM->getCharacterData(LocEnd);
1185 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1191 std::string ResultStr;
1196 const char *startBuf =
SM->getCharacterData(LocStart);
1197 const char *endBuf =
SM->getCharacterData(LocEnd);
1198 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1201 RewritePropertyImplDecl(I, IMD, CID);
1207 std::string ResultStr;
1210 ResultStr =
"#ifndef _REWRITER_typedef_";
1213 ResultStr +=
"#define _REWRITER_typedef_";
1216 ResultStr +=
"typedef struct objc_object ";
1218 ResultStr +=
";\n#endif\n";
1222 RewriteObjCInternalStruct(ClassDecl, ResultStr);
1227 RewriteMethodDeclaration(I);
1229 RewriteMethodDeclaration(I);
1249 DisableReplaceStmtScope S(*
this);
1255 Base = cast<OpaqueValueExpr>(
Base)->getSourceExpr();
1256 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(
Base));
1261 RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
1262 RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1271 case ObjCMessageExpr::Class:
1272 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->
getType(),
1284 case ObjCMessageExpr::Instance:
1285 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->
getType(),
1297 case ObjCMessageExpr::SuperClass:
1298 case ObjCMessageExpr::SuperInstance:
1299 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->
getType(),
1314 Stmt *Replacement = SynthMessageExpr(NewMsg);
1315 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1331 DisableReplaceStmtScope S(*
this);
1336 Base = cast<OpaqueValueExpr>(
Base)->getSourceExpr();
1337 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(
Base));
1347 case ObjCMessageExpr::Class:
1348 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->
getType(),
1360 case ObjCMessageExpr::Instance:
1361 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->
getType(),
1373 case ObjCMessageExpr::SuperClass:
1374 case ObjCMessageExpr::SuperInstance:
1375 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->
getType(),
1390 Stmt *Replacement = SynthMessageExpr(NewMsg);
1391 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1404void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1405 buf +=
"((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
1406 "id *, unsigned int))(void *)objc_msgSend)";
1408 buf +=
"((id)l_collection,\n\t\t";
1409 buf +=
"sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1411 buf +=
"&enumState, "
1412 "(id *)__rw_items, (unsigned int)16)";
1419 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1425 buf =
"goto __break_label_";
1426 buf += utostr(ObjCBcLabelNo.back());
1427 ReplaceText(startLoc, strlen(
"break"), buf);
1436 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1442 buf =
"goto __continue_label_";
1443 buf += utostr(ObjCBcLabelNo.back());
1444 ReplaceText(startLoc, strlen(
"continue"), buf);
1483 assert(!Stmts.empty() &&
"ObjCForCollectionStmt - Statement stack empty");
1484 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1485 "ObjCForCollectionStmt Statement stack mismatch");
1486 assert(!ObjCBcLabelNo.empty() &&
1487 "ObjCForCollectionStmt - Label No stack empty");
1490 const char *startBuf =
SM->getCharacterData(startLoc);
1491 StringRef elementName;
1492 std::string elementTypeAsString;
1495 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
1497 NamedDecl*
D = cast<NamedDecl>(DS->getSingleDecl());
1498 QualType ElementType = cast<ValueDecl>(
D)->getType();
1502 elementTypeAsString =
"id";
1504 elementTypeAsString = ElementType.
getAsString(Context->getPrintingPolicy());
1505 buf += elementTypeAsString;
1507 elementName =
D->getName();
1512 DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
1518 elementTypeAsString =
"id";
1524 buf +=
"struct __objcFastEnumerationState enumState = { 0 };\n\t";
1526 buf +=
"id __rw_items[16];\n\t";
1528 buf +=
"id l_collection = (id)";
1530 const char *startCollectionBuf = startBuf;
1531 startCollectionBuf += 3;
1532 startCollectionBuf = strchr(startCollectionBuf,
'(');
1533 startCollectionBuf++;
1535 while (*startCollectionBuf !=
' ' ||
1536 *(startCollectionBuf+1) !=
'i' || *(startCollectionBuf+2) !=
'n' ||
1537 (*(startCollectionBuf+3) !=
' ' &&
1538 *(startCollectionBuf+3) !=
'[' && *(startCollectionBuf+3) !=
'('))
1539 startCollectionBuf++;
1540 startCollectionBuf += 3;
1543 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1546 const char *rparenBuf =
SM->getCharacterData(rightParenLoc);
1561 buf +=
"unsigned long limit =\n\t\t";
1562 SynthCountByEnumWithState(buf);
1572 buf +=
"if (limit) {\n\t";
1573 buf +=
"unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1574 buf +=
"do {\n\t\t";
1575 buf +=
"unsigned long counter = 0;\n\t\t";
1576 buf +=
"do {\n\t\t\t";
1577 buf +=
"if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1578 buf +=
"objc_enumerationMutation(l_collection);\n\t\t\t";
1581 buf += elementTypeAsString;
1582 buf +=
")enumState.itemsPtr[counter++];";
1584 ReplaceText(lparenLoc, 1, buf);
1598 buf +=
"__continue_label_";
1599 buf += utostr(ObjCBcLabelNo.back());
1602 buf +=
"} while (counter < limit);\n\t";
1603 buf +=
"} while (limit = ";
1604 SynthCountByEnumWithState(buf);
1608 buf += elementTypeAsString;
1610 buf +=
"__break_label_";
1611 buf += utostr(ObjCBcLabelNo.back());
1614 buf +=
"else\n\t\t";
1617 buf += elementTypeAsString;
1623 if (isa<CompoundStmt>(S->getBody())) {
1625 InsertText(endBodyLoc, buf);
1634 const char *stmtBuf =
SM->getCharacterData(OrigEnd);
1635 const char *semiBuf = strchr(stmtBuf,
';');
1636 assert(semiBuf &&
"Can't find ';'");
1638 InsertText(endBodyLoc, buf);
1641 ObjCBcLabelNo.pop_back();
1654 const char *startBuf =
SM->getCharacterData(startLoc);
1656 assert((*startBuf ==
'@') &&
"bogus @synchronized location");
1659 buf =
"objc_sync_enter((id)";
1660 const char *lparenBuf = startBuf;
1661 while (*lparenBuf !=
'(') lparenBuf++;
1662 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1667 const char *endBuf =
SM->getCharacterData(endLoc);
1668 while (*endBuf !=
')') endBuf--;
1672 buf +=
"/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1673 buf +=
"int buf[18/*32-bit i386*/];\n";
1674 buf +=
"char *pointers[4];} _stack;\n";
1675 buf +=
"id volatile _rethrow = 0;\n";
1676 buf +=
"objc_exception_try_enter(&_stack);\n";
1677 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1678 ReplaceText(rparenLoc, 1, buf);
1679 startLoc = S->getSynchBody()->getEndLoc();
1680 startBuf =
SM->getCharacterData(startLoc);
1682 assert((*startBuf ==
'}') &&
"bogus @synchronized block");
1684 buf =
"}\nelse {\n";
1685 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1687 buf +=
"{ /* implicit finally clause */\n";
1688 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1690 std::string syncBuf;
1691 syncBuf +=
" objc_sync_exit(";
1693 Expr *syncExpr = S->getSynchExpr();
1697 ? CK_BlockPointerToObjCPointerCast
1698 : CK_CPointerToObjCPointerCast;
1699 syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
1701 std::string syncExprBufS;
1702 llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1703 assert(syncExpr !=
nullptr &&
"Expected non-null Expr");
1705 syncBuf += syncExprBuf.str();
1709 buf +=
"\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1713 ReplaceText(lastCurlyLoc, 1, buf);
1715 bool hasReturns =
false;
1716 HasReturnStmts(S->getSynchBody(), hasReturns);
1718 RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
1723void RewriteObjC::WarnAboutReturnGotoStmts(
Stmt *S)
1726 for (
Stmt *SubStmt : S->children())
1728 WarnAboutReturnGotoStmts(SubStmt);
1730 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1731 Diags.
Report(Context->getFullLoc(S->getBeginLoc()),
1732 TryFinallyContainsReturnDiag);
1736void RewriteObjC::HasReturnStmts(
Stmt *S,
bool &hasReturns)
1739 for (
Stmt *SubStmt : S->children())
1741 HasReturnStmts(SubStmt, hasReturns);
1743 if (isa<ReturnStmt>(S))
1747void RewriteObjC::RewriteTryReturnStmts(
Stmt *S) {
1749 for (
Stmt *SubStmt : S->children())
1751 RewriteTryReturnStmts(SubStmt);
1753 if (isa<ReturnStmt>(S)) {
1755 const char *startBuf =
SM->getCharacterData(startLoc);
1756 const char *semiBuf = strchr(startBuf,
';');
1757 assert((*semiBuf ==
';') &&
"RewriteTryReturnStmts: can't find ';'");
1761 buf =
"{ objc_exception_try_exit(&_stack); return";
1763 ReplaceText(startLoc, 6, buf);
1764 InsertText(onePastSemiLoc,
"}");
1768void RewriteObjC::RewriteSyncReturnStmts(
Stmt *S, std::string syncExitBuf) {
1770 for (
Stmt *SubStmt : S->children())
1772 RewriteSyncReturnStmts(SubStmt, syncExitBuf);
1774 if (isa<ReturnStmt>(S)) {
1776 const char *startBuf =
SM->getCharacterData(startLoc);
1778 const char *semiBuf = strchr(startBuf,
';');
1779 assert((*semiBuf ==
';') &&
"RewriteSyncReturnStmts: can't find ';'");
1783 buf =
"{ objc_exception_try_exit(&_stack);";
1787 ReplaceText(startLoc, 6, buf);
1788 InsertText(onePastSemiLoc,
"}");
1795 const char *startBuf =
SM->getCharacterData(startLoc);
1797 assert((*startBuf ==
'@') &&
"bogus @try location");
1801 buf =
"/* @try scope begin */ { struct _objc_exception_data {\n";
1802 buf +=
"int buf[18/*32-bit i386*/];\n";
1803 buf +=
"char *pointers[4];} _stack;\n";
1804 buf +=
"id volatile _rethrow = 0;\n";
1805 buf +=
"objc_exception_try_enter(&_stack);\n";
1806 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1808 ReplaceText(startLoc, 4, buf);
1810 startLoc = S->getTryBody()->getEndLoc();
1811 startBuf =
SM->getCharacterData(startLoc);
1813 assert((*startBuf ==
'}') &&
"bogus @try block");
1816 if (S->getNumCatchStmts()) {
1818 buf =
" /* @catch begin */ else {\n";
1819 buf +=
" id _caught = objc_exception_extract(&_stack);\n";
1820 buf +=
" objc_exception_try_enter (&_stack);\n";
1821 buf +=
" if (_setjmp(_stack.buf))\n";
1822 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1823 buf +=
" else { /* @catch continue */";
1825 InsertText(startLoc, buf);
1827 buf =
"}\nelse {\n";
1828 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1830 ReplaceText(lastCurlyLoc, 1, buf);
1832 Stmt *lastCatchBody =
nullptr;
1833 for (
unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
1842 startBuf =
SM->getCharacterData(startLoc);
1844 assert((*startBuf ==
'@') &&
"bogus @catch location");
1846 const char *lParenLoc = strchr(startBuf,
'(');
1852 const char *bodyBuf =
SM->getCharacterData(bodyLoc);
1854 "bogus @catch paren location");
1855 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1857 buf +=
"1) { id _tmp = _caught;";
1858 Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
1859 }
else if (catchDecl) {
1861 if (t == Context->getObjCIdType()) {
1863 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1869 buf +=
"objc_exception_match((struct objc_class *)objc_getClass(\"";
1871 buf +=
"\"), (struct objc_object *)_caught)) { ";
1872 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1879 const char *bodyBuf =
SM->getCharacterData(bodyLoc);
1880 const char *rParenBuf =
SM->getCharacterData(rParenLoc);
1881 assert((*rParenBuf ==
')') &&
"bogus @catch paren location");
1882 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1886 ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
" = _caught;");
1888 llvm_unreachable(
"@catch rewrite bug");
1892 if (lastCatchBody) {
1894 assert(*
SM->getCharacterData(bodyLoc) ==
'}' &&
1895 "bogus @catch body location");
1899 buf =
"} /* last catch end */\n";
1901 buf +=
" _rethrow = _caught;\n";
1902 buf +=
" objc_exception_try_exit(&_stack);\n";
1903 buf +=
"} } /* @catch end */\n";
1904 if (!S->getFinallyStmt())
1906 InsertText(bodyLoc, buf);
1909 lastCurlyLoc = lastCatchBody->
getEndLoc();
1912 startLoc = finalStmt->getBeginLoc();
1913 startBuf =
SM->getCharacterData(startLoc);
1914 assert((*startBuf ==
'@') &&
"bogus @finally start");
1916 ReplaceText(startLoc, 8,
"/* @finally */");
1918 Stmt *body = finalStmt->getFinallyBody();
1921 assert(*
SM->getCharacterData(startLoc) ==
'{' &&
1922 "bogus @finally body location");
1923 assert(*
SM->getCharacterData(endLoc) ==
'}' &&
1924 "bogus @finally body location");
1927 InsertText(startLoc,
" if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1929 InsertText(endLoc,
" if (_rethrow) objc_exception_throw(_rethrow);\n");
1935 WarnAboutReturnGotoStmts(S->getTryBody());
1937 buf =
"{ /* implicit finally clause */\n";
1938 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1939 buf +=
" if (_rethrow) objc_exception_throw(_rethrow);\n";
1941 ReplaceText(lastCurlyLoc, 1, buf);
1946 bool hasReturns =
false;
1947 HasReturnStmts(S->getTryBody(), hasReturns);
1949 RewriteTryReturnStmts(S->getTryBody());
1953 InsertText(lastCurlyLoc,
" } /* @try scope end */\n");
1963 const char *startBuf =
SM->getCharacterData(startLoc);
1965 assert((*startBuf ==
'@') &&
"bogus @throw location");
1969 if (S->getThrowExpr())
1970 buf =
"objc_exception_throw(";
1972 buf =
"objc_exception_throw(_caught";
1975 const char *wBuf = strchr(startBuf,
'w');
1976 assert((*wBuf ==
'w') &&
"@throw: can't find 'w'");
1977 ReplaceText(startLoc, wBuf-startBuf+1, buf);
1979 const char *semiBuf = strchr(startBuf,
';');
1980 assert((*semiBuf ==
';') &&
"@throw: can't find ';'");
1982 ReplaceText(semiLoc, 1,
");");
1988 std::string StrEncoding;
1989 Context->getObjCEncodingForType(Exp->
getEncodedType(), StrEncoding);
1990 Expr *Replacement = getStringLiteral(StrEncoding);
1991 ReplaceStmt(Exp, Replacement);
1999 if (!SelGetUidFunctionDecl)
2000 SynthSelGetUidFunctionDecl();
2001 assert(SelGetUidFunctionDecl &&
"Can't find sel_registerName() decl");
2005 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2007 ReplaceStmt(Exp, SelExp);
2013RewriteObjC::SynthesizeCallToFunctionDecl(
FunctionDecl *FD,
2025 QualType pToFunc = Context->getPointerType(msgSendType);
2027 ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
2033 CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
2038static bool scanForProtocolRefs(
const char *startBuf,
const char *endBuf,
2039 const char *&startRef,
const char *&endRef) {
2040 while (startBuf < endBuf) {
2041 if (*startBuf ==
'<')
2042 startRef = startBuf;
2043 if (*startBuf ==
'>') {
2044 if (startRef && *startRef ==
'<') {
2055static void scanToNextArgument(
const char *&argRef) {
2057 while (*argRef !=
')' && (*argRef !=
',' || angle > 0)) {
2060 else if (*argRef ==
'>')
2064 assert(angle == 0 &&
"scanToNextArgument - bad protocol type syntax");
2067bool RewriteObjC::needToScanForQualifiers(
QualType T) {
2079 QualType ElemTy = Context->getBaseElementType(T);
2080 return needToScanForQualifiers(ElemTy);
2085void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Expr *
E) {
2087 if (needToScanForQualifiers(
Type)) {
2091 Loc = ECE->getLParenLoc();
2092 EndLoc = ECE->getRParenLoc();
2094 Loc =
E->getBeginLoc();
2095 EndLoc =
E->getEndLoc();
2101 const char *startBuf =
SM->getCharacterData(
Loc);
2102 const char *endBuf =
SM->getCharacterData(EndLoc);
2103 const char *startRef =
nullptr, *endRef =
nullptr;
2104 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2109 InsertText(LessLoc,
"/*");
2110 InsertText(GreaterLoc,
"*/");
2115void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl) {
2119 if (
VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2123 else if (
FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2128 assert(funcType &&
"missing function type");
2129 proto = dyn_cast<FunctionProtoType>(funcType);
2134 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2141 if (needToScanForQualifiers(
Type)) {
2144 const char *endBuf =
SM->getCharacterData(
Loc);
2145 const char *startBuf = endBuf;
2146 while (*startBuf !=
';' && *startBuf !=
'<' && startBuf != MainFileStart)
2148 const char *startRef =
nullptr, *endRef =
nullptr;
2149 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2154 InsertText(LessLoc,
"/*");
2155 InsertText(GreaterLoc,
"*/");
2161 const char *startBuf =
SM->getCharacterData(
Loc);
2162 const char *startFuncBuf = startBuf;
2167 const char *endBuf = startBuf;
2169 scanToNextArgument(endBuf);
2170 const char *startRef =
nullptr, *endRef =
nullptr;
2171 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2174 Loc.getLocWithOffset(startRef-startFuncBuf);
2176 Loc.getLocWithOffset(endRef-startFuncBuf+1);
2178 InsertText(LessLoc,
"/*");
2179 InsertText(GreaterLoc,
"*/");
2181 startBuf = ++endBuf;
2186 while (*startBuf && *startBuf !=
')' && *startBuf !=
',')
2193void RewriteObjC::RewriteTypeOfDecl(
VarDecl *ND) {
2196 if (!isa<TypeOfExprType>(TypePtr))
2198 while (isa<TypeOfExprType>(TypePtr)) {
2199 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2205 std::string TypeAsString(QT.
getAsString(Context->getPrintingPolicy()));
2207 const char *startBuf =
SM->getCharacterData(DeclLoc);
2210 TypeAsString +=
" " + Name +
" = ";
2214 startLoc = ECE->getLParenLoc();
2216 startLoc =
E->getBeginLoc();
2217 startLoc =
SM->getExpansionLoc(startLoc);
2218 const char *endBuf =
SM->getCharacterData(startLoc);
2219 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2223 X =
SM->getExpansionLoc(
X);
2224 const char *endBuf =
SM->getCharacterData(
X);
2225 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2230void RewriteObjC::SynthSelGetUidFunctionDecl() {
2231 IdentifierInfo *SelGetUidIdent = &Context->Idents.get(
"sel_registerName");
2233 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2235 getSimpleFunctionType(Context->getObjCSelType(), ArgTys);
2236 SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2239 SelGetUidIdent, getFuncType,
2240 nullptr, SC_Extern);
2243void RewriteObjC::RewriteFunctionDecl(
FunctionDecl *FD) {
2246 FD->
getName() ==
"sel_registerName") {
2247 SelGetUidFunctionDecl = FD;
2250 RewriteObjCQualifiedInterfaceTypes(FD);
2253void RewriteObjC::RewriteBlockPointerType(std::string& Str,
QualType Type) {
2254 std::string TypeString(
Type.getAsString(Context->getPrintingPolicy()));
2255 const char *argPtr = TypeString.c_str();
2256 if (!strchr(argPtr,
'^')) {
2261 Str += (*argPtr ==
'^' ?
'*' : *argPtr);
2267void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2270 std::string TypeString(
Type.getAsString(Context->getPrintingPolicy()));
2271 const char *argPtr = TypeString.c_str();
2296void RewriteObjC::RewriteBlockLiteralFunctionDecl(
FunctionDecl *FD) {
2303 std::string FdStr =
Type.getAsString(Context->getPrintingPolicy());
2307 unsigned numArgs = proto->getNumParams();
2308 for (
unsigned i = 0; i < numArgs; i++) {
2309 QualType ArgType = proto->getParamType(i);
2310 RewriteBlockPointerType(FdStr, ArgType);
2315 InsertText(FunLocStart, FdStr);
2316 CurFunctionDeclToDeclareForBlock =
nullptr;
2320void RewriteObjC::SynthSuperConstructorFunctionDecl() {
2321 if (SuperConstructorFunctionDecl)
2323 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"__rw_objc_super");
2325 QualType argT = Context->getObjCIdType();
2326 assert(!argT.
isNull() &&
"Can't find 'id' type");
2327 ArgTys.push_back(argT);
2328 ArgTys.push_back(argT);
2329 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2331 SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2334 msgSendIdent, msgSendType,
2335 nullptr, SC_Extern);
2339void RewriteObjC::SynthMsgSendFunctionDecl() {
2340 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"objc_msgSend");
2342 QualType argT = Context->getObjCIdType();
2343 assert(!argT.
isNull() &&
"Can't find 'id' type");
2344 ArgTys.push_back(argT);
2345 argT = Context->getObjCSelType();
2346 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2347 ArgTys.push_back(argT);
2348 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2350 MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2353 msgSendIdent, msgSendType,
2354 nullptr, SC_Extern);
2358void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2359 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"objc_msgSendSuper");
2361 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
2363 &Context->Idents.get(
"objc_super"));
2364 QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
2365 assert(!argT.
isNull() &&
"Can't build 'struct objc_super *' type");
2366 ArgTys.push_back(argT);
2367 argT = Context->getObjCSelType();
2368 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2369 ArgTys.push_back(argT);
2370 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2372 MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2375 msgSendIdent, msgSendType,
2376 nullptr, SC_Extern);
2380void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2381 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"objc_msgSend_stret");
2383 QualType argT = Context->getObjCIdType();
2384 assert(!argT.
isNull() &&
"Can't find 'id' type");
2385 ArgTys.push_back(argT);
2386 argT = Context->getObjCSelType();
2387 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2388 ArgTys.push_back(argT);
2389 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2391 MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2394 msgSendIdent, msgSendType,
2395 nullptr, SC_Extern);
2400void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2402 &Context->Idents.get(
"objc_msgSendSuper_stret");
2404 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
2406 &Context->Idents.get(
"objc_super"));
2407 QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
2408 assert(!argT.
isNull() &&
"Can't build 'struct objc_super *' type");
2409 ArgTys.push_back(argT);
2410 argT = Context->getObjCSelType();
2411 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2412 ArgTys.push_back(argT);
2413 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2415 MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2419 msgSendType,
nullptr,
2424void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2425 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"objc_msgSend_fpret");
2427 QualType argT = Context->getObjCIdType();
2428 assert(!argT.
isNull() &&
"Can't find 'id' type");
2429 ArgTys.push_back(argT);
2430 argT = Context->getObjCSelType();
2431 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2432 ArgTys.push_back(argT);
2433 QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
2435 MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2438 msgSendIdent, msgSendType,
2439 nullptr, SC_Extern);
2443void RewriteObjC::SynthGetClassFunctionDecl() {
2444 IdentifierInfo *getClassIdent = &Context->Idents.get(
"objc_getClass");
2446 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2447 QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
2449 GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2452 getClassIdent, getClassType,
2453 nullptr, SC_Extern);
2457void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2459 &Context->Idents.get(
"class_getSuperclass");
2461 ArgTys.push_back(Context->getObjCClassType());
2462 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2464 GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2468 getClassType,
nullptr,
2473void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2474 IdentifierInfo *getClassIdent = &Context->Idents.get(
"objc_getMetaClass");
2476 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2477 QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
2479 GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2482 getClassIdent, getClassType,
2483 nullptr, SC_Extern);
2487 assert(Exp !=
nullptr &&
"Expected non-null ObjCStringLiteral");
2488 QualType strType = getConstantStringStructType();
2490 std::string S =
"__NSConstantStringImpl_";
2492 std::string tmpName = InFileName;
2494 for (i=0; i < tmpName.length(); i++) {
2495 char c = tmpName.at(i);
2502 S += utostr(NumObjCStringLiterals++);
2504 Preamble +=
"static __NSConstantStringImpl " + S;
2505 Preamble +=
" __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2508 std::string prettyBufS;
2509 llvm::raw_string_ostream prettyBuf(prettyBufS);
2517 strType,
nullptr, SC_Static);
2520 Expr *Unop = UnaryOperator::Create(
2521 const_cast<ASTContext &
>(*Context), DRE, UO_AddrOf,
2522 Context->getPointerType(DRE->
getType()), VK_PRValue, OK_Ordinary,
2526 CK_CPointerToObjCPointerCast, Unop);
2527 ReplaceStmt(Exp, cast);
2533QualType RewriteObjC::getSuperStructType() {
2534 if (!SuperStructDecl) {
2535 SuperStructDecl = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
2537 &Context->Idents.get(
"objc_super"));
2541 FieldTypes[0] = Context->getObjCIdType();
2543 FieldTypes[1] = Context->getObjCClassType();
2546 for (
unsigned i = 0; i < 2; ++i) {
2547 SuperStructDecl->
addDecl(FieldDecl::Create(*Context, SuperStructDecl,
2550 FieldTypes[i],
nullptr,
2558 return Context->getTagDeclType(SuperStructDecl);
2561QualType RewriteObjC::getConstantStringStructType() {
2562 if (!ConstantStringDecl) {
2563 ConstantStringDecl = RecordDecl::Create(
2565 SourceLocation(), &Context->Idents.get(
"__NSConstantStringImpl"));
2569 FieldTypes[0] = Context->getObjCIdType();
2571 FieldTypes[1] = Context->IntTy;
2573 FieldTypes[2] = Context->getPointerType(Context->CharTy);
2575 FieldTypes[3] = Context->LongTy;
2578 for (
unsigned i = 0; i < 4; ++i) {
2579 ConstantStringDecl->
addDecl(FieldDecl::Create(*Context,
2583 FieldTypes[i],
nullptr,
2591 return Context->getTagDeclType(ConstantStringDecl);
2602 new (Context)
DeclRefExpr(*Context, MsgSendStretFlavor,
false,
2606 Context->getPointerType(Context->VoidTy),
2609 QualType castType = getSimpleFunctionType(returnType, ArgTypes,
2612 castType = Context->getPointerType(castType);
2613 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2621 CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_PRValue,
2629 if (!SelGetUidFunctionDecl)
2630 SynthSelGetUidFunctionDecl();
2631 if (!MsgSendFunctionDecl)
2632 SynthMsgSendFunctionDecl();
2633 if (!MsgSendSuperFunctionDecl)
2634 SynthMsgSendSuperFunctionDecl();
2635 if (!MsgSendStretFunctionDecl)
2636 SynthMsgSendStretFunctionDecl();
2637 if (!MsgSendSuperStretFunctionDecl)
2638 SynthMsgSendSuperStretFunctionDecl();
2639 if (!MsgSendFpretFunctionDecl)
2640 SynthMsgSendFpretFunctionDecl();
2641 if (!GetClassFunctionDecl)
2642 SynthGetClassFunctionDecl();
2643 if (!GetSuperClassFunctionDecl)
2644 SynthGetSuperClassFunctionDecl();
2645 if (!GetMetaClassFunctionDecl)
2646 SynthGetMetaClassFunctionDecl();
2653 QualType resultType = mDecl->getReturnType();
2655 MsgSendStretFlavor = MsgSendStretFunctionDecl;
2657 MsgSendFlavor = MsgSendFpretFunctionDecl;
2663 case ObjCMessageExpr::SuperClass: {
2664 MsgSendFlavor = MsgSendSuperFunctionDecl;
2665 if (MsgSendStretFlavor)
2666 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2667 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2674 InitExprs.push_back(NoTypeInfoCStyleCastExpr(
2675 Context, Context->getObjCIdType(), CK_BitCast,
2677 Context->getObjCIdType(), VK_PRValue,
2683 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2684 ClsExprs, StartLoc, EndLoc);
2686 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2687 Context->getObjCClassType(),
2690 ClsExprs.push_back(ArgExpr);
2691 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2695 InitExprs.push_back(
2696 NoTypeInfoCStyleCastExpr(Context,
2697 Context->getObjCIdType(),
2700 QualType superType = getSuperStructType();
2703 if (LangOpts.MicrosoftExt) {
2704 SynthSuperConstructorFunctionDecl();
2707 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2710 CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
2718 SuperRep = UnaryOperator::Create(
2719 const_cast<ASTContext &
>(*Context), SuperRep, UO_AddrOf,
2720 Context->getPointerType(SuperRep->
getType()), VK_PRValue, OK_Ordinary,
2722 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2723 Context->getPointerType(superType),
2724 CK_BitCast, SuperRep);
2731 = Context->getTrivialTypeSourceInfo(superType);
2736 SuperRep = UnaryOperator::Create(
2737 const_cast<ASTContext &
>(*Context), SuperRep, UO_AddrOf,
2738 Context->getPointerType(SuperRep->
getType()), VK_PRValue, OK_Ordinary,
2741 MsgExprs.push_back(SuperRep);
2745 case ObjCMessageExpr::Class: {
2750 ClsExprs.push_back(getStringLiteral(clsName->
getName()));
2751 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2753 MsgExprs.push_back(Cls);
2757 case ObjCMessageExpr::SuperInstance:{
2758 MsgSendFlavor = MsgSendSuperFunctionDecl;
2759 if (MsgSendStretFlavor)
2760 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2761 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2765 InitExprs.push_back(NoTypeInfoCStyleCastExpr(
2766 Context, Context->getObjCIdType(), CK_BitCast,
2768 Context->getObjCIdType(), VK_PRValue,
2774 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2777 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2778 Context->getObjCClassType(),
2781 ClsExprs.push_back(ArgExpr);
2782 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2787 InitExprs.push_back(
2789 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2792 QualType superType = getSuperStructType();
2795 if (LangOpts.MicrosoftExt) {
2796 SynthSuperConstructorFunctionDecl();
2799 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2802 CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
2810 SuperRep = UnaryOperator::Create(
2811 const_cast<ASTContext &
>(*Context), SuperRep, UO_AddrOf,
2812 Context->getPointerType(SuperRep->
getType()), VK_PRValue, OK_Ordinary,
2814 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2815 Context->getPointerType(superType),
2816 CK_BitCast, SuperRep);
2823 = Context->getTrivialTypeSourceInfo(superType);
2827 MsgExprs.push_back(SuperRep);
2831 case ObjCMessageExpr::Instance: {
2836 recExpr = CE->getSubExpr();
2839 ? CK_BlockPointerToObjCPointerCast
2840 : CK_CPointerToObjCPointerCast;
2842 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2844 MsgExprs.push_back(recExpr);
2852 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2853 SelExprs, StartLoc, EndLoc);
2854 MsgExprs.push_back(SelExp);
2857 for (
unsigned i = 0; i < Exp->
getNumArgs(); i++) {
2863 if (needToScanForQualifiers(type))
2864 type = Context->getObjCIdType();
2866 (void)convertBlockPointerToFunctionPointer(type);
2870 type->isBooleanType()) {
2871 CK = CK_IntegralToBoolean;
2872 }
else if (
type->isObjCObjectPointerType()) {
2874 CK = CK_BlockPointerToObjCPointerCast;
2876 CK = CK_CPointerToObjCPointerCast;
2884 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2887 else if (
CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2888 if (CE->getType()->isObjCQualifiedIdType()) {
2889 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2890 userExpr = CE->getSubExpr();
2893 CK = CK_IntegralToPointer;
2895 CK = CK_BlockPointerToObjCPointerCast;
2897 CK = CK_CPointerToObjCPointerCast;
2901 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2905 MsgExprs.push_back(userExpr);
2917 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2918 ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
2920 ArgTypes.push_back(Context->getObjCIdType());
2921 ArgTypes.push_back(Context->getObjCSelType());
2926 ? Context->getObjCIdType()
2929 (void)convertBlockPointerToFunctionPointer(t);
2930 ArgTypes.push_back(t);
2933 convertToUnqualifiedObjCType(returnType);
2934 (void)convertBlockPointerToFunctionPointer(returnType);
2936 returnType = Context->getObjCIdType();
2943 *Context, MsgSendFlavor,
false, msgSendType, VK_LValue,
SourceLocation());
2949 cast = NoTypeInfoCStyleCastExpr(Context,
2950 Context->getPointerType(Context->VoidTy),
2957 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->
isVariadic() :
true);
2958 castType = Context->getPointerType(castType);
2959 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2966 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2968 Stmt *ReplacingStmt = CE;
2969 if (MsgSendStretFlavor) {
2975 CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
2976 msgSendType, returnType,
2983 Context->getTrivialTypeSourceInfo(returnType),
2991 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
2993 llvm::APInt(IntSize, 8),
2997 *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue,
3007 return ReplacingStmt;
3011 Stmt *ReplacingStmt =
3015 ReplaceStmt(Exp, ReplacingStmt);
3018 return ReplacingStmt;
3022QualType RewriteObjC::getProtocolType() {
3023 if (!ProtocolTypeDecl) {
3025 = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
3026 ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
3028 &Context->Idents.get(
"Protocol"),
3031 return Context->getTypeDeclType(ProtocolTypeDecl);
3043 nullptr, SC_Extern);
3046 Expr *DerefExpr = UnaryOperator::Create(
3047 const_cast<ASTContext &
>(*Context), DRE, UO_AddrOf,
3048 Context->getPointerType(DRE->
getType()), VK_PRValue, OK_Ordinary,
3053 ReplaceStmt(Exp, castExpr);
3059bool RewriteObjC::BufferContainsPPDirectives(
const char *startBuf,
3060 const char *endBuf) {
3061 while (startBuf < endBuf) {
3062 if (*startBuf ==
'#') {
3064 for (++startBuf; startBuf[0] ==
' ' || startBuf[0] ==
'\t'; ++startBuf)
3066 if (!strncmp(startBuf,
"if", strlen(
"if")) ||
3067 !strncmp(startBuf,
"ifdef", strlen(
"ifdef")) ||
3068 !strncmp(startBuf,
"ifndef", strlen(
"ifndef")) ||
3069 !strncmp(startBuf,
"define", strlen(
"define")) ||
3070 !strncmp(startBuf,
"undef", strlen(
"undef")) ||
3071 !strncmp(startBuf,
"else", strlen(
"else")) ||
3072 !strncmp(startBuf,
"elif", strlen(
"elif")) ||
3073 !strncmp(startBuf,
"endif", strlen(
"endif")) ||
3074 !strncmp(startBuf,
"pragma", strlen(
"pragma")) ||
3075 !strncmp(startBuf,
"include", strlen(
"include")) ||
3076 !strncmp(startBuf,
"import", strlen(
"import")) ||
3077 !strncmp(startBuf,
"include_next", strlen(
"include_next")))
3088 std::string &Result) {
3089 assert(CDecl &&
"Class missing in SynthesizeObjCInternalStruct");
3090 assert(CDecl->
getName() !=
"" &&
3091 "Name missing in SynthesizeObjCInternalStruct");
3093 if (ObjCSynthesizedStructs.count(CDecl))
3100 const char *startBuf =
SM->getCharacterData(LocStart);
3101 const char *endBuf =
SM->getCharacterData(LocEnd);
3106 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3107 endBuf += Lexer::MeasureTokenLength(LocEnd, *
SM, LangOpts);
3108 ReplaceText(LocStart, endBuf-startBuf, Result);
3114 Result +=
"\nstruct ";
3116 if (LangOpts.MicrosoftExt)
3120 const char *cursor = strchr(startBuf,
'{');
3121 assert((cursor && endBuf)
3122 &&
"SynthesizeObjCInternalStruct - malformed @interface");
3138 if (BufferContainsPPDirectives(startBuf, cursor)) {
3141 const char *endHeader =
SM->getCharacterData(L);
3142 endHeader += Lexer::MeasureTokenLength(L, *
SM, LangOpts);
3146 while (endHeader < cursor && *endHeader !=
'>') endHeader++;
3150 ReplaceText(LocStart, endHeader-startBuf, Result);
3153 ReplaceText(LocStart, cursor-startBuf, Result);
3155 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
3156 Result =
"\n struct ";
3160 Result +=
"_IVARS;\n";
3165 InsertText(OnePastCurly, Result);
3170 while (cursor < endBuf) {
3171 if (*cursor ==
'@') {
3174 for (++cursor; cursor[0] ==
' ' || cursor[0] ==
'\t'; ++cursor)
3179 if (!strncmp(cursor,
"public", strlen(
"public")) ||
3180 !strncmp(cursor,
"private", strlen(
"private")) ||
3181 !strncmp(cursor,
"package", strlen(
"package")) ||
3182 !strncmp(cursor,
"protected", strlen(
"protected")))
3183 InsertText(atLoc,
"// ");
3188 else if (*cursor ==
'<') {
3190 InsertText(atLoc,
"/* ");
3191 cursor = strchr(cursor,
'>');
3194 InsertText(atLoc,
" */");
3195 }
else if (*cursor ==
'^') {
3197 ReplaceText(caretLoc, 1,
"*");
3204 endBuf += Lexer::MeasureTokenLength(LocEnd, *
SM, LangOpts);
3205 Result +=
" {\n struct ";
3209 Result +=
"_IVARS;\n};\n";
3210 ReplaceText(LocStart, endBuf-startBuf, Result);
3213 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3214 llvm_unreachable(
"struct already synthesize- SynthesizeObjCInternalStruct");
3224void RewriteObjC::RewriteImplementations() {
3225 int ClsDefCount = ClassImplementation.size();
3226 int CatDefCount = CategoryImplementation.size();
3229 for (
int i = 0; i < ClsDefCount; i++)
3230 RewriteImplementationDecl(ClassImplementation[i]);
3232 for (
int i = 0; i < CatDefCount; i++)
3233 RewriteImplementationDecl(CategoryImplementation[i]);
3236void RewriteObjC::RewriteByRefString(std::string &ResultStr,
3237 const std::string &Name,
3239 assert(BlockByRefDeclNo.count(VD) &&
3240 "RewriteByRefString: ByRef decl missing");
3242 ResultStr +=
"struct ";
3243 ResultStr +=
"__Block_byref_" + Name +
3244 "_" + utostr(BlockByRefDeclNo[VD]) ;
3247static bool HasLocalVariableExternalStorage(
ValueDecl *VD) {
3248 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3249 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3253std::string RewriteObjC::SynthesizeBlockFunc(
BlockExpr *CE,
int i,
3258 std::string StructRef =
"struct " +
Tag;
3259 std::string S =
"static " + RT.
getAsString(Context->getPrintingPolicy()) +
" __" +
3260 funcName.str() +
"_" +
"block_func_" + utostr(i);
3264 if (isa<FunctionNoProtoType>(AFT)) {
3267 S +=
"(" + StructRef +
" *__cself)";
3269 S +=
"(" + StructRef +
" *__cself)";
3272 assert(FT &&
"SynthesizeBlockFunc: No function proto");
3275 S += StructRef +
" *__cself, ";
3276 std::string ParamStr;
3280 ParamStr = (*AI)->getNameAsString();
3282 (void)convertBlockPointerToFunctionPointer(QT);
3297 E = BlockByRefDecls.end(); I !=
E; ++I) {
3299 std::string Name = (*I)->getNameAsString();
3300 std::string TypeString;
3301 RewriteByRefString(TypeString, Name, (*I));
3303 Name = TypeString + Name;
3304 S += Name +
" = __cself->" + (*I)->getNameAsString() +
"; // bound by ref\n";
3308 E = BlockByCopyDecls.end(); I !=
E; ++I) {
3320 if (isTopLevelBlockPointerType((*I)->getType())) {
3321 RewriteBlockPointerTypeVariable(S, (*I));
3323 RewriteBlockPointerType(S, (*I)->getType());
3325 S +=
"__cself->" + (*I)->getNameAsString() +
"; // bound by copy\n";
3328 std::string Name = (*I)->getNameAsString();
3330 if (HasLocalVariableExternalStorage(*I))
3331 QT = Context->getPointerType(QT);
3333 S += Name +
" = __cself->" +
3334 (*I)->getNameAsString() +
"; // bound by copy\n";
3337 std::string RewrittenStr = RewrittenBlockExprs[CE];
3338 const char *cstr = RewrittenStr.c_str();
3339 while (*cstr++ !=
'{') ;
3345std::string RewriteObjC::SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
3348 std::string StructRef =
"struct " +
Tag;
3349 std::string S =
"static void __";
3352 S +=
"_block_copy_" + utostr(i);
3353 S +=
"(" + StructRef;
3354 S +=
"*dst, " + StructRef;
3356 for (
ValueDecl *VD : ImportedBlockDecls) {
3357 S +=
"_Block_object_assign((void*)&dst->";
3359 S +=
", (void*)src->";
3361 if (BlockByRefDeclsPtrSet.count(VD))
3362 S +=
", " + utostr(BLOCK_FIELD_IS_BYREF) +
"/*BLOCK_FIELD_IS_BYREF*/);";
3364 S +=
", " + utostr(BLOCK_FIELD_IS_BLOCK) +
"/*BLOCK_FIELD_IS_BLOCK*/);";
3366 S +=
", " + utostr(BLOCK_FIELD_IS_OBJECT) +
"/*BLOCK_FIELD_IS_OBJECT*/);";
3370 S +=
"\nstatic void __";
3372 S +=
"_block_dispose_" + utostr(i);
3373 S +=
"(" + StructRef;
3375 for (
ValueDecl *VD : ImportedBlockDecls) {
3376 S +=
"_Block_object_dispose((void*)src->";
3378 if (BlockByRefDeclsPtrSet.count(VD))
3379 S +=
", " + utostr(BLOCK_FIELD_IS_BYREF) +
"/*BLOCK_FIELD_IS_BYREF*/);";
3381 S +=
", " + utostr(BLOCK_FIELD_IS_BLOCK) +
"/*BLOCK_FIELD_IS_BLOCK*/);";
3383 S +=
", " + utostr(BLOCK_FIELD_IS_OBJECT) +
"/*BLOCK_FIELD_IS_OBJECT*/);";
3389std::string RewriteObjC::SynthesizeBlockImpl(
BlockExpr *CE, std::string Tag,
3391 std::string S =
"\nstruct " +
Tag;
3394 S +=
" {\n struct __block_impl impl;\n";
3395 S +=
" struct " + Desc;
3402 if (BlockDeclRefs.size()) {
3405 E = BlockByCopyDecls.end(); I !=
E; ++I) {
3407 std::string FieldName = (*I)->getNameAsString();
3408 std::string ArgName =
"_" + FieldName;
3419 if (isTopLevelBlockPointerType((*I)->getType())) {
3420 S +=
"struct __block_impl *";
3424 if (HasLocalVariableExternalStorage(*I))
3425 QT = Context->getPointerType(QT);
3430 S += FieldName +
";\n";
3434 E = BlockByRefDecls.end(); I !=
E; ++I) {
3436 std::string FieldName = (*I)->getNameAsString();
3437 std::string ArgName =
"_" + FieldName;
3439 std::string TypeString;
3440 RewriteByRefString(TypeString, FieldName, (*I));
3442 FieldName = TypeString + FieldName;
3443 ArgName = TypeString + ArgName;
3446 S += FieldName +
"; // by ref\n";
3451 bool firsTime =
true;
3453 E = BlockByCopyDecls.end(); I !=
E; ++I) {
3454 std::string Name = (*I)->getNameAsString();
3461 if (isTopLevelBlockPointerType((*I)->getType()))
3462 Constructor += Name +
"((struct __block_impl *)_" + Name +
")";
3468 E = BlockByRefDecls.end(); I !=
E; ++I) {
3469 std::string Name = (*I)->getNameAsString();
3476 Constructor += Name +
"(_" + Name +
"->__forwarding)";
3481 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3483 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3484 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3491 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3493 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3494 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3504std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
3505 std::string ImplTag,
int i,
3508 std::string S =
"\nstatic struct " + DescTag;
3510 S +=
" {\n unsigned long reserved;\n";
3511 S +=
" unsigned long Block_size;\n";
3513 S +=
" void (*copy)(struct ";
3514 S += ImplTag; S +=
"*, struct ";
3515 S += ImplTag; S +=
"*);\n";
3517 S +=
" void (*dispose)(struct ";
3518 S += ImplTag; S +=
"*);\n";
3522 S += DescTag +
"_DATA = { 0, sizeof(struct ";
3525 S +=
", __" + FunName.str() +
"_block_copy_" + utostr(i);
3526 S +=
", __" + FunName.str() +
"_block_dispose_" + utostr(i);
3532void RewriteObjC::SynthesizeBlockLiterals(
SourceLocation FunLocStart,
3533 StringRef FunName) {
3535 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3536 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3537 bool RewriteSC = (GlobalVarDecl &&
3542 std::string SC(
" void __");
3545 InsertText(FunLocStart, SC);
3549 for (
unsigned i = 0, count=0; i < Blocks.size(); i++) {
3550 CollectBlockDeclRefInfo(Blocks[i]);
3553 for (
int j = 0; j < InnerDeclRefsCount[i]; j++) {
3556 BlockDeclRefs.push_back(Exp);
3557 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
3558 BlockByCopyDeclsPtrSet.insert(VD);
3559 BlockByCopyDecls.push_back(VD);
3561 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
3562 BlockByRefDeclsPtrSet.insert(VD);
3563 BlockByRefDecls.push_back(VD);
3567 if (VD->
hasAttr<BlocksAttr>() ||
3570 ImportedBlockDecls.insert(VD);
3573 std::string ImplTag =
"__" + FunName.str() +
"_block_impl_" + utostr(i);
3574 std::string DescTag =
"__" + FunName.str() +
"_block_desc_" + utostr(i);
3576 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3578 InsertText(FunLocStart, CI);
3580 std::string
CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3582 InsertText(FunLocStart, CF);
3584 if (ImportedBlockDecls.size()) {
3585 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3586 InsertText(FunLocStart, HF);
3588 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3589 ImportedBlockDecls.size() > 0);
3590 InsertText(FunLocStart, BD);
3592 BlockDeclRefs.clear();
3593 BlockByRefDecls.clear();
3594 BlockByRefDeclsPtrSet.clear();
3595 BlockByCopyDecls.clear();
3596 BlockByCopyDeclsPtrSet.clear();
3597 ImportedBlockDecls.clear();
3611 InsertText(FunLocStart, SC);
3615 InnerDeclRefsCount.clear();
3616 InnerDeclRefs.clear();
3617 RewrittenBlockExprs.clear();
3620void RewriteObjC::InsertBlockLiteralsWithinFunction(
FunctionDecl *FD) {
3622 StringRef FuncName = FD->
getName();
3624 SynthesizeBlockLiterals(FunLocStart, FuncName);
3627static void BuildUniqueMethodName(std::string &Name,
3630 Name = std::string(IFace->
getName());
3633 std::string::size_type loc = 0;
3634 while ((loc = Name.find(
':', loc)) != std::string::npos)
3635 Name.replace(loc, 1,
"_");
3638void RewriteObjC::InsertBlockLiteralsWithinMethod(
ObjCMethodDecl *MD) {
3642 std::string FuncName;
3643 BuildUniqueMethodName(FuncName, MD);
3644 SynthesizeBlockLiterals(FunLocStart, FuncName);
3647void RewriteObjC::GetBlockDeclRefExprs(
Stmt *S) {
3648 for (
Stmt *SubStmt : S->children())
3650 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
3651 GetBlockDeclRefExprs(CBE->getBody());
3653 GetBlockDeclRefExprs(SubStmt);
3658 HasLocalVariableExternalStorage(DRE->
getDecl()))
3660 BlockDeclRefs.push_back(DRE);
3663void RewriteObjC::GetInnerBlockDeclRefExprs(
Stmt *S,
3665 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
3666 for (
Stmt *SubStmt : S->children())
3668 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
3669 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
3670 GetInnerBlockDeclRefExprs(CBE->getBody(),
3675 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
3678 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3680 HasLocalVariableExternalStorage(DRE->
getDecl())) {
3682 InnerBlockDeclRefs.push_back(DRE);
3684 if (Var->isFunctionOrMethodVarDecl())
3685 ImportedLocalExternalDecls.insert(Var);
3700 bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
3706 if (convertBlockPointerToFunctionPointer(t))
3707 HasBlockType =
true;
3708 ArgTypes.push_back(t);
3715 FuncType = getSimpleFunctionType(Res, ArgTypes);
3720Stmt *RewriteObjC::SynthesizeBlockCall(
CallExpr *Exp,
const Expr *BlockExp) {
3724 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3726 }
else if (
const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3729 else if (
const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3730 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3732 else if (
const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3735 dyn_cast<ConditionalOperator>(BlockExp)) {
3736 Expr *LHSExp = CEXPR->getLHS();
3737 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3738 Expr *RHSExp = CEXPR->getRHS();
3739 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3740 Expr *CONDExp = CEXPR->getCond();
3745 }
else if (
const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3748 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
3751 assert(
false &&
"RewriteBlockClass: Bad type");
3753 assert(CPT &&
"RewriteBlockClass: Bad type");
3755 assert(FT &&
"RewriteBlockClass: Bad type");
3759 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
3761 &Context->Idents.get(
"__block_impl"));
3762 QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
3768 ArgTypes.push_back(PtrBlock);
3773 if (!convertBlockPointerToFunctionPointer(t))
3774 convertToUnqualifiedObjCType(t);
3775 ArgTypes.push_back(t);
3779 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->
getType(), ArgTypes);
3781 PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
3783 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
3785 const_cast<Expr*
>(BlockExp));
3793 &Context->Idents.get(
"FuncPtr"),
3794 Context->VoidPtrTy,
nullptr,
3798 *Context, PE,
true, FD, FD->
getType(), VK_LValue, OK_Ordinary);
3800 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
3806 BlkExprs.push_back(BlkCast);
3810 BlkExprs.push_back(*I);
3813 CallExpr::Create(*Context, PE, BlkExprs, Exp->
getType(), VK_PRValue,
3836 HasLocalVariableExternalStorage(DeclRefExp->
getDecl());
3840 &Context->Idents.get(
"__forwarding"),
3841 Context->VoidPtrTy,
nullptr,
3845 MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD,
3846 FD->
getType(), VK_LValue, OK_Ordinary);
3848 StringRef Name = VD->
getName();
3850 &Context->Idents.get(Name),
3851 Context->VoidPtrTy,
nullptr,
3854 ME = MemberExpr::CreateImplicit(*Context, ME,
true, FD, DeclRefExp->
getType(),
3855 VK_LValue, OK_Ordinary);
3861 ReplaceStmt(DeclRefExp, PE);
3868Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(
DeclRefExpr *DRE) {
3870 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3871 if (!ImportedLocalExternalDecls.count(Var))
3873 Expr *Exp = UnaryOperator::Create(
3879 ReplaceStmt(DRE, PE);
3891 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
3894 const char *startBuf =
SM->getCharacterData(LocStart);
3895 const char *endBuf =
SM->getCharacterData(LocEnd);
3898 if (isa<TypeOfExprType>(TypePtr)) {
3899 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
3901 std::string TypeAsString =
"(";
3902 RewriteBlockPointerType(TypeAsString, QT);
3903 TypeAsString +=
")";
3904 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
3908 const char *argPtr = startBuf;
3910 while (*argPtr++ && (argPtr < endBuf)) {
3915 ReplaceText(LocStart, 1,
"*");
3921void RewriteObjC::RewriteBlockPointerFunctionArgs(
FunctionDecl *FD) {
3923 unsigned parenCount = 0;
3926 const char *startBuf =
SM->getCharacterData(DeclLoc);
3927 const char *startArgList = strchr(startBuf,
'(');
3929 assert((*startArgList ==
'(') &&
"Rewriter fuzzy parser confused");
3934 assert((DeclLoc.
isValid()) &&
"Invalid DeclLoc");
3936 const char *argPtr = startArgList;
3938 while (*argPtr++ && parenCount) {
3943 ReplaceText(DeclLoc, 1,
"*");
3955bool RewriteObjC::PointerTypeTakesAnyBlockArguments(
QualType QT) {
3962 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3967 if (isTopLevelBlockPointerType(I))
3973bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(
QualType QT) {
3980 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3985 if (I->isObjCQualifiedIdType())
3987 if (I->isObjCObjectPointerType() &&
3988 I->getPointeeType()->isObjCQualifiedInterfaceType())
3996void RewriteObjC::GetExtentOfArgList(
const char *Name,
const char *&LParen,
3997 const char *&RParen) {
3998 const char *argPtr = strchr(Name,
'(');
3999 assert((*argPtr ==
'(') &&
"Rewriter fuzzy parser confused");
4003 unsigned parenCount = 1;
4005 while (*argPtr && parenCount) {
4007 case '(': parenCount++;
break;
4008 case ')': parenCount--;
break;
4011 if (parenCount) argPtr++;
4013 assert((*argPtr ==
')') &&
"Rewriter fuzzy parser confused");
4017void RewriteObjC::RewriteBlockPointerDecl(
NamedDecl *ND) {
4019 RewriteBlockPointerFunctionArgs(FD);
4025 if (
VarDecl *VD = dyn_cast<VarDecl>(ND))
4028 DeclT = TDD->getUnderlyingType();
4029 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4032 llvm_unreachable(
"RewriteBlockPointerDecl(): Decl type not yet handled");
4034 const char *startBuf =
SM->getCharacterData(DeclLoc);
4035 const char *endBuf = startBuf;
4037 while (*startBuf !=
'^' && *startBuf !=
';' && startBuf != MainFileStart)
4041 unsigned OrigLength=0;
4044 if (*startBuf ==
'^') {
4050 while (*startBuf !=
')') {
4058 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4059 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4063 startBuf =
SM->getCharacterData(DeclLoc);
4064 const char *argListBegin, *argListEnd;
4065 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4066 while (argListBegin < argListEnd) {
4067 if (*argListBegin ==
'^')
4069 else if (*argListBegin ==
'<') {
4071 buf += *argListBegin++;
4073 while (*argListBegin !=
'>') {
4074 buf += *argListBegin++;
4077 buf += *argListBegin;
4081 buf += *argListBegin;
4088 ReplaceText(Start, OrigLength, buf);
4111std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
4114 if (CopyDestroyCache.count(flag))
4116 CopyDestroyCache.insert(flag);
4117 S =
"static void __Block_byref_id_object_copy_";
4119 S +=
"(void *dst, void *src) {\n";
4124 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4125 unsigned VoidPtrSize =
4126 static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
4128 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
4129 S +=
" _Block_object_assign((char*)dst + ";
4130 S += utostr(offset);
4131 S +=
", *(void * *) ((char*)src + ";
4132 S += utostr(offset);
4137 S +=
"static void __Block_byref_id_object_dispose_";
4139 S +=
"(void *src) {\n";
4140 S +=
" _Block_object_dispose(*(void * *) ((char*)src + ";
4141 S += utostr(offset);
4166void RewriteObjC::RewriteByRefVar(
VarDecl *ND) {
4169 if (CurFunctionDeclToDeclareForBlock)
4170 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4178 const char *startBuf =
SM->getCharacterData(DeclLoc);
4180 X =
SM->getExpansionLoc(
X);
4181 const char *endBuf =
SM->getCharacterData(
X);
4183 std::string ByrefType;
4184 RewriteByRefString(ByrefType, Name, ND,
true);
4185 ByrefType +=
" {\n";
4186 ByrefType +=
" void *__isa;\n";
4187 RewriteByRefString(ByrefType, Name, ND);
4188 ByrefType +=
" *__forwarding;\n";
4189 ByrefType +=
" int __flags;\n";
4190 ByrefType +=
" int __size;\n";
4194 bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
4195 if (HasCopyAndDispose) {
4196 ByrefType +=
" void (*__Block_byref_id_object_copy)(void*, void*);\n";
4197 ByrefType +=
" void (*__Block_byref_id_object_dispose)(void*);\n";
4201 (void)convertBlockPointerToFunctionPointer(T);
4202 T.getAsStringInternal(Name, Context->getPrintingPolicy());
4204 ByrefType +=
" " + Name +
";\n";
4205 ByrefType +=
"};\n";
4211 assert(CurMethodDef &&
"RewriteByRefVar - CurMethodDef is null");
4214 InsertText(FunLocStart, ByrefType);
4220 if (HasCopyAndDispose) {
4228 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4230 InsertText(FunLocStart, HF);
4236 bool hasInit = (ND->
getInit() !=
nullptr);
4238 if (HasCopyAndDispose)
4242 RewriteByRefString(ByrefType, Name, ND);
4243 std::string ForwardingCastType(
"(");
4244 ForwardingCastType += ByrefType +
" *)";
4246 ByrefType +=
" " + Name +
" = {(void*)";
4247 ByrefType += utostr(isa);
4248 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4249 ByrefType += utostr(flags);
4251 ByrefType +=
"sizeof(";
4252 RewriteByRefString(ByrefType, Name, ND);
4254 if (HasCopyAndDispose) {
4255 ByrefType +=
", __Block_byref_id_object_copy_";
4256 ByrefType += utostr(flag);
4257 ByrefType +=
", __Block_byref_id_object_dispose_";
4258 ByrefType += utostr(flag);
4260 ByrefType +=
"};\n";
4261 unsigned nameSize = Name.size();
4266 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4272 startLoc = ECE->getLParenLoc();
4274 startLoc =
E->getBeginLoc();
4275 startLoc =
SM->getExpansionLoc(startLoc);
4276 endBuf =
SM->getCharacterData(startLoc);
4277 ByrefType +=
" " + Name;
4278 ByrefType +=
" = {(void*)";
4279 ByrefType += utostr(isa);
4280 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4281 ByrefType += utostr(flags);
4283 ByrefType +=
"sizeof(";
4284 RewriteByRefString(ByrefType, Name, ND);
4286 if (HasCopyAndDispose) {
4287 ByrefType +=
"__Block_byref_id_object_copy_";
4288 ByrefType += utostr(flag);
4289 ByrefType +=
", __Block_byref_id_object_dispose_";
4290 ByrefType += utostr(flag);
4293 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4303 const char *startInitializerBuf =
SM->getCharacterData(startLoc);
4304 const char *semiBuf = strchr(startInitializerBuf,
';');
4305 assert((*semiBuf ==
';') &&
"RewriteByRefVar: can't find ';'");
4309 InsertText(semiLoc,
"}");
4313void RewriteObjC::CollectBlockDeclRefInfo(
BlockExpr *Exp) {
4315 GetBlockDeclRefExprs(Exp->
getBody());
4316 if (BlockDeclRefs.size()) {
4318 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4319 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4320 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4321 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4322 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
4326 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4327 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4328 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4329 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4330 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
4334 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4335 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4336 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4337 BlockDeclRefs[i]->getType()->isBlockPointerType())
4338 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4342FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
4344 QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
4353 Blocks.push_back(Exp);
4355 CollectBlockDeclRefInfo(Exp);
4358 int countOfInnerDecls = 0;
4359 if (!InnerBlockDeclRefs.empty()) {
4360 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
4363 if (!VD->
hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
4367 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4368 BlockDeclRefs.push_back(Exp);
4369 BlockByCopyDeclsPtrSet.insert(VD);
4370 BlockByCopyDecls.push_back(VD);
4372 if (VD->
hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
4373 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4374 BlockDeclRefs.push_back(Exp);
4375 BlockByRefDeclsPtrSet.insert(VD);
4376 BlockByRefDecls.push_back(VD);
4380 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
4381 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4382 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4383 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
4384 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4386 InnerDeclRefsCount.push_back(countOfInnerDecls);
4388 std::string FuncName;
4392 else if (CurMethodDef)
4393 BuildUniqueMethodName(FuncName, CurMethodDef);
4394 else if (GlobalVarDecl)
4397 std::string BlockNumber = utostr(Blocks.size()-1);
4399 std::string
Tag =
"__" + FuncName +
"_block_impl_" + BlockNumber;
4400 std::string
Func =
"__" + FuncName +
"_block_func_" + BlockNumber;
4403 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
4404 QualType FType = Context->getPointerType(BFT);
4410 FD = SynthBlockInitFunctionDecl(Tag);
4417 FD = SynthBlockInitFunctionDecl(Func);
4421 NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg);
4422 InitExprs.push_back(castExpr);
4425 std::string DescData =
"__" + FuncName +
"_block_desc_" + BlockNumber +
"_DATA";
4427 VarDecl *NewVD = VarDecl::Create(
4429 &Context->Idents.get(DescData), Context->VoidPtrTy,
nullptr, SC_Static);
4432 new (Context)
DeclRefExpr(*Context, NewVD,
false, Context->VoidPtrTy,
4434 UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,
4436 InitExprs.push_back(DescRefExpr);
4439 if (BlockDeclRefs.size()) {
4443 E = BlockByCopyDecls.end(); I !=
E; ++I) {
4444 if (isObjCType((*I)->getType())) {
4446 FD = SynthBlockInitFunctionDecl((*I)->getName());
4449 if (HasLocalVariableExternalStorage(*I)) {
4451 QT = Context->getPointerType(QT);
4452 Exp = UnaryOperator::Create(
const_cast<ASTContext &
>(*Context), Exp,
4453 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
4457 }
else if (isTopLevelBlockPointerType((*I)->getType())) {
4458 FD = SynthBlockInitFunctionDecl((*I)->getName());
4461 Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast,
4464 FD = SynthBlockInitFunctionDecl((*I)->getName());
4467 if (HasLocalVariableExternalStorage(*I)) {
4469 QT = Context->getPointerType(QT);
4470 Exp = UnaryOperator::Create(
const_cast<ASTContext &
>(*Context), Exp,
4471 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
4476 InitExprs.push_back(Exp);
4480 E = BlockByRefDecls.end(); I !=
E; ++I) {
4483 std::string RecName;
4484 RewriteByRefString(RecName, Name, ND,
true);
4486 +
sizeof(
"struct"));
4488 RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
4490 assert(RD &&
"SynthBlockInitExpr(): Can't find RecordDecl");
4491 QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
4493 FD = SynthBlockInitFunctionDecl((*I)->getName());
4496 bool isNestedCapturedVar =
false;
4498 for (
const auto &CI : block->
captures()) {
4499 const VarDecl *variable = CI.getVariable();
4500 if (variable == ND && CI.isNested()) {
4501 assert (CI.isByRef() &&
4502 "SynthBlockInitExpr - captured block variable is not byref");
4503 isNestedCapturedVar =
true;
4509 if (!isNestedCapturedVar)
4510 Exp = UnaryOperator::Create(
4511 const_cast<ASTContext &
>(*Context), Exp, UO_AddrOf,
4512 Context->getPointerType(Exp->
getType()), VK_PRValue, OK_Ordinary,
4514 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
4515 InitExprs.push_back(Exp);
4518 if (ImportedBlockDecls.size()) {
4522 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4523 Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
4525 InitExprs.push_back(FlagExp);
4527 NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
4529 NewRep = UnaryOperator::Create(
4530 const_cast<ASTContext &
>(*Context), NewRep, UO_AddrOf,
4531 Context->getPointerType(NewRep->
getType()), VK_PRValue, OK_Ordinary,
4533 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
4535 BlockDeclRefs.clear();
4536 BlockByRefDecls.clear();
4537 BlockByRefDeclsPtrSet.clear();
4538 BlockByCopyDecls.clear();
4539 BlockByCopyDeclsPtrSet.clear();
4540 ImportedBlockDecls.clear();
4544bool RewriteObjC::IsDeclStmtInForeachHeader(
DeclStmt *DS) {
4546 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4547 return CS->getElement() == DS;
4555Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(
Stmt *S) {
4556 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4557 isa<DoStmt>(S) || isa<ForStmt>(S))
4559 else if (isa<ObjCForCollectionStmt>(S)) {
4561 ObjCBcLabelNo.push_back(++BcLabelCount);
4568 return RewritePropertyOrImplicitSetter(PseudoOp);
4570 return RewritePropertyOrImplicitGetter(PseudoOp);
4572 }
else if (
ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4573 return RewriteObjCIvarRefExpr(IvarRefExpr);
4579 for (
Stmt *&childStmt : S->children())
4581 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4583 childStmt = newStmt;
4587 if (
BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
4590 InnerContexts.insert(BE->getBlockDecl());
4591 ImportedLocalExternalDecls.clear();
4592 GetInnerBlockDeclRefExprs(BE->getBody(),
4593 InnerBlockDeclRefs, InnerContexts);
4595 Stmt *SaveCurrentBody = CurrentBody;
4596 CurrentBody = BE->getBody();
4597 PropParentMap =
nullptr;
4603 bool saveDisableReplaceStmt = DisableReplaceStmt;
4604 DisableReplaceStmt =
false;
4605 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4606 DisableReplaceStmt = saveDisableReplaceStmt;
4607 CurrentBody = SaveCurrentBody;
4608 PropParentMap =
nullptr;
4609 ImportedLocalExternalDecls.clear();
4611 std::string Str =
Rewrite.getRewrittenText(BE->getSourceRange());
4612 RewrittenBlockExprs[BE] = Str;
4614 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4617 ReplaceStmt(S, blockTranscribed);
4618 return blockTranscribed;
4622 return RewriteAtEncode(AtEncode);
4625 return RewriteAtSelector(AtSelector);
4628 return RewriteObjCStringLiteral(AtString);
4636 const char *startBuf =
SM->getCharacterData(startLoc);
4637 const char *endBuf =
SM->getCharacterData(endLoc);
4639 std::string messString;
4640 messString +=
"// ";
4641 messString.append(startBuf, endBuf-startBuf+1);
4650 return RewriteMessageExpr(MessExpr);
4654 return RewriteObjCTryStmt(StmtTry);
4657 return RewriteObjCSynchronizedStmt(StmtTry);
4660 return RewriteObjCThrowStmt(StmtThrow);
4663 return RewriteObjCProtocolExpr(ProtocolExp);
4666 dyn_cast<ObjCForCollectionStmt>(S))
4667 return RewriteObjCForCollectionStmt(StmtForCollection,
4670 dyn_cast<BreakStmt>(S))
4671 return RewriteBreakStmt(StmtBreakStmt);
4673 dyn_cast<ContinueStmt>(S))
4674 return RewriteContinueStmt(StmtContinueStmt);
4678 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4688 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4689 RewriteObjCQualifiedInterfaceTypes(*DS->
decl_begin());
4692 for (
auto *SD : DS->
decls()) {
4693 if (
ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4694 if (isTopLevelBlockPointerType(ND->
getType()))
4695 RewriteBlockPointerDecl(ND);
4697 CheckFunctionPointerDecl(ND->
getType(), ND);
4698 if (
VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4699 if (VD->
hasAttr<BlocksAttr>()) {
4700 static unsigned uniqueByrefDeclCount = 0;
4701 assert(!BlockByRefDeclNo.count(ND) &&
4702 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4703 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4704 RewriteByRefVar(VD);
4707 RewriteTypeOfDecl(VD);
4711 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4712 RewriteBlockPointerDecl(TD);
4713 else if (TD->getUnderlyingType()->isFunctionPointerType())
4714 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4720 RewriteObjCQualifiedInterfaceTypes(CE);
4722 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4723 isa<DoStmt>(S) || isa<ForStmt>(S)) {
4724 assert(!Stmts.empty() &&
"Statement stack is empty");
4725 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
4726 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
4727 &&
"Statement stack mismatch");
4731 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4733 if (VD->
hasAttr<BlocksAttr>())
4734 return RewriteBlockDeclRefExpr(DRE);
4735 if (HasLocalVariableExternalStorage(VD))
4736 return RewriteLocalVariableExternalStorage(DRE);
4739 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
4741 Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
4742 ReplaceStmt(S, BlockCall);
4747 RewriteCastExpr(CE);
4756 llvm::raw_string_ostream Buf(SStr);
4757 Replacement->printPretty(Buf);
4758 const std::string &Str = Buf.str();
4760 printf(
"CAST = %s\n", &Str[0]);
4770void RewriteObjC::RewriteRecordBody(
RecordDecl *RD) {
4771 for (
auto *FD : RD->
fields()) {
4772 if (isTopLevelBlockPointerType(FD->
getType()))
4773 RewriteBlockPointerDecl(FD);
4776 RewriteObjCQualifiedInterfaceTypes(FD);
4782void RewriteObjC::HandleDeclInMainFile(
Decl *
D) {
4783 switch (
D->getKind()) {
4784 case Decl::Function: {
4792 RewriteBlocksInFunctionProtoType(FD->
getType(), FD);
4799 CurFunctionDef = FD;
4800 CurFunctionDeclToDeclareForBlock = FD;
4803 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4805 CurrentBody =
nullptr;
4806 if (PropParentMap) {
4807 delete PropParentMap;
4808 PropParentMap =
nullptr;
4812 InsertBlockLiteralsWithinFunction(FD);
4813 CurFunctionDef =
nullptr;
4814 CurFunctionDeclToDeclareForBlock =
nullptr;
4818 case Decl::ObjCMethod: {
4824 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4826 CurrentBody =
nullptr;
4827 if (PropParentMap) {
4828 delete PropParentMap;
4829 PropParentMap =
nullptr;
4831 InsertBlockLiteralsWithinMethod(MD);
4832 CurMethodDef =
nullptr;
4836 case Decl::ObjCImplementation: {
4838 ClassImplementation.push_back(CI);
4841 case Decl::ObjCCategoryImpl: {
4843 CategoryImplementation.push_back(CI);
4848 RewriteObjCQualifiedInterfaceTypes(VD);
4849 if (isTopLevelBlockPointerType(VD->
getType()))
4850 RewriteBlockPointerDecl(VD);
4852 CheckFunctionPointerDecl(VD->
getType(), VD);
4855 RewriteCastExpr(CE);
4861 RewriteRecordBody(RD);
4866 RewriteFunctionBodyOrGlobalInitializer(VD->
getInit());
4867 CurrentBody =
nullptr;
4868 if (PropParentMap) {
4869 delete PropParentMap;
4870 PropParentMap =
nullptr;
4873 GlobalVarDecl =
nullptr;
4877 RewriteCastExpr(CE);
4882 case Decl::TypeAlias:
4883 case Decl::Typedef: {
4885 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4886 RewriteBlockPointerDecl(TD);
4887 else if (TD->getUnderlyingType()->isFunctionPointerType())
4888 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4892 case Decl::CXXRecord:
4893 case Decl::Record: {
4896 RewriteRecordBody(RD);
4905void RewriteObjC::HandleTranslationUnit(
ASTContext &C) {
4914 RewriteObjCProtocolMetaData(ProtDecl,
"",
"", Preamble);
4916 InsertText(
SM->getLocForStartOfFile(MainFileID), Preamble,
false);
4917 if (ClassImplementation.size() || CategoryImplementation.size())
4918 RewriteImplementations();
4922 if (
const RewriteBuffer *RewriteBuf =
4923 Rewrite.getRewriteBufferFor(MainFileID)) {
4925 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
4927 llvm::errs() <<
"No changes\n";
4930 if (ClassImplementation.size() || CategoryImplementation.size() ||
4931 ProtocolExprDecls.size()) {
4933 std::string ResultStr;
4934 RewriteMetaDataIntoBuffer(ResultStr);
4936 *OutFile << ResultStr;
4941void RewriteObjCFragileABI::Initialize(
ASTContext &context) {
4942 InitializeCommon(context);
4948 Preamble +=
"struct objc_selector; struct objc_class;\n";
4949 Preamble +=
"struct __rw_objc_super { struct objc_object *object; ";
4950 Preamble +=
"struct objc_object *superClass; ";
4951 if (LangOpts.MicrosoftExt) {
4953 Preamble +=
"__rw_objc_super(struct objc_object *o, struct objc_object *s) "
4955 Preamble +=
"object(o), superClass(s) {} ";
4958 Preamble +=
"#ifndef _REWRITER_typedef_Protocol\n";
4959 Preamble +=
"typedef struct objc_object Protocol;\n";
4960 Preamble +=
"#define _REWRITER_typedef_Protocol\n";
4962 if (LangOpts.MicrosoftExt) {
4963 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
4964 Preamble +=
"#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
4966 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern\n";
4967 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
4968 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4969 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
4970 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4971 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
4972 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4973 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
4974 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4975 Preamble +=
"__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
4976 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4977 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
4979 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
4980 Preamble +=
"(struct objc_class *);\n";
4981 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
4983 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
4984 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
4985 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
4986 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
4987 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_exception_match";
4988 Preamble +=
"(struct objc_class *, struct objc_object *);\n";
4990 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
4991 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
4992 Preamble +=
"__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
4993 Preamble +=
"#ifndef __FASTENUMERATIONSTATE\n";
4994 Preamble +=
"struct __objcFastEnumerationState {\n\t";
4995 Preamble +=
"unsigned long state;\n\t";
4996 Preamble +=
"void **itemsPtr;\n\t";
4997 Preamble +=
"unsigned long *mutationsPtr;\n\t";
4998 Preamble +=
"unsigned long extra[5];\n};\n";
4999 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
5000 Preamble +=
"#define __FASTENUMERATIONSTATE\n";
5002 Preamble +=
"#ifndef __NSCONSTANTSTRINGIMPL\n";
5003 Preamble +=
"struct __NSConstantStringImpl {\n";
5009 Preamble +=
"#ifdef CF_EXPORT_CONSTANT_STRING\n";
5010 Preamble +=
"extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5012 Preamble +=
"__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5014 Preamble +=
"#define __NSCONSTANTSTRINGIMPL\n";
5017 Preamble +=
"#ifndef BLOCK_IMPL\n";
5018 Preamble +=
"#define BLOCK_IMPL\n";
5019 Preamble +=
"struct __block_impl {\n";
5025 Preamble +=
"// Runtime copy/destroy helper functions (from Block_private.h)\n";
5026 Preamble +=
"#ifdef __OBJC_EXPORT_BLOCKS\n";
5027 Preamble +=
"extern \"C\" __declspec(dllexport) "
5028 "void _Block_object_assign(void *, const void *, const int);\n";
5029 Preamble +=
"extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5030 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5031 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5033 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5034 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5035 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5036 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5039 if (LangOpts.MicrosoftExt) {
5040 Preamble +=
"#undef __OBJC_RW_DLLIMPORT\n";
5041 Preamble +=
"#undef __OBJC_RW_STATICIMPORT\n";
5042 Preamble +=
"#ifndef KEEP_ATTRIBUTES\n";
5043 Preamble +=
"#define __attribute__(X)\n";
5053 Preamble +=
"\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5058void RewriteObjCFragileABI::RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
5059 std::string &Result) {
5065 Result +=
"__OFFSETOFIVAR__(struct ";
5067 if (LangOpts.MicrosoftExt)
5076void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
5078 StringRef ClassName, std::string &Result) {
5079 static bool objc_protocol_methods =
false;
5088 Result +=
"\nstruct _protocol_methods {\n";
5089 Result +=
"\tstruct objc_selector *_cmd;\n";
5090 Result +=
"\tchar *method_types;\n";
5093 objc_protocol_methods =
true;
5110 Result +=
"\nstatic struct {\n";
5111 Result +=
"\tint protocol_method_count;\n";
5112 Result +=
"\tstruct _protocol_methods protocol_methods[";
5113 Result += utostr(NumMethods);
5114 Result +=
"];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
5116 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
5117 "{\n\t" + utostr(NumMethods) +
"\n";
5124 Result +=
"\t ,{{(struct objc_selector *)\"";
5126 Result +=
"\t ,{(struct objc_selector *)\"";
5127 Result += (*I)->getSelector().getAsString();
5128 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
5130 Result += MethodTypeString;
5133 Result +=
"\t }\n};\n";
5139 if (NumMethods > 0) {
5145 Result +=
"\nstatic struct {\n";
5146 Result +=
"\tint protocol_method_count;\n";
5147 Result +=
"\tstruct _protocol_methods protocol_methods[";
5148 Result += utostr(NumMethods);
5149 Result +=
"];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
5151 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
5153 Result += utostr(NumMethods);
5161 Result +=
"\t ,{{(struct objc_selector *)\"";
5163 Result +=
"\t ,{(struct objc_selector *)\"";
5164 Result += (*I)->getSelector().getAsString();
5165 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
5167 Result += MethodTypeString;
5170 Result +=
"\t }\n};\n";
5183 static bool objc_protocol =
false;
5184 if (!objc_protocol) {
5185 Result +=
"\nstruct _objc_protocol {\n";
5186 Result +=
"\tstruct _objc_protocol_extension *isa;\n";
5187 Result +=
"\tchar *protocol_name;\n";
5188 Result +=
"\tstruct _objc_protocol **protocol_list;\n";
5189 Result +=
"\tstruct _objc_protocol_method_list *instance_methods;\n";
5190 Result +=
"\tstruct _objc_protocol_method_list *class_methods;\n";
5193 objc_protocol =
true;
5196 Result +=
"\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
5198 Result +=
" __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
5201 Result +=
"\", 0, ";
5203 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
5210 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
5220 llvm_unreachable(
"protocol already synthesized");
5223void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
5225 StringRef prefix, StringRef ClassName,
5226 std::string &Result) {
5227 if (Protocols.
empty())
return;
5229 for (
unsigned i = 0; i != Protocols.
size(); i++)
5230 RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
5239 Result +=
"\nstatic struct {\n";
5240 Result +=
"\tstruct _objc_protocol_list *next;\n";
5241 Result +=
"\tint protocol_count;\n";
5242 Result +=
"\tstruct _objc_protocol *class_protocols[";
5243 Result += utostr(Protocols.
size());
5244 Result +=
"];\n} _OBJC_";
5246 Result +=
"_PROTOCOLS_";
5247 Result += ClassName;
5248 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
5250 Result += utostr(Protocols.
size());
5253 Result +=
"\t,{&_OBJC_PROTOCOL_";
5254 Result += Protocols[0]->getNameAsString();
5257 for (
unsigned i = 1; i != Protocols.
size(); i++) {
5258 Result +=
"\t ,&_OBJC_PROTOCOL_";
5259 Result += Protocols[i]->getNameAsString();
5262 Result +=
"\t }\n};\n";
5266 std::string &Result) {
5273 RewriteObjCInternalStruct(CDecl, Result);
5280 static bool objc_ivar =
false;
5288 Result +=
"\nstruct _objc_ivar {\n";
5289 Result +=
"\tchar *ivar_name;\n";
5290 Result +=
"\tchar *ivar_type;\n";
5291 Result +=
"\tint ivar_offset;\n";
5302 Result +=
"\nstatic struct {\n";
5303 Result +=
"\tint ivar_count;\n";
5304 Result +=
"\tstruct _objc_ivar ivar_list[";
5305 Result += utostr(NumIvars);
5306 Result +=
"];\n} _OBJC_INSTANCE_VARIABLES_";
5308 Result +=
" __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
5310 Result += utostr(NumIvars);
5316 for (
auto *IV : IDecl->
ivars())
5317 IVars.push_back(IV);
5324 Result +=
"\t,{{\"";
5325 Result += IVI->getNameAsString();
5327 std::string TmpString, StrEncoding;
5328 Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);
5329 QuoteDoublequotes(TmpString, StrEncoding);
5330 Result += StrEncoding;
5332 RewriteIvarOffsetComputation(*IVI, Result);
5334 for (++IVI; IVI != IVE; ++IVI) {
5335 Result +=
"\t ,{\"";
5336 Result += IVI->getNameAsString();
5338 std::string TmpString, StrEncoding;
5339 Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);
5340 QuoteDoublequotes(TmpString, StrEncoding);
5341 Result += StrEncoding;
5343 RewriteIvarOffsetComputation(*IVI, Result);
5347 Result +=
"\t }\n};\n";
5356 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
5358 if (!Prop->getPropertyIvarDecl())
5364 if (!Getter->isDefined())
5365 InstanceMethods.push_back(Getter);
5369 if (!Setter->isDefined())
5370 InstanceMethods.push_back(Setter);
5372 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5373 true,
"", IDecl->
getName(), Result);
5377 false,
"", IDecl->
getName(), Result);
5381 "CLASS", CDecl->
getName(), Result);
5399 static bool objc_class =
false;
5401 Result +=
"\nstruct _objc_class {\n";
5402 Result +=
"\tstruct _objc_class *isa;\n";
5403 Result +=
"\tconst char *super_class_name;\n";
5404 Result +=
"\tchar *name;\n";
5405 Result +=
"\tlong version;\n";
5406 Result +=
"\tlong info;\n";
5407 Result +=
"\tlong instance_size;\n";
5408 Result +=
"\tstruct _objc_ivar_list *ivars;\n";
5409 Result +=
"\tstruct _objc_method_list *methods;\n";
5410 Result +=
"\tstruct objc_cache *cache;\n";
5411 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5412 Result +=
"\tconst char *ivar_layout;\n";
5413 Result +=
"\tstruct _objc_class_ext *ext;\n";
5421 while (SuperClass) {
5422 RootClass = SuperClass;
5427 Result +=
"\nstatic struct _objc_class _OBJC_METACLASS_";
5429 Result +=
" __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
5430 "{\n\t(struct _objc_class *)\"";
5442 Result +=
", 0, \"";
5448 Result +=
", 0,2, sizeof(struct _objc_class), 0";
5450 Result +=
"\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
5457 Result +=
"\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
5462 Result +=
"\t,0,0,0,0\n";
5466 Result +=
"\nstatic struct _objc_class _OBJC_CLASS_";
5468 Result +=
" __attribute__ ((used, section (\"__OBJC, __class\")))= "
5469 "{\n\t&_OBJC_METACLASS_";
5479 Result +=
", 0, \"";
5485 if (!ObjCSynthesizedStructs.count(CDecl))
5489 Result +=
",sizeof(struct ";
5491 if (LangOpts.MicrosoftExt)
5496 Result +=
", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
5503 Result +=
", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
5505 Result +=
", 0\n\t";
5510 Result +=
", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
5512 Result +=
", 0,0\n";
5515 Result +=
",0,0,0\n";
5519void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
5520 int ClsDefCount = ClassImplementation.size();
5521 int CatDefCount = CategoryImplementation.size();
5524 for (
int i = 0; i < ClsDefCount; i++)
5525 RewriteObjCClassMetaData(ClassImplementation[i], Result);
5528 for (
int i = 0; i < CatDefCount; i++)
5529 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
5543 Result +=
"\nstruct _objc_symtab {\n";
5544 Result +=
"\tlong sel_ref_cnt;\n";
5545 Result +=
"\tSEL *refs;\n";
5546 Result +=
"\tshort cls_def_cnt;\n";
5547 Result +=
"\tshort cat_def_cnt;\n";
5548 Result +=
"\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+
"];\n";
5551 Result +=
"static struct _objc_symtab "
5552 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
5553 Result +=
"\t0, 0, " + utostr(ClsDefCount)
5554 +
", " + utostr(CatDefCount) +
"\n";
5555 for (
int i = 0; i < ClsDefCount; i++) {
5556 Result +=
"\t,&_OBJC_CLASS_";
5557 Result += ClassImplementation[i]->getNameAsString();
5561 for (
int i = 0; i < CatDefCount; i++) {
5562 Result +=
"\t,&_OBJC_CATEGORY_";
5563 Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
5565 Result += CategoryImplementation[i]->getNameAsString();
5582 Result +=
"\nstruct _objc_module {\n";
5583 Result +=
"\tlong version;\n";
5584 Result +=
"\tlong size;\n";
5585 Result +=
"\tconst char *name;\n";
5586 Result +=
"\tstruct _objc_symtab *symtab;\n";
5588 Result +=
"static struct _objc_module "
5589 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
5590 Result +=
"\t" + utostr(OBJC_ABI_VERSION) +
5591 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
5594 if (LangOpts.MicrosoftExt) {
5595 if (ProtocolExprDecls.size()) {
5596 Result +=
"#pragma section(\".objc_protocol$B\",long,read,write)\n";
5597 Result +=
"#pragma data_seg(push, \".objc_protocol$B\")\n";
5599 Result +=
"static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
5600 Result += ProtDecl->getNameAsString();
5601 Result +=
" = &_OBJC_PROTOCOL_";
5602 Result += ProtDecl->getNameAsString();
5605 Result +=
"#pragma data_seg(pop)\n\n";
5607 Result +=
"#pragma section(\".objc_module_info$B\",long,read,write)\n";
5608 Result +=
"#pragma data_seg(push, \".objc_module_info$B\")\n";
5609 Result +=
"static struct _objc_module *_POINTER_OBJC_MODULES = ";
5610 Result +=
"&_OBJC_MODULES;\n";
5611 Result +=
"#pragma data_seg(pop)\n\n";
5618 std::string &Result) {
5625 FullCategoryName +=
'_';
5634 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
5636 if (!Prop->getPropertyIvarDecl())
5642 InstanceMethods.push_back(Getter);
5646 InstanceMethods.push_back(Setter);
5648 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5649 true,
"CATEGORY_", FullCategoryName, Result);
5653 false,
"CATEGORY_", FullCategoryName, Result);
5659 FullCategoryName, Result);
5673 static bool objc_category =
false;
5674 if (!objc_category) {
5675 Result +=
"\nstruct _objc_category {\n";
5676 Result +=
"\tchar *category_name;\n";
5677 Result +=
"\tchar *class_name;\n";
5678 Result +=
"\tstruct _objc_method_list *instance_methods;\n";
5679 Result +=
"\tstruct _objc_method_list *class_methods;\n";
5680 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5681 Result +=
"\tunsigned int size;\n";
5682 Result +=
"\tstruct _objc_property_list *instance_properties;\n";
5684 objc_category =
true;
5686 Result +=
"\nstatic struct _objc_category _OBJC_CATEGORY_";
5687 Result += FullCategoryName;
5688 Result +=
" __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
5690 Result +=
"\"\n\t, \"";
5695 Result +=
"\t, (struct _objc_method_list *)"
5696 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
5697 Result += FullCategoryName;
5701 Result +=
"\t, 0\n";
5703 Result +=
"\t, (struct _objc_method_list *)"
5704 "&_OBJC_CATEGORY_CLASS_METHODS_";
5705 Result += FullCategoryName;
5709 Result +=
"\t, 0\n";
5712 Result +=
"\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
5713 Result += FullCategoryName;
5717 Result +=
"\t, 0\n";
5718 Result +=
"\t, sizeof(struct _objc_category), 0\n};\n";
5723template<
typename MethodIterator>
5724void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5725 MethodIterator MethodEnd,
5726 bool IsInstanceMethod,
5728 StringRef ClassName,
5729 std::string &Result) {
5730 if (MethodBegin == MethodEnd)
return;
5732 if (!objc_impl_method) {
5739 Result +=
"\nstruct _objc_method {\n";
5740 Result +=
"\tSEL _cmd;\n";
5741 Result +=
"\tchar *method_types;\n";
5742 Result +=
"\tvoid *_imp;\n";
5745 objc_impl_method =
true;
5756 unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
5757 Result +=
"\nstatic struct {\n";
5758 Result +=
"\tstruct _objc_method_list *next_method;\n";
5759 Result +=
"\tint method_count;\n";
5760 Result +=
"\tstruct _objc_method method_list[";
5761 Result += utostr(NumMethods);
5762 Result +=
"];\n} _OBJC_";
5765 Result +=
"_METHODS_";
5766 Result += ClassName;
5767 Result +=
" __attribute__ ((used, section (\"__OBJC, __";
5769 Result +=
"_meth\")))= ";
5770 Result +=
"{\n\t0, " + utostr(NumMethods) +
"\n";
5772 Result +=
"\t,{{(SEL)\"";
5773 Result += (*MethodBegin)->getSelector().getAsString();
5774 std::string MethodTypeString =
5775 Context->getObjCEncodingForMethodDecl(*MethodBegin);
5777 Result += MethodTypeString;
5778 Result +=
"\", (void *)";
5779 Result += MethodInternalNames[*MethodBegin];
5781 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
5782 Result +=
"\t ,{(SEL)\"";
5783 Result += (*MethodBegin)->getSelector().getAsString();
5784 std::string MethodTypeString =
5785 Context->getObjCEncodingForMethodDecl(*MethodBegin);
5787 Result += MethodTypeString;
5788 Result +=
"\", (void *)";
5789 Result += MethodInternalNames[*MethodBegin];
5792 Result +=
"\t }\n};\n";
5801 DisableReplaceStmtScope S(*
this);
5802 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
5808 Expr *Replacement = IV;
5813 assert(iFaceDecl &&
"RewriteObjCIvarRefExpr - iFaceDecl is null");
5818 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5821 std::string RecName =
5826 RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
5828 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5829 QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
5841 *Context, PE,
true,
D,
D->getType(), VK_LValue, OK_Ordinary);
5848 assert(!IV->
isFreeIvar() &&
"Cannot have a free standing ivar outside a method");
5859 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5862 std::string RecName =
5867 RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
5869 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5870 QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
5884 ReplaceStmtWithRange(IV, Replacement, OldRange);
Defines the Diagnostic-related interfaces.
enum clang::sema::@1655::IndirectLocalPathEntry::EntryKind Kind
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the SourceManager interface.
__device__ __2f16 float c
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
A builtin binary operation expression such as "x + y" or "x <= y".
Represents a block literal declaration, which is like an unnamed FunctionDecl.
param_iterator param_end()
MutableArrayRef< ParmVarDecl * >::iterator param_iterator
param_iterator param_begin()
ArrayRef< Capture > captures() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
const Stmt * getBody() const
const FunctionProtoType * getFunctionType() const
getFunctionType - Return the underlying function type for this block.
const BlockDecl * getBlockDecl() const
QualType getPointeeType() const
BreakStmt - This represents a break.
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr....
SourceLocation getRParenLoc() const
SourceLocation getLParenLoc() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CompoundLiteralExpr - [C99 6.5.2.5].
CompoundStmt - This represents a group of statements like { stmt stmt }.
SourceLocation getBeginLoc() const
ConditionalOperator - The ?: ternary operator.
ContinueStmt - This represents a continue.
decl_iterator - Iterates through the declarations stored within this context.
Iterates over a filtered subrange of declarations stored in a DeclContext.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
SourceLocation getLocation() const
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
decl_iterator decl_begin()
Decl - This represents one declaration (or definition), e.g.
SourceLocation getEndLoc() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getTypeSpecStartLoc() const
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
bool hasErrorOccurred() const
This represents one expression.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Represents a prototype with parameter type info, e.g.
unsigned getNumParams() const
QualType getParamType(unsigned i) const
bool isVariadic() const
Whether this function prototype is variadic.
ArrayRef< QualType > param_types() const
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Describes an C or C++ initializer list.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Represents a linkage specification.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
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...
Represents Objective-C's @catch statement.
const VarDecl * getCatchParamDecl() const
const Stmt * getCatchBody() const
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getRParenLoc() const
Represents Objective-C's @finally statement.
Represents Objective-C's @synchronized statement.
Represents Objective-C's @throw statement.
Represents Objective-C's @try ... @catch ... @finally statement.
ObjCCategoryDecl - Represents a category declaration.
protocol_iterator protocol_end() const
protocol_iterator protocol_begin() const
const ObjCProtocolList & getReferencedProtocols() const
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.
classmeth_iterator classmeth_end() const
SourceRange getAtEndRange() const
classmeth_iterator classmeth_begin() const
instmeth_range instance_methods() const
instmeth_iterator instmeth_end() const
SourceLocation getAtStartLoc() const
instprop_range instance_properties() const
instmeth_iterator instmeth_begin() const
classmeth_range class_methods() const
ObjCEncodeExpr, used for @encode in Objective-C.
QualType getEncodedType() const
Represents Objective-C's collection statement.
propimpl_range property_impls() const
const ObjCInterfaceDecl * getClassInterface() const
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
std::string getNameAsString() const
Get the name of the class associated with this interface.
ivar_iterator ivar_begin() const
StringRef getName() const
getName - Get the name of identifier for the class interface associated with this implementation as a...
ivar_iterator ivar_end() const
unsigned ivar_size() const
Represents an ObjC class declaration.
ivar_iterator ivar_end() const
unsigned ivar_size() const
ObjCIvarDecl * lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared)
bool isImplicitInterfaceDecl() const
isImplicitInterfaceDecl - check that this is an implicitly declared ObjCInterfaceDecl node.
ObjCCategoryDecl * FindCategoryDeclaration(const IdentifierInfo *CategoryId) const
FindCategoryDeclaration - Finds category declaration in the list of categories for this class and ret...
ivar_iterator ivar_begin() const
protocol_iterator protocol_end() const
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
const ObjCProtocolList & getReferencedProtocols() const
SourceLocation getEndOfDefinitionLoc() const
protocol_iterator protocol_begin() const
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
ObjCInterfaceDecl * getSuperClass() const
Interfaces are the core concept in Objective-C for object oriented design.
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarRefExpr - A reference to an ObjC instance variable.
const Expr * getBase() const
ObjCList - This is a simple template class used to hold various lists of decls etc,...
An expression that sends a message to the given Objective-C object or class.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
void getSelectorLocs(SmallVectorImpl< SourceLocation > &SelLocs) const
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getLeftLoc() const
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super',...
Selector getSelector() const
TypeSourceInfo * getClassReceiverTypeInfo() const
Returns a type-source information of a class message send, or nullptr if the message is not a class m...
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
QualType getSuperType() const
Retrieve the type referred to by 'super'.
const ObjCMethodDecl * getMethodDecl() const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getRightLoc() const
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver.
ObjCMethodDecl - Represents an instance or class method declaration.
ImplicitParamDecl * getSelfDecl() const
ArrayRef< ParmVarDecl * > parameters() const
CompoundStmt * getCompoundBody()
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
Selector getSelector() const
bool isInstanceMethod() const
QualType getReturnType() const
ObjCInterfaceDecl * getClassInterface()
Represents a pointer to an Objective C object.
Represents a class type in Objective C.
Represents one property declaration in an Objective-C interface.
SourceLocation getAtLoc() const
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
ObjCPropertyAttribute::Kind getPropertyAttributes() const
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
ObjCIvarDecl * getPropertyIvarDecl() const
Kind getPropertyImplementation() const
ObjCPropertyDecl * getPropertyDecl() const
ObjCMethodDecl * getSetterMethodDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
ObjCMethodDecl * getGetterMethodDecl() const
Represents an Objective-C protocol declaration.
bool hasDefinition() const
Determine whether this protocol has a definition.
bool isThisDeclarationADefinition() const
Determine whether this particular declaration is also the definition.
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
ObjCProtocolExpr used for protocol expression in Objective-C.
ObjCProtocolDecl * getProtocol() const
ObjCSelectorExpr used for @selector in Objective-C.
Selector getSelector() const
ObjCStringLiteral, used for Objective-C string literals i.e.
StringLiteral * getString()
ParenExpr - This represents a parenthesized expression, e.g.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Expr * getResultExpr()
Return the result-bearing expression, or null if there is none.
unsigned getNumSemanticExprs() const
Expr * getSemanticExpr(unsigned index)
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
QualType IgnoreParens() const
Returns the specified type after dropping any outer-level parentheses.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const
bool isConstQualified() const
Determine whether this type is const-qualified.
bool isObjCGCWeak() const
true when Type is objc's weak.
unsigned getCVRQualifiers() const
Retrieve the set of CVR (const-volatile-restrict) qualifiers applied to this type.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Represents a struct/union/class.
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Rewriter - This is the main interface to the rewrite buffers.
std::string getAsString() const
Derive the full selector name (e.g.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
unsigned getByteLength() const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
The top declaration context.
Represents a declaration of a type.
Represents a typeof (or typeof) expression (a C23 feature and GCC extension) or a typeof_unqual expre...
Expr * getUnderlyingExpr() const
A container of type source information.
The base class of the type hierarchy.
bool isBlockPointerType() const
bool isFunctionPointerType() const
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
const ObjCObjectPointerType * getAsObjCInterfacePointerType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
bool isObjCQualifiedIdType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isObjCQualifiedInterfaceType() const
bool isObjCObjectPointerType() const
bool isObjCQualifiedClassType() const
bool isRealFloatingType() const
Floating point categories.
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Base class for declarations which introduce a typedef-name.
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
const Expr * getInit() const
StorageClass getStorageClass() const
Returns the storage class as written in the source.
@ BLOCK_BYREF_CURRENT_MAX
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
@ CF
Indicates that the tracked object is a CF object.
@ RewriteObjC
ObjC->C Rewriter.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ Rewrite
We are substituting template parameters for (typically) other template parameters in order to rewrite...
@ OK_Ordinary
An ordinary object is located at an address in memory.
std::unique_ptr< ASTConsumer > CreateObjCRewriter(const std::string &InFile, std::unique_ptr< raw_ostream > OS, DiagnosticsEngine &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning)
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
const FunctionProtoType * T
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
int printf(__constant const char *st,...) __attribute__((format(printf
Extra information about a function prototype.
Describes how types, statements, expressions, and declarations should be printed.
Iterator for iterating over Stmt * arrays that contain only T *.