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;
65 DiagnosticsEngine &Diags;
66 const LangOptions &LangOpts;
69 TranslationUnitDecl *TUDecl;
71 const char *MainFileStart, *MainFileEnd;
73 ParentMap *PropParentMap;
74 std::string InFileName;
75 std::unique_ptr<raw_ostream> OutFile;
78 TypeDecl *ProtocolTypeDecl;
79 VarDecl *GlobalVarDecl;
80 unsigned RewriteFailedDiag;
82 unsigned NumObjCStringLiterals;
83 VarDecl *ConstantStringClassReference;
84 RecordDecl *NSStringRecord;
89 unsigned TryFinallyContainsReturnDiag;
91 ObjCMethodDecl *CurMethodDef;
92 RecordDecl *SuperStructDecl;
93 RecordDecl *ConstantStringDecl;
95 FunctionDecl *MsgSendFunctionDecl;
96 FunctionDecl *MsgSendSuperFunctionDecl;
97 FunctionDecl *MsgSendStretFunctionDecl;
98 FunctionDecl *MsgSendSuperStretFunctionDecl;
99 FunctionDecl *MsgSendFpretFunctionDecl;
100 FunctionDecl *GetClassFunctionDecl;
101 FunctionDecl *GetMetaClassFunctionDecl;
102 FunctionDecl *GetSuperClassFunctionDecl;
103 FunctionDecl *SelGetUidFunctionDecl;
104 FunctionDecl *CFStringFunctionDecl;
105 FunctionDecl *SuperConstructorFunctionDecl;
106 FunctionDecl *CurFunctionDef;
107 FunctionDecl *CurFunctionDeclToDeclareForBlock;
110 SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
111 SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
112 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
113 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
114 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
115 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
116 SmallVector<Stmt *, 32> Stmts;
117 SmallVector<int, 8> ObjCBcLabelNo;
119 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
121 llvm::DenseSet<uint64_t> CopyDestroyCache;
124 SmallVector<BlockExpr *, 32> Blocks;
125 SmallVector<int, 32> InnerDeclRefsCount;
126 SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
128 SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
131 llvm::SmallSetVector<ValueDecl *, 8> BlockByCopyDecls;
132 llvm::SmallSetVector<ValueDecl *, 8> BlockByRefDecls;
133 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
134 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
135 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
137 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
142 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
146 bool SilenceRewriteMacroWarning;
147 bool objc_impl_method;
149 bool DisableReplaceStmt;
150 class DisableReplaceStmtScope {
155 DisableReplaceStmtScope(RewriteObjC &R)
156 : R(R), SavedValue(R.DisableReplaceStmt) {
157 R.DisableReplaceStmt =
true;
160 ~DisableReplaceStmtScope() {
161 R.DisableReplaceStmt = SavedValue;
165 void InitializeCommon(ASTContext &context);
169 bool HandleTopLevelDecl(DeclGroupRef D)
override {
170 for (DeclGroupRef::iterator I = D.
begin(), E = D.
end(); I != E; ++I) {
171 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
172 if (!
Class->isThisDeclarationADefinition()) {
173 RewriteForwardClassDecl(D);
178 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
179 if (!Proto->isThisDeclarationADefinition()) {
180 RewriteForwardProtocolDecl(D);
185 HandleTopLevelSingleDecl(*I);
190 void HandleTopLevelSingleDecl(Decl *D);
191 void HandleDeclInMainFile(Decl *D);
192 RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
193 DiagnosticsEngine &D,
const LangOptions &LOpts,
194 bool silenceMacroWarn);
196 ~RewriteObjC()
override {}
198 void HandleTranslationUnit(ASTContext &C)
override;
200 void ReplaceStmt(Stmt *Old, Stmt *
New) {
204 void ReplaceStmtWithRange(Stmt *Old, Stmt *
New, SourceRange SrcRange) {
205 assert(Old !=
nullptr &&
New !=
nullptr &&
"Expected non-null Stmt's");
207 Stmt *ReplacingStmt = ReplacedNodes[Old];
211 if (DisableReplaceStmt)
223 llvm::raw_string_ostream S(Str);
224 New->printPretty(S,
nullptr, PrintingPolicy(LangOpts));
227 if (!
Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
228 ReplacedNodes[Old] =
New;
231 if (SilenceRewriteMacroWarning)
237 void InsertText(SourceLocation Loc, StringRef Str,
238 bool InsertAfter =
true) {
240 if (!
Rewrite.InsertText(Loc, Str, InsertAfter) ||
241 SilenceRewriteMacroWarning)
247 void ReplaceText(SourceLocation Start,
unsigned OrigLength,
250 if (!
Rewrite.ReplaceText(Start, OrigLength, Str) ||
251 SilenceRewriteMacroWarning)
258 void RewriteRecordBody(RecordDecl *RD);
259 void RewriteInclude();
260 void RewriteForwardClassDecl(DeclGroupRef D);
261 void RewriteForwardClassDecl(
const SmallVectorImpl<Decl *> &DG);
262 void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
263 const std::string &typedefString);
264 void RewriteImplementations();
265 void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
266 ObjCImplementationDecl *IMD,
267 ObjCCategoryImplDecl *CID);
268 void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
269 void RewriteImplementationDecl(Decl *Dcl);
270 void RewriteObjCMethodDecl(
const ObjCInterfaceDecl *IDecl,
271 ObjCMethodDecl *MDecl, std::string &ResultStr);
272 void RewriteTypeIntoString(QualType T, std::string &ResultStr,
273 const FunctionType *&FPRetType);
274 void RewriteByRefString(std::string &ResultStr,
const std::string &Name,
275 ValueDecl *VD,
bool def=
false);
276 void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
277 void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
278 void RewriteForwardProtocolDecl(DeclGroupRef D);
279 void RewriteForwardProtocolDecl(
const SmallVectorImpl<Decl *> &DG);
280 void RewriteMethodDeclaration(ObjCMethodDecl *Method);
281 void RewriteProperty(ObjCPropertyDecl *prop);
282 void RewriteFunctionDecl(FunctionDecl *FD);
283 void RewriteBlockPointerType(std::string& Str, QualType Type);
284 void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
285 void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
286 void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
287 void RewriteTypeOfDecl(VarDecl *VD);
288 void RewriteObjCQualifiedInterfaceTypes(Expr *E);
291 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
292 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
293 Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
294 Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
295 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
296 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
297 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
298 Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
299 void RewriteTryReturnStmts(Stmt *S);
300 void RewriteSyncReturnStmts(Stmt *S, std::string buf);
301 Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
302 Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
303 Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
304 Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
305 SourceLocation OrigEnd);
306 Stmt *RewriteBreakStmt(BreakStmt *S);
307 Stmt *RewriteContinueStmt(ContinueStmt *S);
308 void RewriteCastExpr(CStyleCastExpr *CE);
311 void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
314 void RewriteBlockPointerDecl(NamedDecl *VD);
315 void RewriteByRefVar(VarDecl *VD);
316 Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
317 Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
318 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
320 void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
321 std::string &Result);
323 void Initialize(ASTContext &context)
override = 0;
326 virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;
327 virtual void RewriteObjCProtocolListMetaData(
const ObjCList<ObjCProtocolDecl> &Prots,
330 std::string &Result) = 0;
331 virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
332 std::string &Result) = 0;
333 virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
336 std::string &Result) = 0;
337 virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
338 std::string &Result) = 0;
341 virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;
342 virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
343 std::string &Result) = 0;
347 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
348 ArrayRef<Expr *> Args,
349 SourceLocation StartLoc=SourceLocation(),
350 SourceLocation EndLoc=SourceLocation());
351 CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
352 QualType msgSendType,
354 SmallVectorImpl<QualType> &ArgTypes,
355 SmallVectorImpl<Expr*> &MsgExprs,
356 ObjCMethodDecl *Method);
357 Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
358 SourceLocation StartLoc=SourceLocation(),
359 SourceLocation EndLoc=SourceLocation());
361 void SynthCountByEnumWithState(std::string &buf);
362 void SynthMsgSendFunctionDecl();
363 void SynthMsgSendSuperFunctionDecl();
364 void SynthMsgSendStretFunctionDecl();
365 void SynthMsgSendFpretFunctionDecl();
366 void SynthMsgSendSuperStretFunctionDecl();
367 void SynthGetClassFunctionDecl();
368 void SynthGetMetaClassFunctionDecl();
369 void SynthGetSuperClassFunctionDecl();
370 void SynthSelGetUidFunctionDecl();
371 void SynthSuperConstructorFunctionDecl();
373 std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
int flag);
374 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE,
int i,
375 StringRef funcName, std::string Tag);
376 std::string SynthesizeBlockFunc(BlockExpr *CE,
int i,
377 StringRef funcName, std::string Tag);
378 std::string SynthesizeBlockImpl(BlockExpr *CE,
379 std::string Tag, std::string Desc);
380 std::string SynthesizeBlockDescriptor(std::string DescTag,
382 int i, StringRef funcName,
384 Stmt *SynthesizeBlockCall(CallExpr *Exp,
const Expr* BlockExp);
385 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
387 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
388 Stmt *SynthBlockInitExpr(BlockExpr *Exp,
389 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);
392 QualType getProtocolType();
393 void WarnAboutReturnGotoStmts(Stmt *S);
394 void HasReturnStmts(Stmt *S,
bool &hasReturns);
395 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
396 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
397 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
399 bool IsDeclStmtInForeachHeader(DeclStmt *DS);
400 void CollectBlockDeclRefInfo(BlockExpr *Exp);
401 void GetBlockDeclRefExprs(Stmt *S);
402 void GetInnerBlockDeclRefExprs(Stmt *S,
403 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
404 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
408 bool isTopLevelBlockPointerType(QualType T) {
409 return isa<BlockPointerType>(T);
415 bool convertBlockPointerToFunctionPointer(QualType &T) {
416 if (isTopLevelBlockPointerType(T)) {
417 const auto *BPT =
T->
castAs<BlockPointerType>();
424 bool needToScanForQualifiers(QualType T);
425 QualType getSuperStructType();
426 QualType getConstantStringStructType();
427 QualType convertFunctionTypeOfBlocks(
const FunctionType *FT);
428 bool BufferContainsPPDirectives(
const char *startBuf,
const char *endBuf);
430 void convertToUnqualifiedObjCType(QualType &T) {
437 if (
const ObjCObjectPointerType * OBJPT =
439 const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
440 T = QualType(IFaceT, 0);
447 bool isObjCType(QualType T) {
457 if (
const PointerType *PT = OCT->
getAs<PointerType>()) {
458 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
459 PT->getPointeeType()->isObjCQualifiedIdType())
464 bool PointerTypeTakesAnyBlockArguments(QualType QT);
465 bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
466 void GetExtentOfArgList(
const char *Name,
const char *&LParen,
467 const char *&RParen);
469 void QuoteDoublequotes(std::string &From, std::string &To) {
470 for (
unsigned i = 0; i < From.length(); i++) {
478 QualType getSimpleFunctionType(QualType result,
479 ArrayRef<QualType> args,
480 bool variadic =
false) {
483 FunctionProtoType::ExtProtoInfo fpi;
489 CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
490 CastKind Kind, Expr *E) {
492 return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E,
nullptr,
493 FPOptionsOverride(), TInfo,
494 SourceLocation(), SourceLocation());
497 StringLiteral *getStringLiteral(StringRef Str) {
499 Context->
CharTy, llvm::APInt(32, Str.size() + 1),
nullptr,
500 ArraySizeModifier::Normal, 0);
501 return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,
502 false, StrType, SourceLocation());
508 RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
509 DiagnosticsEngine &D,
const LangOptions &LOpts,
510 bool silenceMacroWarn)
511 :
RewriteObjC(inFile, std::move(
OS), D, LOpts, silenceMacroWarn) {}
513 ~RewriteObjCFragileABI()
override {}
514 void Initialize(ASTContext &context)
override;
517 template<
typename MethodIterator>
518 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
519 MethodIterator MethodEnd,
520 bool IsInstanceMethod,
523 std::string &Result);
524 void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
525 StringRef prefix, StringRef ClassName,
526 std::string &Result)
override;
527 void RewriteObjCProtocolListMetaData(
528 const ObjCList<ObjCProtocolDecl> &Prots,
529 StringRef prefix, StringRef ClassName, std::string &Result)
override;
530 void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
531 std::string &Result)
override;
532 void RewriteMetaDataIntoBuffer(std::string &Result)
override;
533 void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
534 std::string &Result)
override;
537 void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
538 std::string &Result)
override;
539 Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV)
override;
543void RewriteObjC::RewriteBlocksInFunctionProtoType(
QualType funcType,
546 = dyn_cast<FunctionProtoType>(funcType.
IgnoreParens())) {
547 for (
const auto &I : fproto->param_types())
548 if (isTopLevelBlockPointerType(I)) {
550 RewriteBlockPointerDecl(D);
557 const PointerType *PT = funcType->
getAs<PointerType>();
558 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
559 RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
562static bool IsHeaderFile(
const std::string &Filename) {
563 std::string::size_type DotPos = Filename.rfind(
'.');
565 if (DotPos == std::string::npos) {
570 std::string Ext = Filename.substr(DotPos + 1);
573 return Ext ==
"h" || Ext ==
"hh" || Ext ==
"H";
576RewriteObjC::RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
578 bool silenceMacroWarn)
579 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(
std::move(
OS)),
580 SilenceRewriteMacroWarning(silenceMacroWarn) {
581 IsHeader = IsHeaderFile(inFile);
583 "rewriting sub-expression within a macro (may not be correct)");
586 "rewriter doesn't support user-specified control flow semantics "
587 "for @try/@finally (code may not execute properly)");
590std::unique_ptr<ASTConsumer>
592 std::unique_ptr<raw_ostream> OS,
594 bool SilenceRewriteMacroWarning) {
595 return std::make_unique<RewriteObjCFragileABI>(
596 InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);
599void RewriteObjC::InitializeCommon(
ASTContext &context) {
601 SM = &Context->getSourceManager();
603 MsgSendFunctionDecl =
nullptr;
604 MsgSendSuperFunctionDecl =
nullptr;
605 MsgSendStretFunctionDecl =
nullptr;
606 MsgSendSuperStretFunctionDecl =
nullptr;
607 MsgSendFpretFunctionDecl =
nullptr;
608 GetClassFunctionDecl =
nullptr;
609 GetMetaClassFunctionDecl =
nullptr;
610 GetSuperClassFunctionDecl =
nullptr;
611 SelGetUidFunctionDecl =
nullptr;
612 CFStringFunctionDecl =
nullptr;
613 ConstantStringClassReference =
nullptr;
614 NSStringRecord =
nullptr;
615 CurMethodDef =
nullptr;
616 CurFunctionDef =
nullptr;
617 CurFunctionDeclToDeclareForBlock =
nullptr;
618 GlobalVarDecl =
nullptr;
619 SuperStructDecl =
nullptr;
620 ProtocolTypeDecl =
nullptr;
621 ConstantStringDecl =
nullptr;
623 SuperConstructorFunctionDecl =
nullptr;
624 NumObjCStringLiterals = 0;
625 PropParentMap =
nullptr;
626 CurrentBody =
nullptr;
627 DisableReplaceStmt =
false;
628 objc_impl_method =
false;
631 MainFileID =
SM->getMainFileID();
632 llvm::MemoryBufferRef MainBuf =
SM->getBufferOrFake(MainFileID);
633 MainFileStart = MainBuf.getBufferStart();
634 MainFileEnd = MainBuf.getBufferEnd();
636 Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
643void RewriteObjC::HandleTopLevelSingleDecl(
Decl *D) {
651 Loc =
SM->getExpansionLoc(Loc);
654 if (Loc.isInvalid())
return;
658 RewriteFunctionDecl(FD);
659 }
else if (
VarDecl *FVD = dyn_cast<VarDecl>(D)) {
661 if (FVD->getName() ==
"_NSConstantStringClassReference") {
662 ConstantStringClassReference = FVD;
666 if (ID->isThisDeclarationADefinition())
667 RewriteInterfaceDecl(ID);
669 RewriteCategoryDecl(CD);
671 if (PD->isThisDeclarationADefinition())
672 RewriteProtocolDecl(PD);
676 DIEnd = LSD->decls_end();
679 if (!IFace->isThisDeclarationADefinition()) {
681 SourceLocation StartLoc = IFace->getBeginLoc();
685 StartLoc == (*DI)->getBeginLoc())
691 }
while (DI != DIEnd);
692 RewriteForwardClassDecl(DG);
698 if (!Proto->isThisDeclarationADefinition()) {
700 SourceLocation StartLoc = Proto->getBeginLoc();
704 StartLoc == (*DI)->getBeginLoc())
710 }
while (DI != DIEnd);
711 RewriteForwardProtocolDecl(DG);
716 HandleTopLevelSingleDecl(*DI);
721 if (
SM->isWrittenInMainFile(Loc))
722 return HandleDeclInMainFile(D);
729void RewriteObjC::RewriteInclude() {
730 SourceLocation LocStart =
SM->getLocForStartOfFile(MainFileID);
731 StringRef MainBuf =
SM->getBufferData(MainFileID);
732 const char *MainBufStart = MainBuf.begin();
733 const char *MainBufEnd = MainBuf.end();
734 size_t ImportLen = strlen(
"import");
737 for (
const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
738 if (*BufPtr ==
'#') {
739 if (++BufPtr == MainBufEnd)
741 while (*BufPtr ==
' ' || *BufPtr ==
'\t')
742 if (++BufPtr == MainBufEnd)
744 if (!strncmp(BufPtr,
"import", ImportLen)) {
746 SourceLocation ImportLoc =
747 LocStart.getLocWithOffset(BufPtr-MainBufStart);
748 ReplaceText(ImportLoc, ImportLen,
"include");
755static std::string getIvarAccessString(
ObjCIvarDecl *OID) {
760 S +=
"_IMPL *)self)->";
768 static bool objcGetPropertyDefined =
false;
769 static bool objcSetPropertyDefined =
false;
771 InsertText(startLoc,
"// ");
772 const char *startBuf =
SM->getCharacterData(startLoc);
773 assert((*startBuf ==
'@') &&
"bogus @synthesize location");
774 const char *semiBuf = strchr(startBuf,
';');
775 assert((*semiBuf ==
';') &&
"@synthesize: can't find ';'");
776 SourceLocation onePastSemiLoc =
777 startLoc.getLocWithOffset(semiBuf-startBuf+1);
791 bool GenGetProperty =
796 if (GenGetProperty && !objcGetPropertyDefined) {
797 objcGetPropertyDefined =
true;
799 Getr =
"\nextern \"C\" __declspec(dllimport) "
800 "id objc_getProperty(id, SEL, long, bool);\n";
807 if (GenGetProperty) {
820 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
822 std::string ParamStr =
823 FT->getParamType(i).getAsString(Context->getPrintingPolicy());
826 if (FT->isVariadic()) {
827 if (FT->getNumParams())
836 Getr +=
"return (_TYPE)";
837 Getr +=
"objc_getProperty(self, _cmd, ";
838 RewriteIvarOffsetComputation(OID, Getr);
842 Getr +=
"return " + getIvarAccessString(OID);
844 InsertText(onePastSemiLoc, Getr);
855 if (GenSetProperty && !objcSetPropertyDefined) {
856 objcSetPropertyDefined =
true;
858 Setr =
"\nextern \"C\" __declspec(dllimport) "
859 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
867 if (GenSetProperty) {
868 Setr +=
"objc_setProperty (self, _cmd, ";
869 RewriteIvarOffsetComputation(OID, Setr);
883 Setr += getIvarAccessString(OID) +
" = ";
887 InsertText(onePastSemiLoc, Setr);
891 std::string &typedefString) {
892 typedefString +=
"#ifndef _REWRITER_typedef_";
894 typedefString +=
"\n";
895 typedefString +=
"#define _REWRITER_typedef_";
897 typedefString +=
"\n";
898 typedefString +=
"typedef struct objc_object ";
900 typedefString +=
";\n#endif\n";
904 const std::string &typedefString) {
905 SourceLocation startLoc = ClassDecl->
getBeginLoc();
906 const char *startBuf =
SM->getCharacterData(startLoc);
907 const char *semiPtr = strchr(startBuf,
';');
909 ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);
912void RewriteObjC::RewriteForwardClassDecl(
DeclGroupRef D) {
913 std::string typedefString;
916 if (I == D.
begin()) {
920 typedefString +=
"// @class ";
922 typedefString +=
";\n";
924 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
931 std::string typedefString;
932 for (
unsigned i = 0; i < D.size(); i++) {
935 typedefString +=
"// @class ";
937 typedefString +=
";\n";
939 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
944void RewriteObjC::RewriteMethodDeclaration(
ObjCMethodDecl *Method) {
947 if (Method->isImplicit())
949 SourceLocation LocStart = Method->getBeginLoc();
950 SourceLocation LocEnd = Method->getEndLoc();
952 if (
SM->getExpansionLineNumber(LocEnd) >
953 SM->getExpansionLineNumber(LocStart)) {
954 InsertText(LocStart,
"#if 0\n");
955 ReplaceText(LocEnd, 1,
";\n#endif\n");
957 InsertText(LocStart,
"// ");
962 SourceLocation Loc = prop->
getAtLoc();
964 ReplaceText(Loc, 0,
"// ");
972 ReplaceText(LocStart, 0,
"// ");
977 RewriteMethodDeclaration(I);
979 RewriteMethodDeclaration(I);
983 strlen(
"@end"),
"/* @end */");
991 ReplaceText(LocStart, 0,
"// ");
994 RewriteMethodDeclaration(I);
996 RewriteMethodDeclaration(I);
1002 ReplaceText(LocEnd, strlen(
"@end"),
"/* @end */");
1005 const char *startBuf =
SM->getCharacterData(LocStart);
1006 const char *endBuf =
SM->getCharacterData(LocEnd);
1007 for (
const char *p = startBuf; p < endBuf; p++) {
1008 if (*p ==
'@' && !strncmp(p+1,
"optional", strlen(
"optional"))) {
1009 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
1010 ReplaceText(OptionalLoc, strlen(
"@optional"),
"/* @optional */");
1013 else if (*p ==
'@' && !strncmp(p+1,
"required", strlen(
"required"))) {
1014 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
1015 ReplaceText(OptionalLoc, strlen(
"@required"),
"/* @required */");
1021void RewriteObjC::RewriteForwardProtocolDecl(
DeclGroupRef D) {
1022 SourceLocation LocStart = (*D.
begin())->getBeginLoc();
1023 if (LocStart.isInvalid())
1024 llvm_unreachable(
"Invalid SourceLocation");
1026 ReplaceText(LocStart, 0,
"// ");
1031 SourceLocation LocStart = DG[0]->getBeginLoc();
1032 if (LocStart.isInvalid())
1033 llvm_unreachable(
"Invalid SourceLocation");
1035 ReplaceText(LocStart, 0,
"// ");
1038void RewriteObjC::RewriteTypeIntoString(
QualType T, std::string &ResultStr,
1040 if (T->isObjCQualifiedIdType())
1042 else if (T->isFunctionPointerType() ||
1043 T->isBlockPointerType()) {
1048 if (
const PointerType* PT = retType->
getAs<PointerType>())
1049 PointeeTy = PT->getPointeeType();
1058 ResultStr += T.getAsString(Context->getPrintingPolicy());
1063 std::string &ResultStr) {
1066 ResultStr +=
"\nstatic ";
1067 RewriteTypeIntoString(OMD->
getReturnType(), ResultStr, FPRetType);
1071 std::string NameStr;
1089 int len = selString.size();
1090 for (
int i = 0; i < len; i++)
1091 if (selString[i] ==
':')
1093 NameStr += selString;
1096 MethodInternalNames[OMD] = NameStr;
1097 ResultStr += NameStr;
1104 QualType selfTy = Context->getObjCInterfaceType(IDecl);
1105 selfTy = Context->getPointerType(selfTy);
1106 if (!LangOpts.MicrosoftExt) {
1108 ResultStr +=
"struct ";
1115 ResultStr += Context->getObjCClassType().getAsString(
1116 Context->getPrintingPolicy());
1118 ResultStr +=
" self, ";
1119 ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
1120 ResultStr +=
" _cmd";
1123 for (
const auto *PDecl : OMD->
parameters()) {
1125 if (PDecl->getType()->isObjCQualifiedIdType()) {
1132 (void)convertBlockPointerToFunctionPointer(QT);
1138 ResultStr +=
", ...";
1147 for (
unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
1148 if (i) ResultStr +=
", ";
1149 std::string ParamStr =
1150 FT->getParamType(i).getAsString(Context->getPrintingPolicy());
1151 ResultStr += ParamStr;
1153 if (FT->isVariadic()) {
1154 if (FT->getNumParams())
1165void RewriteObjC::RewriteImplementationDecl(
Decl *OID) {
1168 assert((IMD || CID) &&
"Unknown ImplementationDecl");
1175 std::string ResultStr;
1180 const char *startBuf =
SM->getCharacterData(LocStart);
1181 const char *endBuf =
SM->getCharacterData(LocEnd);
1182 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1188 std::string ResultStr;
1193 const char *startBuf =
SM->getCharacterData(LocStart);
1194 const char *endBuf =
SM->getCharacterData(LocEnd);
1195 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1198 RewritePropertyImplDecl(I, IMD, CID);
1204 std::string ResultStr;
1207 ResultStr =
"#ifndef _REWRITER_typedef_";
1210 ResultStr +=
"#define _REWRITER_typedef_";
1213 ResultStr +=
"typedef struct objc_object ";
1215 ResultStr +=
";\n#endif\n";
1219 RewriteObjCInternalStruct(ClassDecl, ResultStr);
1224 RewriteMethodDeclaration(I);
1226 RewriteMethodDeclaration(I);
1246 DisableReplaceStmtScope S(*
this);
1259 RHS =
cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1311 Stmt *Replacement = SynthMessageExpr(NewMsg);
1312 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1328 DisableReplaceStmtScope S(*
this);
1387 Stmt *Replacement = SynthMessageExpr(NewMsg);
1388 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1401void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1402 buf +=
"((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
1403 "id *, unsigned int))(void *)objc_msgSend)";
1405 buf +=
"((id)l_collection,\n\t\t";
1406 buf +=
"sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1408 buf +=
"&enumState, "
1409 "(id *)__rw_items, (unsigned int)16)";
1422 buf =
"goto __break_label_";
1423 buf += utostr(ObjCBcLabelNo.back());
1424 ReplaceText(startLoc, strlen(
"break"), buf);
1439 buf =
"goto __continue_label_";
1440 buf += utostr(ObjCBcLabelNo.back());
1441 ReplaceText(startLoc, strlen(
"continue"), buf);
1479 SourceLocation OrigEnd) {
1480 assert(!Stmts.empty() &&
"ObjCForCollectionStmt - Statement stack empty");
1482 "ObjCForCollectionStmt Statement stack mismatch");
1483 assert(!ObjCBcLabelNo.empty() &&
1484 "ObjCForCollectionStmt - Label No stack empty");
1487 const char *startBuf =
SM->getCharacterData(startLoc);
1488 StringRef elementName;
1489 std::string elementTypeAsString;
1499 elementTypeAsString =
"id";
1501 elementTypeAsString = ElementType.
getAsString(Context->getPrintingPolicy());
1502 buf += elementTypeAsString;
1515 elementTypeAsString =
"id";
1521 buf +=
"struct __objcFastEnumerationState enumState = { 0 };\n\t";
1523 buf +=
"id __rw_items[16];\n\t";
1525 buf +=
"id l_collection = (id)";
1527 const char *startCollectionBuf = startBuf;
1528 startCollectionBuf += 3;
1529 startCollectionBuf = strchr(startCollectionBuf,
'(');
1530 startCollectionBuf++;
1532 while (*startCollectionBuf !=
' ' ||
1533 *(startCollectionBuf+1) !=
'i' || *(startCollectionBuf+2) !=
'n' ||
1534 (*(startCollectionBuf+3) !=
' ' &&
1535 *(startCollectionBuf+3) !=
'[' && *(startCollectionBuf+3) !=
'('))
1536 startCollectionBuf++;
1537 startCollectionBuf += 3;
1540 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1543 const char *rparenBuf =
SM->getCharacterData(rightParenLoc);
1544 SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);
1558 buf +=
"unsigned long limit =\n\t\t";
1559 SynthCountByEnumWithState(buf);
1569 buf +=
"if (limit) {\n\t";
1570 buf +=
"unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1571 buf +=
"do {\n\t\t";
1572 buf +=
"unsigned long counter = 0;\n\t\t";
1573 buf +=
"do {\n\t\t\t";
1574 buf +=
"if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1575 buf +=
"objc_enumerationMutation(l_collection);\n\t\t\t";
1578 buf += elementTypeAsString;
1579 buf +=
")enumState.itemsPtr[counter++];";
1581 ReplaceText(lparenLoc, 1, buf);
1595 buf +=
"__continue_label_";
1596 buf += utostr(ObjCBcLabelNo.back());
1599 buf +=
"} while (counter < limit);\n\t";
1600 buf +=
"} while (limit = ";
1601 SynthCountByEnumWithState(buf);
1605 buf += elementTypeAsString;
1607 buf +=
"__break_label_";
1608 buf += utostr(ObjCBcLabelNo.back());
1611 buf +=
"else\n\t\t";
1614 buf += elementTypeAsString;
1621 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);
1622 InsertText(endBodyLoc, buf);
1631 const char *stmtBuf =
SM->getCharacterData(OrigEnd);
1632 const char *semiBuf = strchr(stmtBuf,
';');
1633 assert(semiBuf &&
"Can't find ';'");
1634 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);
1635 InsertText(endBodyLoc, buf);
1638 ObjCBcLabelNo.pop_back();
1651 const char *startBuf =
SM->getCharacterData(startLoc);
1653 assert((*startBuf ==
'@') &&
"bogus @synchronized location");
1656 buf =
"objc_sync_enter((id)";
1657 const char *lparenBuf = startBuf;
1658 while (*lparenBuf !=
'(') lparenBuf++;
1659 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1664 const char *endBuf =
SM->getCharacterData(endLoc);
1665 while (*endBuf !=
')') endBuf--;
1666 SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf);
1669 buf +=
"/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1670 buf +=
"int buf[18/*32-bit i386*/];\n";
1671 buf +=
"char *pointers[4];} _stack;\n";
1672 buf +=
"id volatile _rethrow = 0;\n";
1673 buf +=
"objc_exception_try_enter(&_stack);\n";
1674 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1675 ReplaceText(rparenLoc, 1, buf);
1677 startBuf =
SM->getCharacterData(startLoc);
1679 assert((*startBuf ==
'}') &&
"bogus @synchronized block");
1680 SourceLocation lastCurlyLoc = startLoc;
1681 buf =
"}\nelse {\n";
1682 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1684 buf +=
"{ /* implicit finally clause */\n";
1685 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1687 std::string syncBuf;
1688 syncBuf +=
" objc_sync_exit(";
1694 ? CK_BlockPointerToObjCPointerCast
1695 : CK_CPointerToObjCPointerCast;
1696 syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
1698 std::string syncExprBufS;
1699 llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1700 assert(syncExpr !=
nullptr &&
"Expected non-null Expr");
1702 syncBuf += syncExprBufS;
1706 buf +=
"\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1710 ReplaceText(lastCurlyLoc, 1, buf);
1712 bool hasReturns =
false;
1720void RewriteObjC::WarnAboutReturnGotoStmts(
Stmt *S)
1725 WarnAboutReturnGotoStmts(SubStmt);
1729 TryFinallyContainsReturnDiag);
1733void RewriteObjC::HasReturnStmts(
Stmt *S,
bool &hasReturns)
1738 HasReturnStmts(SubStmt, hasReturns);
1744void RewriteObjC::RewriteTryReturnStmts(
Stmt *S) {
1748 RewriteTryReturnStmts(SubStmt);
1752 const char *startBuf =
SM->getCharacterData(startLoc);
1753 const char *semiBuf = strchr(startBuf,
';');
1754 assert((*semiBuf ==
';') &&
"RewriteTryReturnStmts: can't find ';'");
1755 SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
1758 buf =
"{ objc_exception_try_exit(&_stack); return";
1760 ReplaceText(startLoc, 6, buf);
1761 InsertText(onePastSemiLoc,
"}");
1765void RewriteObjC::RewriteSyncReturnStmts(
Stmt *S, std::string syncExitBuf) {
1769 RewriteSyncReturnStmts(SubStmt, syncExitBuf);
1773 const char *startBuf =
SM->getCharacterData(startLoc);
1775 const char *semiBuf = strchr(startBuf,
';');
1776 assert((*semiBuf ==
';') &&
"RewriteSyncReturnStmts: can't find ';'");
1777 SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
1780 buf =
"{ objc_exception_try_exit(&_stack);";
1784 ReplaceText(startLoc, 6, buf);
1785 InsertText(onePastSemiLoc,
"}");
1792 const char *startBuf =
SM->getCharacterData(startLoc);
1794 assert((*startBuf ==
'@') &&
"bogus @try location");
1798 buf =
"/* @try scope begin */ { struct _objc_exception_data {\n";
1799 buf +=
"int buf[18/*32-bit i386*/];\n";
1800 buf +=
"char *pointers[4];} _stack;\n";
1801 buf +=
"id volatile _rethrow = 0;\n";
1802 buf +=
"objc_exception_try_enter(&_stack);\n";
1803 buf +=
"if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1805 ReplaceText(startLoc, 4, buf);
1808 startBuf =
SM->getCharacterData(startLoc);
1810 assert((*startBuf ==
'}') &&
"bogus @try block");
1812 SourceLocation lastCurlyLoc = startLoc;
1814 startLoc = startLoc.getLocWithOffset(1);
1815 buf =
" /* @catch begin */ else {\n";
1816 buf +=
" id _caught = objc_exception_extract(&_stack);\n";
1817 buf +=
" objc_exception_try_enter (&_stack);\n";
1818 buf +=
" if (_setjmp(_stack.buf))\n";
1819 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1820 buf +=
" else { /* @catch continue */";
1822 InsertText(startLoc, buf);
1824 buf =
"}\nelse {\n";
1825 buf +=
" _rethrow = objc_exception_extract(&_stack);\n";
1827 ReplaceText(lastCurlyLoc, 1, buf);
1829 Stmt *lastCatchBody =
nullptr;
1839 startBuf =
SM->getCharacterData(startLoc);
1841 assert((*startBuf ==
'@') &&
"bogus @catch location");
1843 const char *lParenLoc = strchr(startBuf,
'(');
1848 SourceLocation bodyLoc = lastCatchBody->
getBeginLoc();
1849 const char *bodyBuf =
SM->getCharacterData(bodyLoc);
1851 "bogus @catch paren location");
1852 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1854 buf +=
"1) { id _tmp = _caught;";
1855 Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
1856 }
else if (catchDecl) {
1858 if (t == Context->getObjCIdType()) {
1860 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1866 buf +=
"objc_exception_match((struct objc_class *)objc_getClass(\"";
1868 buf +=
"\"), (struct objc_object *)_caught)) { ";
1869 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1875 SourceLocation bodyLoc = lastCatchBody->
getBeginLoc();
1876 const char *bodyBuf =
SM->getCharacterData(bodyLoc);
1877 const char *rParenBuf =
SM->getCharacterData(rParenLoc);
1878 assert((*rParenBuf ==
')') &&
"bogus @catch paren location");
1879 assert((*bodyBuf ==
'{') &&
"bogus @catch body location");
1883 ReplaceText(rParenLoc, bodyBuf-rParenBuf+1,
" = _caught;");
1885 llvm_unreachable(
"@catch rewrite bug");
1889 if (lastCatchBody) {
1890 SourceLocation bodyLoc = lastCatchBody->
getEndLoc();
1891 assert(*
SM->getCharacterData(bodyLoc) ==
'}' &&
1892 "bogus @catch body location");
1895 bodyLoc = bodyLoc.getLocWithOffset(-1);
1896 buf =
"} /* last catch end */\n";
1898 buf +=
" _rethrow = _caught;\n";
1899 buf +=
" objc_exception_try_exit(&_stack);\n";
1900 buf +=
"} } /* @catch end */\n";
1903 InsertText(bodyLoc, buf);
1906 lastCurlyLoc = lastCatchBody->
getEndLoc();
1909 startLoc = finalStmt->getBeginLoc();
1910 startBuf =
SM->getCharacterData(startLoc);
1911 assert((*startBuf ==
'@') &&
"bogus @finally start");
1913 ReplaceText(startLoc, 8,
"/* @finally */");
1915 Stmt *body = finalStmt->getFinallyBody();
1917 SourceLocation endLoc = body->
getEndLoc();
1918 assert(*
SM->getCharacterData(startLoc) ==
'{' &&
1919 "bogus @finally body location");
1920 assert(*
SM->getCharacterData(endLoc) ==
'}' &&
1921 "bogus @finally body location");
1923 startLoc = startLoc.getLocWithOffset(1);
1924 InsertText(startLoc,
" if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1925 endLoc = endLoc.getLocWithOffset(-1);
1926 InsertText(endLoc,
" if (_rethrow) objc_exception_throw(_rethrow);\n");
1934 buf =
"{ /* implicit finally clause */\n";
1935 buf +=
" if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1936 buf +=
" if (_rethrow) objc_exception_throw(_rethrow);\n";
1938 ReplaceText(lastCurlyLoc, 1, buf);
1943 bool hasReturns =
false;
1949 lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1);
1950 InsertText(lastCurlyLoc,
" } /* @try scope end */\n");
1960 const char *startBuf =
SM->getCharacterData(startLoc);
1962 assert((*startBuf ==
'@') &&
"bogus @throw location");
1967 buf =
"objc_exception_throw(";
1969 buf =
"objc_exception_throw(_caught";
1972 const char *wBuf = strchr(startBuf,
'w');
1973 assert((*wBuf ==
'w') &&
"@throw: can't find 'w'");
1974 ReplaceText(startLoc, wBuf-startBuf+1, buf);
1976 const char *semiBuf = strchr(startBuf,
';');
1977 assert((*semiBuf ==
';') &&
"@throw: can't find ';'");
1978 SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
1979 ReplaceText(semiLoc, 1,
");");
1985 std::string StrEncoding;
1986 Context->getObjCEncodingForType(Exp->
getEncodedType(), StrEncoding);
1987 Expr *Replacement = getStringLiteral(StrEncoding);
1988 ReplaceStmt(Exp, Replacement);
1996 if (!SelGetUidFunctionDecl)
1997 SynthSelGetUidFunctionDecl();
1998 assert(SelGetUidFunctionDecl &&
"Can't find sel_registerName() decl");
2002 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2004 ReplaceStmt(Exp, SelExp);
2010RewriteObjC::SynthesizeCallToFunctionDecl(
FunctionDecl *FD,
2012 SourceLocation StartLoc,
2013 SourceLocation EndLoc) {
2022 QualType pToFunc = Context->getPointerType(msgSendType);
2035static bool scanForProtocolRefs(
const char *startBuf,
const char *endBuf,
2036 const char *&startRef,
const char *&endRef) {
2037 while (startBuf < endBuf) {
2038 if (*startBuf ==
'<')
2039 startRef = startBuf;
2040 if (*startBuf ==
'>') {
2041 if (startRef && *startRef ==
'<') {
2052static void scanToNextArgument(
const char *&argRef) {
2054 while (*argRef !=
')' && (*argRef !=
',' || angle > 0)) {
2057 else if (*argRef ==
'>')
2061 assert(angle == 0 &&
"scanToNextArgument - bad protocol type syntax");
2064bool RewriteObjC::needToScanForQualifiers(
QualType T) {
2065 if (T->isObjCQualifiedIdType())
2067 if (
const PointerType *PT = T->getAs<PointerType>()) {
2068 if (PT->getPointeeType()->isObjCQualifiedIdType())
2071 if (T->isObjCObjectPointerType()) {
2072 T = T->getPointeeType();
2073 return T->isObjCQualifiedInterfaceType();
2075 if (T->isArrayType()) {
2076 QualType ElemTy = Context->getBaseElementType(T);
2077 return needToScanForQualifiers(ElemTy);
2082void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Expr *E) {
2084 if (needToScanForQualifiers(Type)) {
2085 SourceLocation Loc, EndLoc;
2088 Loc = ECE->getLParenLoc();
2089 EndLoc = ECE->getRParenLoc();
2095 if (Loc.isInvalid() || EndLoc.isInvalid())
2098 const char *startBuf =
SM->getCharacterData(Loc);
2099 const char *endBuf =
SM->getCharacterData(EndLoc);
2100 const char *startRef =
nullptr, *endRef =
nullptr;
2101 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2103 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
2104 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);
2106 InsertText(LessLoc,
"/*");
2107 InsertText(GreaterLoc,
"*/");
2112void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(
Decl *Dcl) {
2116 if (
VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2120 else if (
FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2125 assert(funcType &&
"missing function type");
2126 proto = dyn_cast<FunctionProtoType>(funcType);
2131 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2138 if (needToScanForQualifiers(Type)) {
2141 const char *endBuf =
SM->getCharacterData(Loc);
2142 const char *startBuf = endBuf;
2143 while (*startBuf !=
';' && *startBuf !=
'<' && startBuf != MainFileStart)
2145 const char *startRef =
nullptr, *endRef =
nullptr;
2146 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2148 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
2149 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);
2151 InsertText(LessLoc,
"/*");
2152 InsertText(GreaterLoc,
"*/");
2158 const char *startBuf =
SM->getCharacterData(Loc);
2159 const char *startFuncBuf = startBuf;
2164 const char *endBuf = startBuf;
2166 scanToNextArgument(endBuf);
2167 const char *startRef =
nullptr, *endRef =
nullptr;
2168 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2170 SourceLocation LessLoc =
2171 Loc.getLocWithOffset(startRef-startFuncBuf);
2172 SourceLocation GreaterLoc =
2173 Loc.getLocWithOffset(endRef-startFuncBuf+1);
2175 InsertText(LessLoc,
"/*");
2176 InsertText(GreaterLoc,
"*/");
2178 startBuf = ++endBuf;
2183 while (*startBuf && *startBuf !=
')' && *startBuf !=
',')
2190void RewriteObjC::RewriteTypeOfDecl(
VarDecl *ND) {
2192 const Type* TypePtr = QT->
getAs<Type>();
2198 TypePtr = QT->
getAs<Type>();
2202 std::string TypeAsString(QT.
getAsString(Context->getPrintingPolicy()));
2204 const char *startBuf =
SM->getCharacterData(DeclLoc);
2207 TypeAsString +=
" " + Name +
" = ";
2209 SourceLocation startLoc;
2211 startLoc = ECE->getLParenLoc();
2214 startLoc =
SM->getExpansionLoc(startLoc);
2215 const char *endBuf =
SM->getCharacterData(startLoc);
2216 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2220 X =
SM->getExpansionLoc(
X);
2221 const char *endBuf =
SM->getCharacterData(
X);
2222 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2227void RewriteObjC::SynthSelGetUidFunctionDecl() {
2228 IdentifierInfo *SelGetUidIdent = &Context->Idents.get(
"sel_registerName");
2230 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2232 getSimpleFunctionType(Context->getObjCSelType(), ArgTys);
2236 SelGetUidIdent, getFuncType,
2240void RewriteObjC::RewriteFunctionDecl(
FunctionDecl *FD) {
2243 FD->
getName() ==
"sel_registerName") {
2244 SelGetUidFunctionDecl = FD;
2247 RewriteObjCQualifiedInterfaceTypes(FD);
2250void RewriteObjC::RewriteBlockPointerType(std::string& Str,
QualType Type) {
2251 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
2252 const char *argPtr = TypeString.c_str();
2253 if (!strchr(argPtr,
'^')) {
2258 Str += (*argPtr ==
'^' ?
'*' : *argPtr);
2264void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2267 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
2268 const char *argPtr = TypeString.c_str();
2293void RewriteObjC::RewriteBlockLiteralFunctionDecl(
FunctionDecl *FD) {
2299 QualType Type = proto->getReturnType();
2300 std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
2304 unsigned numArgs = proto->getNumParams();
2305 for (
unsigned i = 0; i < numArgs; i++) {
2306 QualType ArgType = proto->getParamType(i);
2307 RewriteBlockPointerType(FdStr, ArgType);
2312 InsertText(FunLocStart, FdStr);
2313 CurFunctionDeclToDeclareForBlock =
nullptr;
2317void RewriteObjC::SynthSuperConstructorFunctionDecl() {
2318 if (SuperConstructorFunctionDecl)
2320 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"__rw_objc_super");
2322 QualType argT = Context->getObjCIdType();
2323 assert(!argT.
isNull() &&
"Can't find 'id' type");
2324 ArgTys.push_back(argT);
2325 ArgTys.push_back(argT);
2326 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2331 msgSendIdent, msgSendType,
2336void RewriteObjC::SynthMsgSendFunctionDecl() {
2337 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"objc_msgSend");
2339 QualType argT = Context->getObjCIdType();
2340 assert(!argT.
isNull() &&
"Can't find 'id' type");
2341 ArgTys.push_back(argT);
2342 argT = Context->getObjCSelType();
2343 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2344 ArgTys.push_back(argT);
2345 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2350 msgSendIdent, msgSendType,
2355void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2356 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"objc_msgSendSuper");
2359 SourceLocation(), SourceLocation(),
2360 &Context->Idents.get(
"objc_super"));
2361 QualType argT = Context->getPointerType(Context->getCanonicalTagType(RD));
2362 assert(!argT.
isNull() &&
"Can't build 'struct objc_super *' type");
2363 ArgTys.push_back(argT);
2364 argT = Context->getObjCSelType();
2365 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2366 ArgTys.push_back(argT);
2367 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2372 msgSendIdent, msgSendType,
2377void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2378 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"objc_msgSend_stret");
2380 QualType argT = Context->getObjCIdType();
2381 assert(!argT.
isNull() &&
"Can't find 'id' type");
2382 ArgTys.push_back(argT);
2383 argT = Context->getObjCSelType();
2384 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2385 ArgTys.push_back(argT);
2386 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2391 msgSendIdent, msgSendType,
2397void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2399 &Context->Idents.get(
"objc_msgSendSuper_stret");
2402 SourceLocation(), SourceLocation(),
2403 &Context->Idents.get(
"objc_super"));
2404 QualType argT = Context->getPointerType(Context->getCanonicalTagType(RD));
2405 assert(!argT.
isNull() &&
"Can't build 'struct objc_super *' type");
2406 ArgTys.push_back(argT);
2407 argT = Context->getObjCSelType();
2408 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2409 ArgTys.push_back(argT);
2410 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2416 msgSendType,
nullptr,
2421void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2422 IdentifierInfo *msgSendIdent = &Context->Idents.get(
"objc_msgSend_fpret");
2424 QualType argT = Context->getObjCIdType();
2425 assert(!argT.
isNull() &&
"Can't find 'id' type");
2426 ArgTys.push_back(argT);
2427 argT = Context->getObjCSelType();
2428 assert(!argT.
isNull() &&
"Can't find 'SEL' type");
2429 ArgTys.push_back(argT);
2430 QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
2435 msgSendIdent, msgSendType,
2440void RewriteObjC::SynthGetClassFunctionDecl() {
2441 IdentifierInfo *getClassIdent = &Context->Idents.get(
"objc_getClass");
2443 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2444 QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
2449 getClassIdent, getClassType,
2454void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2456 &Context->Idents.get(
"class_getSuperclass");
2458 ArgTys.push_back(Context->getObjCClassType());
2459 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2465 getClassType,
nullptr,
2470void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2471 IdentifierInfo *getClassIdent = &Context->Idents.get(
"objc_getMetaClass");
2473 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2474 QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
2479 getClassIdent, getClassType,
2484 assert(Exp !=
nullptr &&
"Expected non-null ObjCStringLiteral");
2485 QualType strType = getConstantStringStructType();
2487 std::string S =
"__NSConstantStringImpl_";
2489 std::string tmpName = InFileName;
2491 for (i=0; i < tmpName.length(); i++) {
2492 char c = tmpName.at(i);
2499 S += utostr(NumObjCStringLiterals++);
2501 Preamble +=
"static __NSConstantStringImpl " + S;
2502 Preamble +=
" __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2505 std::string prettyBufS;
2506 llvm::raw_string_ostream prettyBuf(prettyBufS);
2513 SourceLocation(), &Context->Idents.get(S),
2518 const_cast<ASTContext &
>(*Context), DRE, UO_AddrOf,
2523 CK_CPointerToObjCPointerCast, Unop);
2524 ReplaceStmt(Exp,
cast);
2530QualType RewriteObjC::getSuperStructType() {
2531 if (!SuperStructDecl) {
2533 SourceLocation(), SourceLocation(),
2534 &Context->Idents.get(
"objc_super"));
2538 FieldTypes[0] = Context->getObjCIdType();
2540 FieldTypes[1] = Context->getObjCClassType();
2543 for (
unsigned i = 0; i < 2; ++i) {
2546 SourceLocation(),
nullptr,
2547 FieldTypes[i],
nullptr,
2555 return Context->getCanonicalTagType(SuperStructDecl);
2558QualType RewriteObjC::getConstantStringStructType() {
2559 if (!ConstantStringDecl) {
2562 SourceLocation(), &Context->Idents.get(
"__NSConstantStringImpl"));
2566 FieldTypes[0] = Context->getObjCIdType();
2568 FieldTypes[1] = Context->IntTy;
2570 FieldTypes[2] = Context->getPointerType(Context->CharTy);
2572 FieldTypes[3] = Context->LongTy;
2575 for (
unsigned i = 0; i < 4; ++i) {
2579 SourceLocation(),
nullptr,
2580 FieldTypes[i],
nullptr,
2588 return Context->getCanonicalTagType(ConstantStringDecl);
2599 new (Context)
DeclRefExpr(*Context, MsgSendStretFlavor,
false,
2600 msgSendType,
VK_LValue, SourceLocation());
2603 Context->getPointerType(Context->VoidTy),
2606 QualType castType = getSimpleFunctionType(returnType, ArgTypes,
2607 Method ? Method->isVariadic()
2609 castType = Context->getPointerType(castType);
2610 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2624 SourceLocation StartLoc,
2625 SourceLocation EndLoc) {
2626 if (!SelGetUidFunctionDecl)
2627 SynthSelGetUidFunctionDecl();
2628 if (!MsgSendFunctionDecl)
2629 SynthMsgSendFunctionDecl();
2630 if (!MsgSendSuperFunctionDecl)
2631 SynthMsgSendSuperFunctionDecl();
2632 if (!MsgSendStretFunctionDecl)
2633 SynthMsgSendStretFunctionDecl();
2634 if (!MsgSendSuperStretFunctionDecl)
2635 SynthMsgSendSuperStretFunctionDecl();
2636 if (!MsgSendFpretFunctionDecl)
2637 SynthMsgSendFpretFunctionDecl();
2638 if (!GetClassFunctionDecl)
2639 SynthGetClassFunctionDecl();
2640 if (!GetSuperClassFunctionDecl)
2641 SynthGetSuperClassFunctionDecl();
2642 if (!GetMetaClassFunctionDecl)
2643 SynthGetMetaClassFunctionDecl();
2650 QualType resultType = mDecl->getReturnType();
2652 MsgSendStretFlavor = MsgSendStretFunctionDecl;
2654 MsgSendFlavor = MsgSendFpretFunctionDecl;
2661 MsgSendFlavor = MsgSendSuperFunctionDecl;
2662 if (MsgSendStretFlavor)
2663 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2664 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2671 InitExprs.push_back(NoTypeInfoCStyleCastExpr(
2672 Context, Context->getObjCIdType(), CK_BitCast,
2675 SourceLocation())));
2680 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2681 ClsExprs, StartLoc, EndLoc);
2683 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2684 Context->getObjCClassType(),
2687 ClsExprs.push_back(ArgExpr);
2688 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2692 InitExprs.push_back(
2693 NoTypeInfoCStyleCastExpr(Context,
2694 Context->getObjCIdType(),
2697 QualType superType = getSuperStructType();
2700 if (LangOpts.MicrosoftExt) {
2701 SynthSuperConstructorFunctionDecl();
2704 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2716 const_cast<ASTContext &
>(*Context), SuperRep, UO_AddrOf,
2719 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2720 Context->getPointerType(superType),
2721 CK_BitCast, SuperRep);
2725 new (Context)
InitListExpr(*Context, SourceLocation(), InitExprs,
2728 = Context->getTrivialTypeSourceInfo(superType);
2734 const_cast<ASTContext &
>(*Context), SuperRep, UO_AddrOf,
2738 MsgExprs.push_back(SuperRep);
2747 ClsExprs.push_back(getStringLiteral(clsName->
getName()));
2748 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2750 MsgExprs.push_back(Cls);
2755 MsgSendFlavor = MsgSendSuperFunctionDecl;
2756 if (MsgSendStretFlavor)
2757 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2758 assert(MsgSendFlavor &&
"MsgSendFlavor is NULL!");
2762 InitExprs.push_back(NoTypeInfoCStyleCastExpr(
2763 Context, Context->getObjCIdType(), CK_BitCast,
2766 SourceLocation())));
2771 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2774 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2775 Context->getObjCClassType(),
2778 ClsExprs.push_back(ArgExpr);
2779 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2784 InitExprs.push_back(
2786 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2789 QualType superType = getSuperStructType();
2792 if (LangOpts.MicrosoftExt) {
2793 SynthSuperConstructorFunctionDecl();
2796 DeclRefExpr(*Context, SuperConstructorFunctionDecl,
false, superType,
2808 const_cast<ASTContext &
>(*Context), SuperRep, UO_AddrOf,
2811 SuperRep = NoTypeInfoCStyleCastExpr(Context,
2812 Context->getPointerType(superType),
2813 CK_BitCast, SuperRep);
2817 new (Context)
InitListExpr(*Context, SourceLocation(), InitExprs,
2820 = Context->getTrivialTypeSourceInfo(superType);
2822 SourceLocation(), superTInfo, superType,
VK_PRValue, ILE,
false);
2824 MsgExprs.push_back(SuperRep);
2833 recExpr = CE->getSubExpr();
2836 ? CK_BlockPointerToObjCPointerCast
2837 : CK_CPointerToObjCPointerCast;
2839 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2841 MsgExprs.push_back(recExpr);
2849 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2850 SelExprs, StartLoc, EndLoc);
2851 MsgExprs.push_back(SelExp);
2854 for (
unsigned i = 0; i < Exp->
getNumArgs(); i++) {
2860 if (needToScanForQualifiers(type))
2861 type = Context->getObjCIdType();
2863 (void)convertBlockPointerToFunctionPointer(type);
2867 type->isBooleanType()) {
2868 CK = CK_IntegralToBoolean;
2869 }
else if (type->isObjCObjectPointerType()) {
2871 CK = CK_BlockPointerToObjCPointerCast;
2873 CK = CK_CPointerToObjCPointerCast;
2881 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2884 else if (
CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2885 if (CE->getType()->isObjCQualifiedIdType()) {
2886 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2887 userExpr = CE->getSubExpr();
2890 CK = CK_IntegralToPointer;
2892 CK = CK_BlockPointerToObjCPointerCast;
2894 CK = CK_CPointerToObjCPointerCast;
2898 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2902 MsgExprs.push_back(userExpr);
2914 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2915 ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
2917 ArgTypes.push_back(Context->getObjCIdType());
2918 ArgTypes.push_back(Context->getObjCSelType());
2923 ? Context->getObjCIdType()
2926 (void)convertBlockPointerToFunctionPointer(t);
2927 ArgTypes.push_back(t);
2930 convertToUnqualifiedObjCType(returnType);
2931 (void)convertBlockPointerToFunctionPointer(returnType);
2933 returnType = Context->getObjCIdType();
2940 *Context, MsgSendFlavor,
false, msgSendType,
VK_LValue, SourceLocation());
2946 cast = NoTypeInfoCStyleCastExpr(Context,
2947 Context->getPointerType(Context->VoidTy),
2954 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->
isVariadic() :
true);
2955 castType = Context->getPointerType(castType);
2956 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2965 Stmt *ReplacingStmt = CE;
2966 if (MsgSendStretFlavor) {
2972 CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
2973 msgSendType, returnType,
2980 Context->getTrivialTypeSourceInfo(returnType),
2981 Context->getSizeType(), SourceLocation(),
2988 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
2990 llvm::APInt(IntSize, 8),
2994 *Context, sizeofExpr, limit, BO_LE, Context->IntTy,
VK_PRValue,
2998 lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType,
3000 ReplacingStmt =
new (Context)
ParenExpr(SourceLocation(), SourceLocation(),
3004 return ReplacingStmt;
3008 Stmt *ReplacingStmt =
3012 ReplaceStmt(Exp, ReplacingStmt);
3015 return ReplacingStmt;
3019QualType RewriteObjC::getProtocolType() {
3020 if (!ProtocolTypeDecl) {
3022 = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
3024 SourceLocation(), SourceLocation(),
3025 &Context->Idents.get(
"Protocol"),
3028 return Context->getTypeDeclType(ProtocolTypeDecl);
3039 SourceLocation(), ID, getProtocolType(),
3042 *Context, VD,
false, getProtocolType(),
VK_LValue, SourceLocation());
3044 const_cast<ASTContext &
>(*Context), DRE, UO_AddrOf,
3056bool RewriteObjC::BufferContainsPPDirectives(
const char *startBuf,
3057 const char *endBuf) {
3058 while (startBuf < endBuf) {
3059 if (*startBuf ==
'#') {
3061 for (++startBuf; startBuf[0] ==
' ' || startBuf[0] ==
'\t'; ++startBuf)
3063 if (!strncmp(startBuf,
"if", strlen(
"if")) ||
3064 !strncmp(startBuf,
"ifdef", strlen(
"ifdef")) ||
3065 !strncmp(startBuf,
"ifndef", strlen(
"ifndef")) ||
3066 !strncmp(startBuf,
"define", strlen(
"define")) ||
3067 !strncmp(startBuf,
"undef", strlen(
"undef")) ||
3068 !strncmp(startBuf,
"else", strlen(
"else")) ||
3069 !strncmp(startBuf,
"elif", strlen(
"elif")) ||
3070 !strncmp(startBuf,
"endif", strlen(
"endif")) ||
3071 !strncmp(startBuf,
"pragma", strlen(
"pragma")) ||
3072 !strncmp(startBuf,
"include", strlen(
"include")) ||
3073 !strncmp(startBuf,
"import", strlen(
"import")) ||
3074 !strncmp(startBuf,
"include_next", strlen(
"include_next")))
3085 std::string &Result) {
3086 assert(CDecl &&
"Class missing in SynthesizeObjCInternalStruct");
3087 assert(CDecl->
getName() !=
"" &&
3088 "Name missing in SynthesizeObjCInternalStruct");
3090 if (ObjCSynthesizedStructs.count(CDecl))
3097 const char *startBuf =
SM->getCharacterData(LocStart);
3098 const char *endBuf =
SM->getCharacterData(LocEnd);
3103 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3105 ReplaceText(LocStart, endBuf-startBuf, Result);
3111 Result +=
"\nstruct ";
3113 if (LangOpts.MicrosoftExt)
3117 const char *cursor = strchr(startBuf,
'{');
3118 assert((cursor && endBuf)
3119 &&
"SynthesizeObjCInternalStruct - malformed @interface");
3135 if (BufferContainsPPDirectives(startBuf, cursor)) {
3138 const char *endHeader =
SM->getCharacterData(L);
3143 while (endHeader < cursor && *endHeader !=
'>') endHeader++;
3147 ReplaceText(LocStart, endHeader-startBuf, Result);
3150 ReplaceText(LocStart, cursor-startBuf, Result);
3152 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
3153 Result =
"\n struct ";
3157 Result +=
"_IVARS;\n";
3160 SourceLocation OnePastCurly =
3161 LocStart.getLocWithOffset(cursor-startBuf+1);
3162 InsertText(OnePastCurly, Result);
3167 while (cursor < endBuf) {
3168 if (*cursor ==
'@') {
3169 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3171 for (++cursor; cursor[0] ==
' ' || cursor[0] ==
'\t'; ++cursor)
3176 if (!strncmp(cursor,
"public", strlen(
"public")) ||
3177 !strncmp(cursor,
"private", strlen(
"private")) ||
3178 !strncmp(cursor,
"package", strlen(
"package")) ||
3179 !strncmp(cursor,
"protected", strlen(
"protected")))
3180 InsertText(atLoc,
"// ");
3185 else if (*cursor ==
'<') {
3186 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3187 InsertText(atLoc,
"/* ");
3188 cursor = strchr(cursor,
'>');
3190 atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3191 InsertText(atLoc,
" */");
3192 }
else if (*cursor ==
'^') {
3193 SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf);
3194 ReplaceText(caretLoc, 1,
"*");
3199 InsertText(LocEnd.getLocWithOffset(1),
";");
3202 Result +=
" {\n struct ";
3206 Result +=
"_IVARS;\n};\n";
3207 ReplaceText(LocStart, endBuf-startBuf, Result);
3210 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3211 llvm_unreachable(
"struct already synthesize- SynthesizeObjCInternalStruct");
3221void RewriteObjC::RewriteImplementations() {
3222 int ClsDefCount = ClassImplementation.size();
3223 int CatDefCount = CategoryImplementation.size();
3226 for (
int i = 0; i < ClsDefCount; i++)
3227 RewriteImplementationDecl(ClassImplementation[i]);
3229 for (
int i = 0; i < CatDefCount; i++)
3230 RewriteImplementationDecl(CategoryImplementation[i]);
3233void RewriteObjC::RewriteByRefString(std::string &ResultStr,
3234 const std::string &Name,
3236 assert(BlockByRefDeclNo.count(VD) &&
3237 "RewriteByRefString: ByRef decl missing");
3239 ResultStr +=
"struct ";
3240 ResultStr +=
"__Block_byref_" + Name +
3241 "_" + utostr(BlockByRefDeclNo[VD]) ;
3244static bool HasLocalVariableExternalStorage(
ValueDecl *VD) {
3245 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3246 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3250std::string RewriteObjC::SynthesizeBlockFunc(
BlockExpr *CE,
int i,
3255 std::string StructRef =
"struct " + Tag;
3256 std::string S =
"static " + RT.
getAsString(Context->getPrintingPolicy()) +
" __" +
3257 funcName.str() +
"_" +
"block_func_" + utostr(i);
3264 S +=
"(" + StructRef +
" *__cself)";
3266 S +=
"(" + StructRef +
" *__cself)";
3269 assert(FT &&
"SynthesizeBlockFunc: No function proto");
3272 S += StructRef +
" *__cself, ";
3273 std::string ParamStr;
3277 ParamStr = (*AI)->getNameAsString();
3279 (void)convertBlockPointerToFunctionPointer(QT);
3293 for (
auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;
3296 std::string Name = (*I)->getNameAsString();
3297 std::string TypeString;
3298 RewriteByRefString(TypeString, Name, (*I));
3300 Name = TypeString + Name;
3301 S += Name +
" = __cself->" + (*I)->getNameAsString() +
"; // bound by ref\n";
3304 for (
auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;
3317 if (isTopLevelBlockPointerType((*I)->getType())) {
3318 RewriteBlockPointerTypeVariable(S, (*I));
3320 RewriteBlockPointerType(S, (*I)->getType());
3322 S +=
"__cself->" + (*I)->getNameAsString() +
"; // bound by copy\n";
3325 std::string Name = (*I)->getNameAsString();
3327 if (HasLocalVariableExternalStorage(*I))
3328 QT = Context->getPointerType(QT);
3330 S += Name +
" = __cself->" +
3331 (*I)->getNameAsString() +
"; // bound by copy\n";
3334 std::string RewrittenStr = RewrittenBlockExprs[CE];
3335 const char *cstr = RewrittenStr.c_str();
3336 while (*cstr++ !=
'{') ;
3342std::string RewriteObjC::SynthesizeBlockHelperFuncs(
BlockExpr *CE,
int i,
3345 std::string StructRef =
"struct " + Tag;
3346 std::string S =
"static void __";
3349 S +=
"_block_copy_" + utostr(i);
3350 S +=
"(" + StructRef;
3351 S +=
"*dst, " + StructRef;
3353 for (
ValueDecl *VD : ImportedBlockDecls) {
3354 S +=
"_Block_object_assign((void*)&dst->";
3356 S +=
", (void*)src->";
3358 if (BlockByRefDecls.contains(VD))
3359 S +=
", " + utostr(BLOCK_FIELD_IS_BYREF) +
"/*BLOCK_FIELD_IS_BYREF*/);";
3361 S +=
", " + utostr(BLOCK_FIELD_IS_BLOCK) +
"/*BLOCK_FIELD_IS_BLOCK*/);";
3363 S +=
", " + utostr(BLOCK_FIELD_IS_OBJECT) +
"/*BLOCK_FIELD_IS_OBJECT*/);";
3367 S +=
"\nstatic void __";
3369 S +=
"_block_dispose_" + utostr(i);
3370 S +=
"(" + StructRef;
3372 for (
ValueDecl *VD : ImportedBlockDecls) {
3373 S +=
"_Block_object_dispose((void*)src->";
3375 if (BlockByRefDecls.contains(VD))
3376 S +=
", " + utostr(BLOCK_FIELD_IS_BYREF) +
"/*BLOCK_FIELD_IS_BYREF*/);";
3378 S +=
", " + utostr(BLOCK_FIELD_IS_BLOCK) +
"/*BLOCK_FIELD_IS_BLOCK*/);";
3380 S +=
", " + utostr(BLOCK_FIELD_IS_OBJECT) +
"/*BLOCK_FIELD_IS_OBJECT*/);";
3386std::string RewriteObjC::SynthesizeBlockImpl(
BlockExpr *CE, std::string Tag,
3388 std::string S =
"\nstruct " + Tag;
3391 S +=
" {\n struct __block_impl impl;\n";
3392 S +=
" struct " + Desc;
3399 if (BlockDeclRefs.size()) {
3401 for (
auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;
3404 std::string FieldName = (*I)->getNameAsString();
3405 std::string ArgName =
"_" + FieldName;
3416 if (isTopLevelBlockPointerType((*I)->getType())) {
3417 S +=
"struct __block_impl *";
3421 if (HasLocalVariableExternalStorage(*I))
3422 QT = Context->getPointerType(QT);
3427 S += FieldName +
";\n";
3430 for (
auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;
3433 std::string FieldName = (*I)->getNameAsString();
3434 std::string ArgName =
"_" + FieldName;
3436 std::string TypeString;
3437 RewriteByRefString(TypeString, FieldName, (*I));
3439 FieldName = TypeString + FieldName;
3440 ArgName = TypeString + ArgName;
3443 S += FieldName +
"; // by ref\n";
3448 bool firsTime =
true;
3449 for (
auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;
3451 std::string Name = (*I)->getNameAsString();
3458 if (isTopLevelBlockPointerType((*I)->getType()))
3459 Constructor += Name +
"((struct __block_impl *)_" + Name +
")";
3464 for (
auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;
3466 std::string Name = (*I)->getNameAsString();
3473 Constructor += Name +
"(_" + Name +
"->__forwarding)";
3478 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3480 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3481 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3488 Constructor +=
" impl.isa = &_NSConcreteGlobalBlock;\n";
3490 Constructor +=
" impl.isa = &_NSConcreteStackBlock;\n";
3491 Constructor +=
" impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3501std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
3502 std::string ImplTag,
int i,
3505 std::string S =
"\nstatic struct " + DescTag;
3507 S +=
" {\n unsigned long reserved;\n";
3508 S +=
" unsigned long Block_size;\n";
3510 S +=
" void (*copy)(struct ";
3511 S += ImplTag; S +=
"*, struct ";
3512 S += ImplTag; S +=
"*);\n";
3514 S +=
" void (*dispose)(struct ";
3515 S += ImplTag; S +=
"*);\n";
3519 S += DescTag +
"_DATA = { 0, sizeof(struct ";
3522 S +=
", __" + FunName.str() +
"_block_copy_" + utostr(i);
3523 S +=
", __" + FunName.str() +
"_block_dispose_" + utostr(i);
3529void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
3530 StringRef FunName) {
3532 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3533 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3534 bool RewriteSC = (GlobalVarDecl &&
3539 std::string SC(
" void __");
3542 InsertText(FunLocStart, SC);
3546 for (
unsigned i = 0, count=0; i < Blocks.size(); i++) {
3547 CollectBlockDeclRefInfo(Blocks[i]);
3550 for (
int j = 0; j < InnerDeclRefsCount[i]; j++) {
3553 BlockDeclRefs.push_back(Exp);
3554 if (VD->
hasAttr<BlocksAttr>())
3555 BlockByRefDecls.insert(VD);
3557 BlockByCopyDecls.insert(VD);
3560 if (VD->
hasAttr<BlocksAttr>() ||
3563 ImportedBlockDecls.insert(VD);
3566 std::string ImplTag =
"__" + FunName.str() +
"_block_impl_" + utostr(i);
3567 std::string DescTag =
"__" + FunName.str() +
"_block_desc_" + utostr(i);
3569 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3571 InsertText(FunLocStart, CI);
3573 std::string
CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3575 InsertText(FunLocStart, CF);
3577 if (ImportedBlockDecls.size()) {
3578 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3579 InsertText(FunLocStart, HF);
3581 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3582 ImportedBlockDecls.size() > 0);
3583 InsertText(FunLocStart, BD);
3585 BlockDeclRefs.clear();
3586 BlockByRefDecls.clear();
3587 BlockByCopyDecls.clear();
3588 ImportedBlockDecls.clear();
3602 InsertText(FunLocStart, SC);
3606 InnerDeclRefsCount.clear();
3607 InnerDeclRefs.clear();
3608 RewrittenBlockExprs.clear();
3611void RewriteObjC::InsertBlockLiteralsWithinFunction(
FunctionDecl *FD) {
3613 StringRef FuncName = FD->
getName();
3615 SynthesizeBlockLiterals(FunLocStart, FuncName);
3618static void BuildUniqueMethodName(std::string &Name,
3621 Name = std::string(IFace->
getName());
3624 std::string::size_type loc = 0;
3625 while ((loc = Name.find(
':', loc)) != std::string::npos)
3626 Name.replace(loc, 1,
"_");
3629void RewriteObjC::InsertBlockLiteralsWithinMethod(
ObjCMethodDecl *MD) {
3633 std::string FuncName;
3634 BuildUniqueMethodName(FuncName, MD);
3635 SynthesizeBlockLiterals(FunLocStart, FuncName);
3638void RewriteObjC::GetBlockDeclRefExprs(
Stmt *S) {
3641 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
3642 GetBlockDeclRefExprs(CBE->getBody());
3644 GetBlockDeclRefExprs(SubStmt);
3649 HasLocalVariableExternalStorage(DRE->
getDecl()))
3651 BlockDeclRefs.push_back(DRE);
3654void RewriteObjC::GetInnerBlockDeclRefExprs(
Stmt *S,
3656 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
3659 if (
BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
3661 GetInnerBlockDeclRefExprs(CBE->getBody(),
3666 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
3669 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3671 HasLocalVariableExternalStorage(DRE->
getDecl())) {
3673 InnerBlockDeclRefs.push_back(DRE);
3675 if (Var->isFunctionOrMethodVarDecl())
3676 ImportedLocalExternalDecls.insert(Var);
3691 bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
3697 if (convertBlockPointerToFunctionPointer(t))
3698 HasBlockType =
true;
3699 ArgTypes.push_back(t);
3706 FuncType = getSimpleFunctionType(Res, ArgTypes);
3711Stmt *RewriteObjC::SynthesizeBlockCall(
CallExpr *Exp,
const Expr *BlockExp) {
3715 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3717 }
else if (
const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3720 else if (
const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3721 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3723 else if (
const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3726 dyn_cast<ConditionalOperator>(BlockExp)) {
3727 Expr *LHSExp = CEXPR->getLHS();
3728 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3729 Expr *RHSExp = CEXPR->getRHS();
3730 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3731 Expr *CONDExp = CEXPR->getCond();
3733 CONDExp, SourceLocation(),
cast<Expr>(LHSStmt), SourceLocation(),
3736 }
else if (
const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3739 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
3742 assert(
false &&
"RewriteBlockClass: Bad type");
3744 assert(CPT &&
"RewriteBlockClass: Bad type");
3746 assert(FT &&
"RewriteBlockClass: Bad type");
3751 SourceLocation(), SourceLocation(),
3752 &Context->Idents.get(
"__block_impl"));
3753 QualType PtrBlock = Context->getPointerType(Context->getCanonicalTagType(RD));
3759 ArgTypes.push_back(PtrBlock);
3764 if (!convertBlockPointerToFunctionPointer(t))
3765 convertToUnqualifiedObjCType(t);
3766 ArgTypes.push_back(t);
3770 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->
getType(), ArgTypes);
3772 PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
3774 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
3776 const_cast<Expr*
>(BlockExp));
3784 &Context->Idents.get(
"FuncPtr"),
3785 Context->VoidPtrTy,
nullptr,
3791 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
3793 PE =
new (Context)
ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
3797 BlkExprs.push_back(BlkCast);
3800 E = Exp->
arg_end(); I != E; ++I) {
3801 BlkExprs.push_back(*I);
3827 HasLocalVariableExternalStorage(DeclRefExp->
getDecl());
3831 &Context->Idents.get(
"__forwarding"),
3832 Context->VoidPtrTy,
nullptr,
3839 StringRef Name = VD->
getName();
3841 &Context->Idents.get(Name),
3842 Context->VoidPtrTy,
nullptr,
3852 ReplaceStmt(DeclRefExp, PE);
3859Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(
DeclRefExpr *DRE) {
3861 if (
VarDecl *Var = dyn_cast<VarDecl>(VD))
3862 if (!ImportedLocalExternalDecls.count(Var))
3870 ReplaceStmt(DRE, PE);
3879 if (LocStart.isInvalid())
3885 const char *startBuf =
SM->getCharacterData(LocStart);
3886 const char *endBuf =
SM->getCharacterData(LocEnd);
3888 const Type* TypePtr = QT->
getAs<Type>();
3892 std::string TypeAsString =
"(";
3893 RewriteBlockPointerType(TypeAsString, QT);
3894 TypeAsString +=
")";
3895 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
3899 const char *argPtr = startBuf;
3901 while (*argPtr++ && (argPtr < endBuf)) {
3905 LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
3906 ReplaceText(LocStart, 1,
"*");
3912void RewriteObjC::RewriteBlockPointerFunctionArgs(
FunctionDecl *FD) {
3914 unsigned parenCount = 0;
3917 const char *startBuf =
SM->getCharacterData(DeclLoc);
3918 const char *startArgList = strchr(startBuf,
'(');
3920 assert((*startArgList ==
'(') &&
"Rewriter fuzzy parser confused");
3924 DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
3925 assert((DeclLoc.isValid()) &&
"Invalid DeclLoc");
3927 const char *argPtr = startArgList;
3929 while (*argPtr++ && parenCount) {
3933 DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
3934 ReplaceText(DeclLoc, 1,
"*");
3946bool RewriteObjC::PointerTypeTakesAnyBlockArguments(
QualType QT) {
3948 const PointerType *PT = QT->
getAs<PointerType>();
3953 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3958 if (isTopLevelBlockPointerType(I))
3964bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(
QualType QT) {
3966 const PointerType *PT = QT->
getAs<PointerType>();
3971 assert(BPT &&
"BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3976 if (I->isObjCQualifiedIdType())
3978 if (I->isObjCObjectPointerType() &&
3979 I->getPointeeType()->isObjCQualifiedInterfaceType())
3987void RewriteObjC::GetExtentOfArgList(
const char *Name,
const char *&LParen,
3988 const char *&RParen) {
3989 const char *argPtr = strchr(Name,
'(');
3990 assert((*argPtr ==
'(') &&
"Rewriter fuzzy parser confused");
3994 unsigned parenCount = 1;
3996 while (*argPtr && parenCount) {
3998 case '(': parenCount++;
break;
3999 case ')': parenCount--;
break;
4002 if (parenCount) argPtr++;
4004 assert((*argPtr ==
')') &&
"Rewriter fuzzy parser confused");
4008void RewriteObjC::RewriteBlockPointerDecl(
NamedDecl *ND) {
4010 RewriteBlockPointerFunctionArgs(FD);
4016 if (
VarDecl *VD = dyn_cast<VarDecl>(ND))
4019 DeclT = TDD->getUnderlyingType();
4020 else if (
FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4023 llvm_unreachable(
"RewriteBlockPointerDecl(): Decl type not yet handled");
4025 const char *startBuf =
SM->getCharacterData(DeclLoc);
4026 const char *endBuf = startBuf;
4028 while (*startBuf !=
'^' && *startBuf !=
';' && startBuf != MainFileStart)
4030 SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
4032 unsigned OrigLength=0;
4035 if (*startBuf ==
'^') {
4041 while (*startBuf !=
')') {
4049 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4050 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4054 startBuf =
SM->getCharacterData(DeclLoc);
4055 const char *argListBegin, *argListEnd;
4056 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4057 while (argListBegin < argListEnd) {
4058 if (*argListBegin ==
'^')
4060 else if (*argListBegin ==
'<') {
4062 buf += *argListBegin++;
4064 while (*argListBegin !=
'>') {
4065 buf += *argListBegin++;
4068 buf += *argListBegin;
4072 buf += *argListBegin;
4079 ReplaceText(Start, OrigLength, buf);
4102std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(
VarDecl *VD,
4105 if (!CopyDestroyCache.insert(flag).second)
4107 S =
"static void __Block_byref_id_object_copy_";
4109 S +=
"(void *dst, void *src) {\n";
4114 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4115 unsigned VoidPtrSize =
4116 static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
4118 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
4119 S +=
" _Block_object_assign((char*)dst + ";
4120 S += utostr(offset);
4121 S +=
", *(void * *) ((char*)src + ";
4122 S += utostr(offset);
4127 S +=
"static void __Block_byref_id_object_dispose_";
4129 S +=
"(void *src) {\n";
4130 S +=
" _Block_object_dispose(*(void * *) ((char*)src + ";
4131 S += utostr(offset);
4156void RewriteObjC::RewriteByRefVar(
VarDecl *ND) {
4159 if (CurFunctionDeclToDeclareForBlock)
4160 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4164 if (DeclLoc.isInvalid())
4168 const char *startBuf =
SM->getCharacterData(DeclLoc);
4170 X =
SM->getExpansionLoc(
X);
4171 const char *endBuf =
SM->getCharacterData(
X);
4173 std::string ByrefType;
4174 RewriteByRefString(ByrefType, Name, ND,
true);
4175 ByrefType +=
" {\n";
4176 ByrefType +=
" void *__isa;\n";
4177 RewriteByRefString(ByrefType, Name, ND);
4178 ByrefType +=
" *__forwarding;\n";
4179 ByrefType +=
" int __flags;\n";
4180 ByrefType +=
" int __size;\n";
4184 bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
4185 if (HasCopyAndDispose) {
4186 ByrefType +=
" void (*__Block_byref_id_object_copy)(void*, void*);\n";
4187 ByrefType +=
" void (*__Block_byref_id_object_dispose)(void*);\n";
4191 (void)convertBlockPointerToFunctionPointer(T);
4194 ByrefType +=
" " + Name +
";\n";
4195 ByrefType +=
"};\n";
4197 SourceLocation FunLocStart;
4201 assert(CurMethodDef &&
"RewriteByRefVar - CurMethodDef is null");
4204 InsertText(FunLocStart, ByrefType);
4210 if (HasCopyAndDispose) {
4218 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4220 InsertText(FunLocStart, HF);
4226 bool hasInit = (ND->
getInit() !=
nullptr);
4228 if (HasCopyAndDispose)
4232 RewriteByRefString(ByrefType, Name, ND);
4233 std::string ForwardingCastType(
"(");
4234 ForwardingCastType += ByrefType +
" *)";
4236 ByrefType +=
" " + Name +
" = {(void*)";
4237 ByrefType += utostr(
isa);
4238 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4239 ByrefType += utostr(flags);
4241 ByrefType +=
"sizeof(";
4242 RewriteByRefString(ByrefType, Name, ND);
4244 if (HasCopyAndDispose) {
4245 ByrefType +=
", __Block_byref_id_object_copy_";
4246 ByrefType += utostr(flag);
4247 ByrefType +=
", __Block_byref_id_object_dispose_";
4248 ByrefType += utostr(flag);
4250 ByrefType +=
"};\n";
4251 unsigned nameSize = Name.size();
4256 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4259 SourceLocation startLoc;
4262 startLoc = ECE->getLParenLoc();
4265 startLoc =
SM->getExpansionLoc(startLoc);
4266 endBuf =
SM->getCharacterData(startLoc);
4267 ByrefType +=
" " + Name;
4268 ByrefType +=
" = {(void*)";
4269 ByrefType += utostr(
isa);
4270 ByrefType +=
"," + ForwardingCastType +
"&" + Name +
", ";
4271 ByrefType += utostr(flags);
4273 ByrefType +=
"sizeof(";
4274 RewriteByRefString(ByrefType, Name, ND);
4276 if (HasCopyAndDispose) {
4277 ByrefType +=
"__Block_byref_id_object_copy_";
4278 ByrefType += utostr(flag);
4279 ByrefType +=
", __Block_byref_id_object_dispose_";
4280 ByrefType += utostr(flag);
4283 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4293 const char *startInitializerBuf =
SM->getCharacterData(startLoc);
4294 const char *semiBuf = strchr(startInitializerBuf,
';');
4295 assert((*semiBuf ==
';') &&
"RewriteByRefVar: can't find ';'");
4296 SourceLocation semiLoc =
4297 startLoc.getLocWithOffset(semiBuf-startInitializerBuf);
4299 InsertText(semiLoc,
"}");
4303void RewriteObjC::CollectBlockDeclRefInfo(
BlockExpr *Exp) {
4305 GetBlockDeclRefExprs(Exp->
getBody());
4306 if (BlockDeclRefs.size()) {
4308 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4310 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
4312 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4314 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
4316 for (
unsigned i = 0; i < BlockDeclRefs.size(); i++)
4318 BlockDeclRefs[i]->
getType()->isObjCObjectPointerType() ||
4319 BlockDeclRefs[i]->
getType()->isBlockPointerType())
4320 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4324FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
4326 QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
4328 SourceLocation(), ID, FType,
nullptr,
SC_Extern,
4335 Blocks.push_back(Exp);
4337 CollectBlockDeclRefInfo(Exp);
4340 int countOfInnerDecls = 0;
4341 if (!InnerBlockDeclRefs.empty()) {
4342 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
4345 if (!VD->
hasAttr<BlocksAttr>() && BlockByCopyDecls.insert(VD)) {
4349 InnerDeclRefs.push_back(Exp);
4350 countOfInnerDecls++;
4351 BlockDeclRefs.push_back(Exp);
4353 if (VD->
hasAttr<BlocksAttr>() && BlockByRefDecls.insert(VD)) {
4354 InnerDeclRefs.push_back(Exp);
4355 countOfInnerDecls++;
4356 BlockDeclRefs.push_back(Exp);
4360 for (
unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
4362 InnerBlockDeclRefs[i]->
getType()->isObjCObjectPointerType() ||
4363 InnerBlockDeclRefs[i]->
getType()->isBlockPointerType())
4364 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4366 InnerDeclRefsCount.push_back(countOfInnerDecls);
4368 std::string FuncName;
4372 else if (CurMethodDef)
4373 BuildUniqueMethodName(FuncName, CurMethodDef);
4374 else if (GlobalVarDecl)
4377 std::string BlockNumber = utostr(Blocks.size()-1);
4379 std::string Tag =
"__" + FuncName +
"_block_impl_" + BlockNumber;
4380 std::string
Func =
"__" + FuncName +
"_block_func_" + BlockNumber;
4383 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
4384 QualType FType = Context->getPointerType(BFT);
4390 FD = SynthBlockInitFunctionDecl(Tag);
4397 FD = SynthBlockInitFunctionDecl(
Func);
4401 NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg);
4405 std::string DescData =
"__" + FuncName +
"_block_desc_" + BlockNumber +
"_DATA";
4408 *Context, TUDecl, SourceLocation(), SourceLocation(),
4409 &Context->Idents.get(DescData), Context->VoidPtrTy,
nullptr,
SC_Static);
4412 new (Context)
DeclRefExpr(*Context, NewVD,
false, Context->VoidPtrTy,
4414 UO_AddrOf, Context->getPointerType(Context->VoidPtrTy),
VK_PRValue,
4416 InitExprs.push_back(DescRefExpr);
4419 if (BlockDeclRefs.size()) {
4422 for (
auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;
4424 if (isObjCType((*I)->getType())) {
4426 FD = SynthBlockInitFunctionDecl((*I)->getName());
4429 if (HasLocalVariableExternalStorage(*I)) {
4431 QT = Context->getPointerType(QT);
4434 SourceLocation(),
false,
4437 }
else if (isTopLevelBlockPointerType((*I)->getType())) {
4438 FD = SynthBlockInitFunctionDecl((*I)->getName());
4441 Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast,
4444 FD = SynthBlockInitFunctionDecl((*I)->getName());
4447 if (HasLocalVariableExternalStorage(*I)) {
4449 QT = Context->getPointerType(QT);
4452 SourceLocation(),
false,
4456 InitExprs.push_back(Exp);
4459 for (
auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;
4463 std::string RecName;
4464 RewriteByRefString(RecName, Name, ND,
true);
4466 +
sizeof(
"struct"));
4469 SourceLocation(), SourceLocation(), II);
4470 assert(RD &&
"SynthBlockInitExpr(): Can't find RecordDecl");
4472 Context->getPointerType(Context->getCanonicalTagType(RD));
4474 FD = SynthBlockInitFunctionDecl((*I)->getName());
4477 bool isNestedCapturedVar =
false;
4479 for (
const auto &CI : block->
captures()) {
4480 const VarDecl *variable = CI.getVariable();
4481 if (variable == ND && CI.isNested()) {
4482 assert (CI.isByRef() &&
4483 "SynthBlockInitExpr - captured block variable is not byref");
4484 isNestedCapturedVar =
true;
4490 if (!isNestedCapturedVar)
4492 const_cast<ASTContext &
>(*Context), Exp, UO_AddrOf,
4495 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
4496 InitExprs.push_back(Exp);
4499 if (ImportedBlockDecls.size()) {
4503 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4505 Context->IntTy, SourceLocation());
4506 InitExprs.push_back(FlagExp);
4511 const_cast<ASTContext &
>(*Context), NewRep, UO_AddrOf,
4514 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
4516 BlockDeclRefs.clear();
4517 BlockByRefDecls.clear();
4518 BlockByCopyDecls.clear();
4519 ImportedBlockDecls.clear();
4523bool RewriteObjC::IsDeclStmtInForeachHeader(
DeclStmt *DS) {
4525 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4526 return CS->getElement() == DS;
4534Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(
Stmt *S) {
4540 ObjCBcLabelNo.push_back(++BcLabelCount);
4547 return RewritePropertyOrImplicitSetter(PseudoOp);
4549 return RewritePropertyOrImplicitGetter(PseudoOp);
4551 }
else if (
ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4552 return RewriteObjCIvarRefExpr(IvarRefExpr);
4560 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4562 childStmt = newStmt;
4566 if (
BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
4569 InnerContexts.insert(BE->getBlockDecl());
4570 ImportedLocalExternalDecls.clear();
4571 GetInnerBlockDeclRefExprs(BE->getBody(),
4572 InnerBlockDeclRefs, InnerContexts);
4574 Stmt *SaveCurrentBody = CurrentBody;
4575 CurrentBody = BE->getBody();
4576 PropParentMap =
nullptr;
4582 bool saveDisableReplaceStmt = DisableReplaceStmt;
4583 DisableReplaceStmt =
false;
4584 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4585 DisableReplaceStmt = saveDisableReplaceStmt;
4586 CurrentBody = SaveCurrentBody;
4587 PropParentMap =
nullptr;
4588 ImportedLocalExternalDecls.clear();
4590 std::string Str =
Rewrite.getRewrittenText(BE->getSourceRange());
4591 RewrittenBlockExprs[BE] = Str;
4593 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4596 ReplaceStmt(S, blockTranscribed);
4597 return blockTranscribed;
4601 return RewriteAtEncode(AtEncode);
4604 return RewriteAtSelector(AtSelector);
4607 return RewriteObjCStringLiteral(AtString);
4612 SourceLocation startLoc = MessExpr->getBeginLoc();
4613 SourceLocation endLoc = MessExpr->getEndLoc();
4615 const char *startBuf =
SM->getCharacterData(startLoc);
4616 const char *endBuf =
SM->getCharacterData(endLoc);
4618 std::string messString;
4619 messString +=
"// ";
4620 messString.append(startBuf, endBuf-startBuf+1);
4629 return RewriteMessageExpr(MessExpr);
4633 return RewriteObjCTryStmt(StmtTry);
4636 return RewriteObjCSynchronizedStmt(StmtTry);
4639 return RewriteObjCThrowStmt(StmtThrow);
4642 return RewriteObjCProtocolExpr(ProtocolExp);
4645 dyn_cast<ObjCForCollectionStmt>(S))
4646 return RewriteObjCForCollectionStmt(StmtForCollection,
4647 OrigStmtRange.getEnd());
4649 dyn_cast<BreakStmt>(S))
4650 return RewriteBreakStmt(StmtBreakStmt);
4652 dyn_cast<ContinueStmt>(S))
4653 return RewriteContinueStmt(StmtContinueStmt);
4657 if (
DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4667 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4668 RewriteObjCQualifiedInterfaceTypes(*DS->
decl_begin());
4671 for (
auto *SD : DS->
decls()) {
4672 if (
ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4673 if (isTopLevelBlockPointerType(ND->
getType()))
4674 RewriteBlockPointerDecl(ND);
4676 CheckFunctionPointerDecl(ND->
getType(), ND);
4677 if (
VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4678 if (VD->
hasAttr<BlocksAttr>()) {
4679 static unsigned uniqueByrefDeclCount = 0;
4680 assert(!BlockByRefDeclNo.count(ND) &&
4681 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4682 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4683 RewriteByRefVar(VD);
4686 RewriteTypeOfDecl(VD);
4690 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4691 RewriteBlockPointerDecl(TD);
4692 else if (TD->getUnderlyingType()->isFunctionPointerType())
4693 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4699 RewriteObjCQualifiedInterfaceTypes(CE);
4703 assert(!Stmts.empty() &&
"Statement stack is empty");
4706 &&
"Statement stack mismatch");
4710 if (
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4712 if (VD->
hasAttr<BlocksAttr>())
4713 return RewriteBlockDeclRefExpr(DRE);
4714 if (HasLocalVariableExternalStorage(VD))
4715 return RewriteLocalVariableExternalStorage(DRE);
4718 if (
CallExpr *CE = dyn_cast<CallExpr>(S)) {
4720 Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
4721 ReplaceStmt(S, BlockCall);
4726 RewriteCastExpr(CE);
4735 llvm::raw_string_ostream Buf(SStr);
4736 Replacement->printPretty(Buf);
4737 const std::string &Str = Buf.str();
4739 printf(
"CAST = %s\n", &Str[0]);
4749void RewriteObjC::RewriteRecordBody(
RecordDecl *RD) {
4750 for (
auto *FD : RD->
fields()) {
4751 if (isTopLevelBlockPointerType(FD->
getType()))
4752 RewriteBlockPointerDecl(FD);
4755 RewriteObjCQualifiedInterfaceTypes(FD);
4761void RewriteObjC::HandleDeclInMainFile(
Decl *D) {
4763 case Decl::Function: {
4771 RewriteBlocksInFunctionProtoType(FD->
getType(), FD);
4778 CurFunctionDef = FD;
4779 CurFunctionDeclToDeclareForBlock = FD;
4782 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4784 CurrentBody =
nullptr;
4785 if (PropParentMap) {
4786 delete PropParentMap;
4787 PropParentMap =
nullptr;
4791 InsertBlockLiteralsWithinFunction(FD);
4792 CurFunctionDef =
nullptr;
4793 CurFunctionDeclToDeclareForBlock =
nullptr;
4797 case Decl::ObjCMethod: {
4803 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4805 CurrentBody =
nullptr;
4806 if (PropParentMap) {
4807 delete PropParentMap;
4808 PropParentMap =
nullptr;
4810 InsertBlockLiteralsWithinMethod(MD);
4811 CurMethodDef =
nullptr;
4815 case Decl::ObjCImplementation: {
4817 ClassImplementation.push_back(CI);
4820 case Decl::ObjCCategoryImpl: {
4822 CategoryImplementation.push_back(CI);
4827 RewriteObjCQualifiedInterfaceTypes(VD);
4828 if (isTopLevelBlockPointerType(VD->
getType()))
4829 RewriteBlockPointerDecl(VD);
4831 CheckFunctionPointerDecl(VD->
getType(), VD);
4834 RewriteCastExpr(CE);
4840 RewriteRecordBody(RD);
4845 RewriteFunctionBodyOrGlobalInitializer(VD->
getInit());
4846 CurrentBody =
nullptr;
4847 if (PropParentMap) {
4848 delete PropParentMap;
4849 PropParentMap =
nullptr;
4852 GlobalVarDecl =
nullptr;
4856 RewriteCastExpr(CE);
4861 case Decl::TypeAlias:
4862 case Decl::Typedef: {
4864 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4865 RewriteBlockPointerDecl(TD);
4866 else if (TD->getUnderlyingType()->isFunctionPointerType())
4867 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4871 case Decl::CXXRecord:
4872 case Decl::Record: {
4875 RewriteRecordBody(RD);
4884void RewriteObjC::HandleTranslationUnit(
ASTContext &
C) {
4893 RewriteObjCProtocolMetaData(ProtDecl,
"",
"",
Preamble);
4895 InsertText(
SM->getLocForStartOfFile(MainFileID),
Preamble,
false);
4896 if (ClassImplementation.size() || CategoryImplementation.size())
4897 RewriteImplementations();
4901 if (
const RewriteBuffer *RewriteBuf =
4902 Rewrite.getRewriteBufferFor(MainFileID)) {
4904 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
4906 llvm::errs() <<
"No changes\n";
4909 if (ClassImplementation.size() || CategoryImplementation.size() ||
4910 ProtocolExprDecls.size()) {
4912 std::string ResultStr;
4913 RewriteMetaDataIntoBuffer(ResultStr);
4915 *OutFile << ResultStr;
4920void RewriteObjCFragileABI::Initialize(
ASTContext &context) {
4921 InitializeCommon(context);
4927 Preamble +=
"struct objc_selector; struct objc_class;\n";
4928 Preamble +=
"struct __rw_objc_super { struct objc_object *object; ";
4929 Preamble +=
"struct objc_object *superClass; ";
4930 if (LangOpts.MicrosoftExt) {
4932 Preamble +=
"__rw_objc_super(struct objc_object *o, struct objc_object *s) "
4934 Preamble +=
"object(o), superClass(s) {} ";
4937 Preamble +=
"#ifndef _REWRITER_typedef_Protocol\n";
4938 Preamble +=
"typedef struct objc_object Protocol;\n";
4939 Preamble +=
"#define _REWRITER_typedef_Protocol\n";
4941 if (LangOpts.MicrosoftExt) {
4942 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
4943 Preamble +=
"#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
4945 Preamble +=
"#define __OBJC_RW_DLLIMPORT extern\n";
4946 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
4947 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4948 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
4949 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4950 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
4951 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4952 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
4953 Preamble +=
"(struct objc_super *, struct objc_selector *, ...);\n";
4954 Preamble +=
"__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
4955 Preamble +=
"(struct objc_object *, struct objc_selector *, ...);\n";
4956 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
4958 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
4959 Preamble +=
"(struct objc_class *);\n";
4960 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
4962 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
4963 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
4964 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
4965 Preamble +=
"__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
4966 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_exception_match";
4967 Preamble +=
"(struct objc_class *, struct objc_object *);\n";
4969 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
4970 Preamble +=
"__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
4971 Preamble +=
"__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
4972 Preamble +=
"#ifndef __FASTENUMERATIONSTATE\n";
4973 Preamble +=
"struct __objcFastEnumerationState {\n\t";
4974 Preamble +=
"unsigned long state;\n\t";
4975 Preamble +=
"void **itemsPtr;\n\t";
4976 Preamble +=
"unsigned long *mutationsPtr;\n\t";
4977 Preamble +=
"unsigned long extra[5];\n};\n";
4978 Preamble +=
"__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
4979 Preamble +=
"#define __FASTENUMERATIONSTATE\n";
4981 Preamble +=
"#ifndef __NSCONSTANTSTRINGIMPL\n";
4982 Preamble +=
"struct __NSConstantStringImpl {\n";
4988 Preamble +=
"#ifdef CF_EXPORT_CONSTANT_STRING\n";
4989 Preamble +=
"extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
4991 Preamble +=
"__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
4993 Preamble +=
"#define __NSCONSTANTSTRINGIMPL\n";
4996 Preamble +=
"#ifndef BLOCK_IMPL\n";
4997 Preamble +=
"#define BLOCK_IMPL\n";
4998 Preamble +=
"struct __block_impl {\n";
5004 Preamble +=
"// Runtime copy/destroy helper functions (from Block_private.h)\n";
5005 Preamble +=
"#ifdef __OBJC_EXPORT_BLOCKS\n";
5006 Preamble +=
"extern \"C\" __declspec(dllexport) "
5007 "void _Block_object_assign(void *, const void *, const int);\n";
5008 Preamble +=
"extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5009 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5010 Preamble +=
"extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5012 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5013 Preamble +=
"__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5014 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5015 Preamble +=
"__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5018 if (LangOpts.MicrosoftExt) {
5019 Preamble +=
"#undef __OBJC_RW_DLLIMPORT\n";
5020 Preamble +=
"#undef __OBJC_RW_STATICIMPORT\n";
5021 Preamble +=
"#ifndef KEEP_ATTRIBUTES\n";
5022 Preamble +=
"#define __attribute__(X)\n";
5032 Preamble +=
"\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5037void RewriteObjCFragileABI::RewriteIvarOffsetComputation(
ObjCIvarDecl *ivar,
5038 std::string &Result) {
5044 Result +=
"__OFFSETOFIVAR__(struct ";
5046 if (LangOpts.MicrosoftExt)
5055void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
5057 StringRef ClassName, std::string &Result) {
5058 static bool objc_protocol_methods =
false;
5067 Result +=
"\nstruct _protocol_methods {\n";
5068 Result +=
"\tstruct objc_selector *_cmd;\n";
5069 Result +=
"\tchar *method_types;\n";
5072 objc_protocol_methods =
true;
5089 Result +=
"\nstatic struct {\n";
5090 Result +=
"\tint protocol_method_count;\n";
5091 Result +=
"\tstruct _protocol_methods protocol_methods[";
5092 Result += utostr(NumMethods);
5093 Result +=
"];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
5095 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
5096 "{\n\t" + utostr(NumMethods) +
"\n";
5103 Result +=
"\t ,{{(struct objc_selector *)\"";
5105 Result +=
"\t ,{(struct objc_selector *)\"";
5106 Result += (*I)->getSelector().getAsString();
5107 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
5109 Result += MethodTypeString;
5112 Result +=
"\t }\n};\n";
5118 if (NumMethods > 0) {
5124 Result +=
"\nstatic struct {\n";
5125 Result +=
"\tint protocol_method_count;\n";
5126 Result +=
"\tstruct _protocol_methods protocol_methods[";
5127 Result += utostr(NumMethods);
5128 Result +=
"];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
5130 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
5132 Result += utostr(NumMethods);
5140 Result +=
"\t ,{{(struct objc_selector *)\"";
5142 Result +=
"\t ,{(struct objc_selector *)\"";
5143 Result += (*I)->getSelector().getAsString();
5144 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
5146 Result += MethodTypeString;
5149 Result +=
"\t }\n};\n";
5162 static bool objc_protocol =
false;
5163 if (!objc_protocol) {
5164 Result +=
"\nstruct _objc_protocol {\n";
5165 Result +=
"\tstruct _objc_protocol_extension *isa;\n";
5166 Result +=
"\tchar *protocol_name;\n";
5167 Result +=
"\tstruct _objc_protocol **protocol_list;\n";
5168 Result +=
"\tstruct _objc_protocol_method_list *instance_methods;\n";
5169 Result +=
"\tstruct _objc_protocol_method_list *class_methods;\n";
5172 objc_protocol =
true;
5175 Result +=
"\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
5177 Result +=
" __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
5180 Result +=
"\", 0, ";
5182 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
5189 Result +=
"(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
5199 llvm_unreachable(
"protocol already synthesized");
5202void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
5204 StringRef prefix, StringRef ClassName,
5205 std::string &Result) {
5206 if (Protocols.
empty())
return;
5208 for (
unsigned i = 0; i != Protocols.
size(); i++)
5209 RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
5218 Result +=
"\nstatic struct {\n";
5219 Result +=
"\tstruct _objc_protocol_list *next;\n";
5220 Result +=
"\tint protocol_count;\n";
5221 Result +=
"\tstruct _objc_protocol *class_protocols[";
5222 Result += utostr(Protocols.
size());
5223 Result +=
"];\n} _OBJC_";
5225 Result +=
"_PROTOCOLS_";
5226 Result += ClassName;
5227 Result +=
" __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
5229 Result += utostr(Protocols.
size());
5232 Result +=
"\t,{&_OBJC_PROTOCOL_";
5233 Result += Protocols[0]->getNameAsString();
5236 for (
unsigned i = 1; i != Protocols.
size(); i++) {
5237 Result +=
"\t ,&_OBJC_PROTOCOL_";
5238 Result += Protocols[i]->getNameAsString();
5241 Result +=
"\t }\n};\n";
5245 std::string &Result) {
5252 RewriteObjCInternalStruct(CDecl, Result);
5259 static bool objc_ivar =
false;
5267 Result +=
"\nstruct _objc_ivar {\n";
5268 Result +=
"\tchar *ivar_name;\n";
5269 Result +=
"\tchar *ivar_type;\n";
5270 Result +=
"\tint ivar_offset;\n";
5281 Result +=
"\nstatic struct {\n";
5282 Result +=
"\tint ivar_count;\n";
5283 Result +=
"\tstruct _objc_ivar ivar_list[";
5284 Result += utostr(NumIvars);
5285 Result +=
"];\n} _OBJC_INSTANCE_VARIABLES_";
5287 Result +=
" __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
5289 Result += utostr(NumIvars);
5295 for (
auto *IV : IDecl->
ivars())
5296 IVars.push_back(IV);
5303 Result +=
"\t,{{\"";
5304 Result += IVI->getNameAsString();
5306 std::string TmpString, StrEncoding;
5307 Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);
5308 QuoteDoublequotes(TmpString, StrEncoding);
5309 Result += StrEncoding;
5311 RewriteIvarOffsetComputation(*IVI, Result);
5313 for (++IVI; IVI != IVE; ++IVI) {
5314 Result +=
"\t ,{\"";
5315 Result += IVI->getNameAsString();
5317 std::string TmpString, StrEncoding;
5318 Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);
5319 QuoteDoublequotes(TmpString, StrEncoding);
5320 Result += StrEncoding;
5322 RewriteIvarOffsetComputation(*IVI, Result);
5326 Result +=
"\t }\n};\n";
5337 if (!Prop->getPropertyIvarDecl())
5343 if (!Getter->isDefined())
5344 InstanceMethods.push_back(Getter);
5348 if (!Setter->isDefined())
5349 InstanceMethods.push_back(Setter);
5351 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5352 true,
"", IDecl->
getName(), Result);
5356 false,
"", IDecl->
getName(), Result);
5360 "CLASS", CDecl->
getName(), Result);
5378 static bool objc_class =
false;
5380 Result +=
"\nstruct _objc_class {\n";
5381 Result +=
"\tstruct _objc_class *isa;\n";
5382 Result +=
"\tconst char *super_class_name;\n";
5383 Result +=
"\tchar *name;\n";
5384 Result +=
"\tlong version;\n";
5385 Result +=
"\tlong info;\n";
5386 Result +=
"\tlong instance_size;\n";
5387 Result +=
"\tstruct _objc_ivar_list *ivars;\n";
5388 Result +=
"\tstruct _objc_method_list *methods;\n";
5389 Result +=
"\tstruct objc_cache *cache;\n";
5390 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5391 Result +=
"\tconst char *ivar_layout;\n";
5392 Result +=
"\tstruct _objc_class_ext *ext;\n";
5400 while (SuperClass) {
5401 RootClass = SuperClass;
5406 Result +=
"\nstatic struct _objc_class _OBJC_METACLASS_";
5408 Result +=
" __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
5409 "{\n\t(struct _objc_class *)\"";
5421 Result +=
", 0, \"";
5427 Result +=
", 0,2, sizeof(struct _objc_class), 0";
5429 Result +=
"\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
5436 Result +=
"\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
5441 Result +=
"\t,0,0,0,0\n";
5445 Result +=
"\nstatic struct _objc_class _OBJC_CLASS_";
5447 Result +=
" __attribute__ ((used, section (\"__OBJC, __class\")))= "
5448 "{\n\t&_OBJC_METACLASS_";
5458 Result +=
", 0, \"";
5464 if (!ObjCSynthesizedStructs.count(CDecl))
5468 Result +=
",sizeof(struct ";
5470 if (LangOpts.MicrosoftExt)
5475 Result +=
", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
5482 Result +=
", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
5484 Result +=
", 0\n\t";
5489 Result +=
", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
5491 Result +=
", 0,0\n";
5494 Result +=
",0,0,0\n";
5498void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
5499 int ClsDefCount = ClassImplementation.size();
5500 int CatDefCount = CategoryImplementation.size();
5503 for (
int i = 0; i < ClsDefCount; i++)
5504 RewriteObjCClassMetaData(ClassImplementation[i], Result);
5507 for (
int i = 0; i < CatDefCount; i++)
5508 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
5522 Result +=
"\nstruct _objc_symtab {\n";
5523 Result +=
"\tlong sel_ref_cnt;\n";
5524 Result +=
"\tSEL *refs;\n";
5525 Result +=
"\tshort cls_def_cnt;\n";
5526 Result +=
"\tshort cat_def_cnt;\n";
5527 Result +=
"\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+
"];\n";
5530 Result +=
"static struct _objc_symtab "
5531 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
5532 Result +=
"\t0, 0, " + utostr(ClsDefCount)
5533 +
", " + utostr(CatDefCount) +
"\n";
5534 for (
int i = 0; i < ClsDefCount; i++) {
5535 Result +=
"\t,&_OBJC_CLASS_";
5536 Result += ClassImplementation[i]->getNameAsString();
5540 for (
int i = 0; i < CatDefCount; i++) {
5541 Result +=
"\t,&_OBJC_CATEGORY_";
5542 Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
5544 Result += CategoryImplementation[i]->getNameAsString();
5561 Result +=
"\nstruct _objc_module {\n";
5562 Result +=
"\tlong version;\n";
5563 Result +=
"\tlong size;\n";
5564 Result +=
"\tconst char *name;\n";
5565 Result +=
"\tstruct _objc_symtab *symtab;\n";
5567 Result +=
"static struct _objc_module "
5568 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
5569 Result +=
"\t" + utostr(OBJC_ABI_VERSION) +
5570 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
5573 if (LangOpts.MicrosoftExt) {
5574 if (ProtocolExprDecls.size()) {
5575 Result +=
"#pragma section(\".objc_protocol$B\",long,read,write)\n";
5576 Result +=
"#pragma data_seg(push, \".objc_protocol$B\")\n";
5578 Result +=
"static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
5579 Result += ProtDecl->getNameAsString();
5580 Result +=
" = &_OBJC_PROTOCOL_";
5581 Result += ProtDecl->getNameAsString();
5584 Result +=
"#pragma data_seg(pop)\n\n";
5586 Result +=
"#pragma section(\".objc_module_info$B\",long,read,write)\n";
5587 Result +=
"#pragma data_seg(push, \".objc_module_info$B\")\n";
5588 Result +=
"static struct _objc_module *_POINTER_OBJC_MODULES = ";
5589 Result +=
"&_OBJC_MODULES;\n";
5590 Result +=
"#pragma data_seg(pop)\n\n";
5597 std::string &Result) {
5604 FullCategoryName +=
'_';
5615 if (!Prop->getPropertyIvarDecl())
5621 InstanceMethods.push_back(Getter);
5625 InstanceMethods.push_back(Setter);
5627 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5628 true,
"CATEGORY_", FullCategoryName, Result);
5632 false,
"CATEGORY_", FullCategoryName, Result);
5638 FullCategoryName, Result);
5652 static bool objc_category =
false;
5653 if (!objc_category) {
5654 Result +=
"\nstruct _objc_category {\n";
5655 Result +=
"\tchar *category_name;\n";
5656 Result +=
"\tchar *class_name;\n";
5657 Result +=
"\tstruct _objc_method_list *instance_methods;\n";
5658 Result +=
"\tstruct _objc_method_list *class_methods;\n";
5659 Result +=
"\tstruct _objc_protocol_list *protocols;\n";
5660 Result +=
"\tunsigned int size;\n";
5661 Result +=
"\tstruct _objc_property_list *instance_properties;\n";
5663 objc_category =
true;
5665 Result +=
"\nstatic struct _objc_category _OBJC_CATEGORY_";
5666 Result += FullCategoryName;
5667 Result +=
" __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
5669 Result +=
"\"\n\t, \"";
5674 Result +=
"\t, (struct _objc_method_list *)"
5675 "&_OBJC_CATEGORY_INSTANCE_METHODS_";
5676 Result += FullCategoryName;
5680 Result +=
"\t, 0\n";
5682 Result +=
"\t, (struct _objc_method_list *)"
5683 "&_OBJC_CATEGORY_CLASS_METHODS_";
5684 Result += FullCategoryName;
5688 Result +=
"\t, 0\n";
5691 Result +=
"\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
5692 Result += FullCategoryName;
5696 Result +=
"\t, 0\n";
5697 Result +=
"\t, sizeof(struct _objc_category), 0\n};\n";
5702template<
typename MethodIterator>
5703void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5704 MethodIterator MethodEnd,
5705 bool IsInstanceMethod,
5707 StringRef ClassName,
5708 std::string &Result) {
5709 if (MethodBegin == MethodEnd)
return;
5711 if (!objc_impl_method) {
5718 Result +=
"\nstruct _objc_method {\n";
5719 Result +=
"\tSEL _cmd;\n";
5720 Result +=
"\tchar *method_types;\n";
5721 Result +=
"\tvoid *_imp;\n";
5724 objc_impl_method =
true;
5735 unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
5736 Result +=
"\nstatic struct {\n";
5737 Result +=
"\tstruct _objc_method_list *next_method;\n";
5738 Result +=
"\tint method_count;\n";
5739 Result +=
"\tstruct _objc_method method_list[";
5740 Result += utostr(NumMethods);
5741 Result +=
"];\n} _OBJC_";
5744 Result +=
"_METHODS_";
5745 Result += ClassName;
5746 Result +=
" __attribute__ ((used, section (\"__OBJC, __";
5748 Result +=
"_meth\")))= ";
5749 Result +=
"{\n\t0, " + utostr(NumMethods) +
"\n";
5751 Result +=
"\t,{{(SEL)\"";
5752 Result += (*MethodBegin)->getSelector().getAsString();
5753 std::string MethodTypeString =
5754 Context->getObjCEncodingForMethodDecl(*MethodBegin);
5756 Result += MethodTypeString;
5757 Result +=
"\", (void *)";
5758 Result += MethodInternalNames[*MethodBegin];
5760 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
5761 Result +=
"\t ,{(SEL)\"";
5762 Result += (*MethodBegin)->getSelector().getAsString();
5763 std::string MethodTypeString =
5764 Context->getObjCEncodingForMethodDecl(*MethodBegin);
5766 Result += MethodTypeString;
5767 Result +=
"\", (void *)";
5768 Result += MethodInternalNames[*MethodBegin];
5771 Result +=
"\t }\n};\n";
5780 DisableReplaceStmtScope S(*
this);
5781 BaseExpr =
cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
5787 Expr *Replacement = IV;
5792 assert(iFaceDecl &&
"RewriteObjCIvarRefExpr - iFaceDecl is null");
5797 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5800 std::string RecName =
5806 SourceLocation(), SourceLocation(), II);
5807 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5809 Context->getPointerType(Context->getCanonicalTagType(RD));
5828 assert(!IV->
isFreeIvar() &&
"Cannot have a free standing ivar outside a method");
5839 assert(clsDeclared &&
"RewriteObjCIvarRefExpr(): Can't find class");
5842 std::string RecName =
5848 SourceLocation(), SourceLocation(), II);
5849 assert(RD &&
"RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5851 Context->getPointerType(Context->getCanonicalTagType(RD));
5865 ReplaceStmtWithRange(IV, Replacement, OldRange);
Defines the Diagnostic-related interfaces.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)
Defines the SourceManager interface.
__device__ __2f16 float c
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getObjCClassType() const
Represents the Objective-C Class type.
FullSourceLoc getFullLoc(SourceLocation Loc) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
QualType getObjCIdType() const
Represents the Objective-CC id type.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Represents a member of a struct/union/class.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
A builtin binary operation expression such as "x + y" or "x <= y".
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
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]).
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
ExprIterator arg_iterator
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
SourceLocation getEndLoc() const
ConditionalOperator - The ?
ContinueStmt - This represents a continue.
decl_iterator - Iterates through the declarations stored within this context.
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
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
TranslationUnitDecl * getTranslationUnitDecl()
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.
bool isBitField() const
Determines whether this field is a bitfield.
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
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 ...
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Describes an C or C++ initializer list.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
Represents a linkage specification.
SourceLocation getBeginLoc() const
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
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.
const Expr * getSynchExpr() const
const CompoundStmt * getSynchBody() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents Objective-C's @throw statement.
const Expr * getThrowExpr() const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents Objective-C's @try ... @catch ... @finally statement.
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
unsigned getNumCatchStmts() const
Retrieve the number of @catch statements in this try-catch-finally block.
SourceLocation getBeginLoc() const LLVM_READONLY
const ObjCAtCatchStmt * getCatchStmt(unsigned I) const
Retrieve a @catch statement.
const Stmt * getTryBody() const
Retrieve the @try body.
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
filtered_decl_iterator< ObjCMethodDecl, &ObjCMethodDecl::isInstanceMethod > instmeth_iterator
SourceRange getAtEndRange() const
classmeth_iterator classmeth_begin() const
instmeth_range instance_methods() const
filtered_decl_iterator< ObjCMethodDecl, &ObjCMethodDecl::isClassMethod > classmeth_iterator
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.
SourceLocation getRParenLoc() const
SourceLocation getBeginLoc() const LLVM_READONLY
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
specific_decl_iterator< ObjCIvarDecl > ivar_iterator
Represents typeof(type), a C23 feature and GCC extension, or `typeof_unqual(type),...
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.
static ObjCMessageExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, ArrayRef< SourceLocation > SelLocs, ObjCMethodDecl *Method, ArrayRef< Expr * > Args, SourceLocation RBracLoc, bool isImplicit)
Create a message send to super.
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
@ SuperInstance
The receiver is the instance of the superclass object.
@ Instance
The receiver is an object instance.
@ SuperClass
The receiver is a superclass.
@ Class
The receiver is a class.
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 getBeginLoc() const LLVM_READONLY
Selector getSelector() const
bool isInstanceMethod() const
QualType getReturnType() const
ObjCInterfaceDecl * getClassInterface()
Represents a pointer to an Objective C object.
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.
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
static RecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl=nullptr)
virtual void completeDefinition()
Note that the definition of this type is now complete.
static bool isRewritable(SourceLocation Loc)
isRewritable - Return true if this location is a raw file location, which is rewritable.
std::string getAsString() const
Derive the full selector name (e.g.
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
unsigned getByteLength() const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
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.
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.
RecordDecl * castAsRecordDecl() const
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
static TypedefDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, TypeSourceInfo *TInfo)
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),...
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
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.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
const Expr * getInit() const
StorageClass getStorageClass() const
Returns the storage class as written in the source.
@ BLOCK_BYREF_CURRENT_MAX
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
@ 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...
@ ICIS_NoInit
No in-class initializer.
@ 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].
const FunctionProtoType * T
@ Struct
The "struct" keyword.
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.
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.
CLINKAGE int printf(__constant const char *st,...) __attribute__((format(printf
Describes how types, statements, expressions, and declarations should be printed.