/contrib/llvm/tools/clang/lib/Rewrite/RewriteModernObjC.cpp
C++ | 7543 lines | 5919 code | 738 blank | 886 comment | 1041 complexity | 2ed2046794fc9451031af33af51c7ef3 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- //===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // Hacks and fun related to the code rewriter.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/Rewrite/ASTConsumers.h"
- #include "clang/Rewrite/Rewriter.h"
- #include "clang/AST/AST.h"
- #include "clang/AST/ASTConsumer.h"
- #include "clang/AST/ParentMap.h"
- #include "clang/Basic/SourceManager.h"
- #include "clang/Basic/IdentifierTable.h"
- #include "clang/Basic/Diagnostic.h"
- #include "clang/Lex/Lexer.h"
- #include "llvm/Support/MemoryBuffer.h"
- #include "llvm/Support/raw_ostream.h"
- #include "llvm/ADT/StringExtras.h"
- #include "llvm/ADT/SmallPtrSet.h"
- #include "llvm/ADT/OwningPtr.h"
- #include "llvm/ADT/DenseSet.h"
- using namespace clang;
- using llvm::utostr;
- namespace {
- class RewriteModernObjC : public ASTConsumer {
- protected:
-
- enum {
- BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
- block, ... */
- BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
- BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
- __block variable */
- BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
- helpers */
- BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
- support routines */
- BLOCK_BYREF_CURRENT_MAX = 256
- };
-
- enum {
- BLOCK_NEEDS_FREE = (1 << 24),
- BLOCK_HAS_COPY_DISPOSE = (1 << 25),
- BLOCK_HAS_CXX_OBJ = (1 << 26),
- BLOCK_IS_GC = (1 << 27),
- BLOCK_IS_GLOBAL = (1 << 28),
- BLOCK_HAS_DESCRIPTOR = (1 << 29)
- };
- static const int OBJC_ABI_VERSION = 7;
-
- Rewriter Rewrite;
- DiagnosticsEngine &Diags;
- const LangOptions &LangOpts;
- ASTContext *Context;
- SourceManager *SM;
- TranslationUnitDecl *TUDecl;
- FileID MainFileID;
- const char *MainFileStart, *MainFileEnd;
- Stmt *CurrentBody;
- ParentMap *PropParentMap; // created lazily.
- std::string InFileName;
- raw_ostream* OutFile;
- std::string Preamble;
-
- TypeDecl *ProtocolTypeDecl;
- VarDecl *GlobalVarDecl;
- Expr *GlobalConstructionExp;
- unsigned RewriteFailedDiag;
- unsigned GlobalBlockRewriteFailedDiag;
- // ObjC string constant support.
- unsigned NumObjCStringLiterals;
- VarDecl *ConstantStringClassReference;
- RecordDecl *NSStringRecord;
- // ObjC foreach break/continue generation support.
- int BcLabelCount;
-
- unsigned TryFinallyContainsReturnDiag;
- // Needed for super.
- ObjCMethodDecl *CurMethodDef;
- RecordDecl *SuperStructDecl;
- RecordDecl *ConstantStringDecl;
-
- FunctionDecl *MsgSendFunctionDecl;
- FunctionDecl *MsgSendSuperFunctionDecl;
- FunctionDecl *MsgSendStretFunctionDecl;
- FunctionDecl *MsgSendSuperStretFunctionDecl;
- FunctionDecl *MsgSendFpretFunctionDecl;
- FunctionDecl *GetClassFunctionDecl;
- FunctionDecl *GetMetaClassFunctionDecl;
- FunctionDecl *GetSuperClassFunctionDecl;
- FunctionDecl *SelGetUidFunctionDecl;
- FunctionDecl *CFStringFunctionDecl;
- FunctionDecl *SuperContructorFunctionDecl;
- FunctionDecl *CurFunctionDef;
- /* Misc. containers needed for meta-data rewrite. */
- SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
- SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
- llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
- llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
- llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;
- llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;
- SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;
- /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
- SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;
-
- /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
- llvm::SmallVector<ObjCCategoryDecl*, 8> DefinedNonLazyCategories;
-
- SmallVector<Stmt *, 32> Stmts;
- SmallVector<int, 8> ObjCBcLabelNo;
- // Remember all the @protocol(<expr>) expressions.
- llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
-
- llvm::DenseSet<uint64_t> CopyDestroyCache;
- // Block expressions.
- SmallVector<BlockExpr *, 32> Blocks;
- SmallVector<int, 32> InnerDeclRefsCount;
- SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
-
- SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
- // Block related declarations.
- SmallVector<ValueDecl *, 8> BlockByCopyDecls;
- llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
- SmallVector<ValueDecl *, 8> BlockByRefDecls;
- llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
- llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
- llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
- llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
-
- llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
- llvm::DenseMap<ObjCInterfaceDecl *,
- llvm::SmallPtrSet<ObjCIvarDecl *, 8> > ReferencedIvars;
-
- // This maps an original source AST to it's rewritten form. This allows
- // us to avoid rewriting the same node twice (which is very uncommon).
- // This is needed to support some of the exotic property rewriting.
- llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
- // Needed for header files being rewritten
- bool IsHeader;
- bool SilenceRewriteMacroWarning;
- bool objc_impl_method;
-
- bool DisableReplaceStmt;
- class DisableReplaceStmtScope {
- RewriteModernObjC &R;
- bool SavedValue;
-
- public:
- DisableReplaceStmtScope(RewriteModernObjC &R)
- : R(R), SavedValue(R.DisableReplaceStmt) {
- R.DisableReplaceStmt = true;
- }
- ~DisableReplaceStmtScope() {
- R.DisableReplaceStmt = SavedValue;
- }
- };
- void InitializeCommon(ASTContext &context);
- public:
- llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
- // Top Level Driver code.
- virtual bool HandleTopLevelDecl(DeclGroupRef D) {
- for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
- if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
- if (!Class->isThisDeclarationADefinition()) {
- RewriteForwardClassDecl(D);
- break;
- } else {
- // Keep track of all interface declarations seen.
- ObjCInterfacesSeen.push_back(Class);
- break;
- }
- }
- if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
- if (!Proto->isThisDeclarationADefinition()) {
- RewriteForwardProtocolDecl(D);
- break;
- }
- }
- HandleTopLevelSingleDecl(*I);
- }
- return true;
- }
- void HandleTopLevelSingleDecl(Decl *D);
- void HandleDeclInMainFile(Decl *D);
- RewriteModernObjC(std::string inFile, raw_ostream *OS,
- DiagnosticsEngine &D, const LangOptions &LOpts,
- bool silenceMacroWarn);
-
- ~RewriteModernObjC() {}
-
- virtual void HandleTranslationUnit(ASTContext &C);
- void ReplaceStmt(Stmt *Old, Stmt *New) {
- Stmt *ReplacingStmt = ReplacedNodes[Old];
- if (ReplacingStmt)
- return; // We can't rewrite the same node twice.
- if (DisableReplaceStmt)
- return;
- // If replacement succeeded or warning disabled return with no warning.
- if (!Rewrite.ReplaceStmt(Old, New)) {
- ReplacedNodes[Old] = New;
- return;
- }
- if (SilenceRewriteMacroWarning)
- return;
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
- }
- void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
- if (DisableReplaceStmt)
- return;
- // Measure the old text.
- int Size = Rewrite.getRangeSize(SrcRange);
- if (Size == -1) {
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
- return;
- }
- // Get the new text.
- std::string SStr;
- llvm::raw_string_ostream S(SStr);
- New->printPretty(S, 0, PrintingPolicy(LangOpts));
- const std::string &Str = S.str();
- // If replacement succeeded or warning disabled return with no warning.
- if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
- ReplacedNodes[Old] = New;
- return;
- }
- if (SilenceRewriteMacroWarning)
- return;
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
- }
- void InsertText(SourceLocation Loc, StringRef Str,
- bool InsertAfter = true) {
- // If insertion succeeded or warning disabled return with no warning.
- if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
- SilenceRewriteMacroWarning)
- return;
- Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
- }
- void ReplaceText(SourceLocation Start, unsigned OrigLength,
- StringRef Str) {
- // If removal succeeded or warning disabled return with no warning.
- if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
- SilenceRewriteMacroWarning)
- return;
- Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
- }
- // Syntactic Rewriting.
- void RewriteRecordBody(RecordDecl *RD);
- void RewriteInclude();
- void RewriteForwardClassDecl(DeclGroupRef D);
- void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG);
- void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
- const std::string &typedefString);
- void RewriteImplementations();
- void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
- ObjCImplementationDecl *IMD,
- ObjCCategoryImplDecl *CID);
- void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
- void RewriteImplementationDecl(Decl *Dcl);
- void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
- ObjCMethodDecl *MDecl, std::string &ResultStr);
- void RewriteTypeIntoString(QualType T, std::string &ResultStr,
- const FunctionType *&FPRetType);
- void RewriteByRefString(std::string &ResultStr, const std::string &Name,
- ValueDecl *VD, bool def=false);
- void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
- void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
- void RewriteForwardProtocolDecl(DeclGroupRef D);
- void RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG);
- void RewriteMethodDeclaration(ObjCMethodDecl *Method);
- void RewriteProperty(ObjCPropertyDecl *prop);
- void RewriteFunctionDecl(FunctionDecl *FD);
- void RewriteBlockPointerType(std::string& Str, QualType Type);
- void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
- void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
- void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
- void RewriteTypeOfDecl(VarDecl *VD);
- void RewriteObjCQualifiedInterfaceTypes(Expr *E);
-
- std::string getIvarAccessString(ObjCIvarDecl *D);
-
- // Expression Rewriting.
- Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
- Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
- Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
- Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
- Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
- Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
- Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
- Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);
- Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);
- Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);
- Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);
- Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
- Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
- Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
- Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
- Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
- Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
- SourceLocation OrigEnd);
- Stmt *RewriteBreakStmt(BreakStmt *S);
- Stmt *RewriteContinueStmt(ContinueStmt *S);
- void RewriteCastExpr(CStyleCastExpr *CE);
- void RewriteImplicitCastObjCExpr(CastExpr *IE);
- void RewriteLinkageSpec(LinkageSpecDecl *LSD);
-
- // Block rewriting.
- void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
-
- // Block specific rewrite rules.
- void RewriteBlockPointerDecl(NamedDecl *VD);
- void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);
- Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
- Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
- void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
-
- void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
- std::string &Result);
-
- void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);
- bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,
- bool &IsNamedDefinition);
- void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
- std::string &Result);
-
- bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);
-
- void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
- std::string &Result);
-
- virtual void Initialize(ASTContext &context);
-
- // Misc. AST transformation routines. Sometimes they end up calling
- // rewriting routines on the new ASTs.
- CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
- Expr **args, unsigned nargs,
- SourceLocation StartLoc=SourceLocation(),
- SourceLocation EndLoc=SourceLocation());
-
- Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
- QualType msgSendType,
- QualType returnType,
- SmallVectorImpl<QualType> &ArgTypes,
- SmallVectorImpl<Expr*> &MsgExprs,
- ObjCMethodDecl *Method);
- Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
- SourceLocation StartLoc=SourceLocation(),
- SourceLocation EndLoc=SourceLocation());
-
- void SynthCountByEnumWithState(std::string &buf);
- void SynthMsgSendFunctionDecl();
- void SynthMsgSendSuperFunctionDecl();
- void SynthMsgSendStretFunctionDecl();
- void SynthMsgSendFpretFunctionDecl();
- void SynthMsgSendSuperStretFunctionDecl();
- void SynthGetClassFunctionDecl();
- void SynthGetMetaClassFunctionDecl();
- void SynthGetSuperClassFunctionDecl();
- void SynthSelGetUidFunctionDecl();
- void SynthSuperContructorFunctionDecl();
-
- // Rewriting metadata
- template<typename MethodIterator>
- void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
- MethodIterator MethodEnd,
- bool IsInstanceMethod,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result);
- void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
- std::string &Result);
- void RewriteObjCProtocolListMetaData(
- const ObjCList<ObjCProtocolDecl> &Prots,
- StringRef prefix, StringRef ClassName, std::string &Result);
- void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
- std::string &Result);
- void RewriteClassSetupInitHook(std::string &Result);
-
- void RewriteMetaDataIntoBuffer(std::string &Result);
- void WriteImageInfo(std::string &Result);
- void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
- std::string &Result);
- void RewriteCategorySetupInitHook(std::string &Result);
-
- // Rewriting ivar
- void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
- std::string &Result);
- Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
-
- std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
- std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
- StringRef funcName, std::string Tag);
- std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
- StringRef funcName, std::string Tag);
- std::string SynthesizeBlockImpl(BlockExpr *CE,
- std::string Tag, std::string Desc);
- std::string SynthesizeBlockDescriptor(std::string DescTag,
- std::string ImplTag,
- int i, StringRef funcName,
- unsigned hasCopy);
- Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
- void SynthesizeBlockLiterals(SourceLocation FunLocStart,
- StringRef FunName);
- FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
- Stmt *SynthBlockInitExpr(BlockExpr *Exp,
- const SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs);
- // Misc. helper routines.
- QualType getProtocolType();
- void WarnAboutReturnGotoStmts(Stmt *S);
- void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
- void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
- void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
- bool IsDeclStmtInForeachHeader(DeclStmt *DS);
- void CollectBlockDeclRefInfo(BlockExpr *Exp);
- void GetBlockDeclRefExprs(Stmt *S);
- void GetInnerBlockDeclRefExprs(Stmt *S,
- SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs,
- llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts);
- // We avoid calling Type::isBlockPointerType(), since it operates on the
- // canonical type. We only care if the top-level type is a closure pointer.
- bool isTopLevelBlockPointerType(QualType T) {
- return isa<BlockPointerType>(T);
- }
- /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
- /// to a function pointer type and upon success, returns true; false
- /// otherwise.
- bool convertBlockPointerToFunctionPointer(QualType &T) {
- if (isTopLevelBlockPointerType(T)) {
- const BlockPointerType *BPT = T->getAs<BlockPointerType>();
- T = Context->getPointerType(BPT->getPointeeType());
- return true;
- }
- return false;
- }
-
- bool convertObjCTypeToCStyleType(QualType &T);
-
- bool needToScanForQualifiers(QualType T);
- QualType getSuperStructType();
- QualType getConstantStringStructType();
- QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
- bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
-
- void convertToUnqualifiedObjCType(QualType &T) {
- if (T->isObjCQualifiedIdType()) {
- bool isConst = T.isConstQualified();
- T = isConst ? Context->getObjCIdType().withConst()
- : Context->getObjCIdType();
- }
- else if (T->isObjCQualifiedClassType())
- T = Context->getObjCClassType();
- else if (T->isObjCObjectPointerType() &&
- T->getPointeeType()->isObjCQualifiedInterfaceType()) {
- if (const ObjCObjectPointerType * OBJPT =
- T->getAsObjCInterfacePointerType()) {
- const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
- T = QualType(IFaceT, 0);
- T = Context->getPointerType(T);
- }
- }
- }
-
- // FIXME: This predicate seems like it would be useful to add to ASTContext.
- bool isObjCType(QualType T) {
- if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
- return false;
- QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
- if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
- OCT == Context->getCanonicalType(Context->getObjCClassType()))
- return true;
- if (const PointerType *PT = OCT->getAs<PointerType>()) {
- if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
- PT->getPointeeType()->isObjCQualifiedIdType())
- return true;
- }
- return false;
- }
- bool PointerTypeTakesAnyBlockArguments(QualType QT);
- bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
- void GetExtentOfArgList(const char *Name, const char *&LParen,
- const char *&RParen);
-
- void QuoteDoublequotes(std::string &From, std::string &To) {
- for (unsigned i = 0; i < From.length(); i++) {
- if (From[i] == '"')
- To += "\\\"";
- else
- To += From[i];
- }
- }
- QualType getSimpleFunctionType(QualType result,
- const QualType *args,
- unsigned numArgs,
- bool variadic = false) {
- if (result == Context->getObjCInstanceType())
- result = Context->getObjCIdType();
- FunctionProtoType::ExtProtoInfo fpi;
- fpi.Variadic = variadic;
- return Context->getFunctionType(result, args, numArgs, fpi);
- }
- // Helper function: create a CStyleCastExpr with trivial type source info.
- CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
- CastKind Kind, Expr *E) {
- TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
- return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo,
- SourceLocation(), SourceLocation());
- }
-
- bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
- IdentifierInfo* II = &Context->Idents.get("load");
- Selector LoadSel = Context->Selectors.getSelector(0, &II);
- return OD->getClassMethod(LoadSel) != 0;
- }
- };
-
- }
- void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
- NamedDecl *D) {
- if (const FunctionProtoType *fproto
- = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
- for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(),
- E = fproto->arg_type_end(); I && (I != E); ++I)
- if (isTopLevelBlockPointerType(*I)) {
- // All the args are checked/rewritten. Don't call twice!
- RewriteBlockPointerDecl(D);
- break;
- }
- }
- }
- void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
- const PointerType *PT = funcType->getAs<PointerType>();
- if (PT && PointerTypeTakesAnyBlockArguments(funcType))
- RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
- }
- static bool IsHeaderFile(const std::string &Filename) {
- std::string::size_type DotPos = Filename.rfind('.');
- if (DotPos == std::string::npos) {
- // no file extension
- return false;
- }
- std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
- // C header: .h
- // C++ header: .hh or .H;
- return Ext == "h" || Ext == "hh" || Ext == "H";
- }
- RewriteModernObjC::RewriteModernObjC(std::string inFile, raw_ostream* OS,
- DiagnosticsEngine &D, const LangOptions &LOpts,
- bool silenceMacroWarn)
- : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS),
- SilenceRewriteMacroWarning(silenceMacroWarn) {
- IsHeader = IsHeaderFile(inFile);
- RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
- "rewriting sub-expression within a macro (may not be correct)");
- // FIXME. This should be an error. But if block is not called, it is OK. And it
- // may break including some headers.
- GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
- "rewriting block literal declared in global scope is not implemented");
-
- TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
- DiagnosticsEngine::Warning,
- "rewriter doesn't support user-specified control flow semantics "
- "for @try/@finally (code may not execute properly)");
- }
- ASTConsumer *clang::CreateModernObjCRewriter(const std::string& InFile,
- raw_ostream* OS,
- DiagnosticsEngine &Diags,
- const LangOptions &LOpts,
- bool SilenceRewriteMacroWarning) {
- return new RewriteModernObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
- }
- void RewriteModernObjC::InitializeCommon(ASTContext &context) {
- Context = &context;
- SM = &Context->getSourceManager();
- TUDecl = Context->getTranslationUnitDecl();
- MsgSendFunctionDecl = 0;
- MsgSendSuperFunctionDecl = 0;
- MsgSendStretFunctionDecl = 0;
- MsgSendSuperStretFunctionDecl = 0;
- MsgSendFpretFunctionDecl = 0;
- GetClassFunctionDecl = 0;
- GetMetaClassFunctionDecl = 0;
- GetSuperClassFunctionDecl = 0;
- SelGetUidFunctionDecl = 0;
- CFStringFunctionDecl = 0;
- ConstantStringClassReference = 0;
- NSStringRecord = 0;
- CurMethodDef = 0;
- CurFunctionDef = 0;
- GlobalVarDecl = 0;
- GlobalConstructionExp = 0;
- SuperStructDecl = 0;
- ProtocolTypeDecl = 0;
- ConstantStringDecl = 0;
- BcLabelCount = 0;
- SuperContructorFunctionDecl = 0;
- NumObjCStringLiterals = 0;
- PropParentMap = 0;
- CurrentBody = 0;
- DisableReplaceStmt = false;
- objc_impl_method = false;
- // Get the ID and start/end of the main file.
- MainFileID = SM->getMainFileID();
- const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
- MainFileStart = MainBuf->getBufferStart();
- MainFileEnd = MainBuf->getBufferEnd();
- Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
- }
- //===----------------------------------------------------------------------===//
- // Top Level Driver Code
- //===----------------------------------------------------------------------===//
- void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
- if (Diags.hasErrorOccurred())
- return;
- // Two cases: either the decl could be in the main file, or it could be in a
- // #included file. If the former, rewrite it now. If the later, check to see
- // if we rewrote the #include/#import.
- SourceLocation Loc = D->getLocation();
- Loc = SM->getExpansionLoc(Loc);
- // If this is for a builtin, ignore it.
- if (Loc.isInvalid()) return;
- // Look for built-in declarations that we need to refer during the rewrite.
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- RewriteFunctionDecl(FD);
- } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
- // declared in <Foundation/NSString.h>
- if (FVD->getName() == "_NSConstantStringClassReference") {
- ConstantStringClassReference = FVD;
- return;
- }
- } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
- RewriteCategoryDecl(CD);
- } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
- if (PD->isThisDeclarationADefinition())
- RewriteProtocolDecl(PD);
- } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
- // FIXME. This will not work in all situations and leaving it out
- // is harmless.
- // RewriteLinkageSpec(LSD);
-
- // Recurse into linkage specifications
- for (DeclContext::decl_iterator DI = LSD->decls_begin(),
- DIEnd = LSD->decls_end();
- DI != DIEnd; ) {
- if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
- if (!IFace->isThisDeclarationADefinition()) {
- SmallVector<Decl *, 8> DG;
- SourceLocation StartLoc = IFace->getLocStart();
- do {
- if (isa<ObjCInterfaceDecl>(*DI) &&
- !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
- StartLoc == (*DI)->getLocStart())
- DG.push_back(*DI);
- else
- break;
-
- ++DI;
- } while (DI != DIEnd);
- RewriteForwardClassDecl(DG);
- continue;
- }
- else {
- // Keep track of all interface declarations seen.
- ObjCInterfacesSeen.push_back(IFace);
- ++DI;
- continue;
- }
- }
- if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
- if (!Proto->isThisDeclarationADefinition()) {
- SmallVector<Decl *, 8> DG;
- SourceLocation StartLoc = Proto->getLocStart();
- do {
- if (isa<ObjCProtocolDecl>(*DI) &&
- !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
- StartLoc == (*DI)->getLocStart())
- DG.push_back(*DI);
- else
- break;
-
- ++DI;
- } while (DI != DIEnd);
- RewriteForwardProtocolDecl(DG);
- continue;
- }
- }
-
- HandleTopLevelSingleDecl(*DI);
- ++DI;
- }
- }
- // If we have a decl in the main file, see if we should rewrite it.
- if (SM->isFromMainFile(Loc))
- return HandleDeclInMainFile(D);
- }
- //===----------------------------------------------------------------------===//
- // Syntactic (non-AST) Rewriting Code
- //===----------------------------------------------------------------------===//
- void RewriteModernObjC::RewriteInclude() {
- SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
- StringRef MainBuf = SM->getBufferData(MainFileID);
- const char *MainBufStart = MainBuf.begin();
- const char *MainBufEnd = MainBuf.end();
- size_t ImportLen = strlen("import");
- // Loop over the whole file, looking for includes.
- for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
- if (*BufPtr == '#') {
- if (++BufPtr == MainBufEnd)
- return;
- while (*BufPtr == ' ' || *BufPtr == '\t')
- if (++BufPtr == MainBufEnd)
- return;
- if (!strncmp(BufPtr, "import", ImportLen)) {
- // replace import with include
- SourceLocation ImportLoc =
- LocStart.getLocWithOffset(BufPtr-MainBufStart);
- ReplaceText(ImportLoc, ImportLen, "include");
- BufPtr += ImportLen;
- }
- }
- }
- }
- static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,
- ObjCIvarDecl *IvarDecl, std::string &Result) {
- Result += "OBJC_IVAR_$_";
- Result += IDecl->getName();
- Result += "$";
- Result += IvarDecl->getName();
- }
- std::string
- RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
- const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();
-
- // Build name of symbol holding ivar offset.
- std::string IvarOffsetName;
- WriteInternalIvarName(ClassDecl, D, IvarOffsetName);
-
-
- std::string S = "(*(";
- QualType IvarT = D->getType();
-
- if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) {
- RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl();
- RD = RD->getDefinition();
- if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
- // decltype(((Foo_IMPL*)0)->bar) *
- ObjCContainerDecl *CDecl =
- dyn_cast<ObjCContainerDecl>(D->getDeclContext());
- // ivar in class extensions requires special treatment.
- if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
- CDecl = CatDecl->getClassInterface();
- std::string RecName = CDecl->getName();
- RecName += "_IMPL";
- RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
- SourceLocation(), SourceLocation(),
- &Context->Idents.get(RecName.c_str()));
- QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
- unsigned UnsignedIntSize =
- static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
- Expr *Zero = IntegerLiteral::Create(*Context,
- llvm::APInt(UnsignedIntSize, 0),
- Context->UnsignedIntTy, SourceLocation());
- Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
- ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
- Zero);
- FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
- SourceLocation(),
- &Context->Idents.get(D->getNameAsString()),
- IvarT, 0,
- /*BitWidth=*/0, /*Mutable=*/true,
- ICIS_NoInit);
- MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
- FD->getType(), VK_LValue,
- OK_Ordinary);
- IvarT = Context->getDecltypeType(ME, ME->getType());
- }
- }
- convertObjCTypeToCStyleType(IvarT);
- QualType castT = Context->getPointerType(IvarT);
- std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));
- S += TypeString;
- S += ")";
-
- // ((char *)self + IVAR_OFFSET_SYMBOL_NAME)
- S += "((char *)self + ";
- S += IvarOffsetName;
- S += "))";
- ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D);
- return S;
- }
- /// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not
- /// been found in the class implementation. In this case, it must be synthesized.
- static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,
- ObjCPropertyDecl *PD,
- bool getter) {
- return getter ? !IMP->getInstanceMethod(PD->getGetterName())
- : !IMP->getInstanceMethod(PD->getSetterName());
-
- }
- void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
- ObjCImplementationDecl *IMD,
- ObjCCategoryImplDecl *CID) {
- static bool objcGetPropertyDefined = false;
- static bool objcSetPropertyDefined = false;
- SourceLocation startGetterSetterLoc;
-
- if (PID->getLocStart().isValid()) {
- SourceLocation startLoc = PID->getLocStart();
- InsertText(startLoc, "// ");
- const char *startBuf = SM->getCharacterData(startLoc);
- assert((*startBuf == '@') && "bogus @synthesize location");
- const char *semiBuf = strchr(startBuf, ';');
- assert((*semiBuf == ';') && "@synthesize: can't find ';'");
- startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
- }
- else
- startGetterSetterLoc = IMD ? IMD->getLocEnd() : CID->getLocEnd();
- if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
- return; // FIXME: is this correct?
- // Generate the 'getter' function.
- ObjCPropertyDecl *PD = PID->getPropertyDecl();
- ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
- if (!OID)
- return;
- unsigned Attributes = PD->getPropertyAttributes();
- if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {
- bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
- (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
- ObjCPropertyDecl::OBJC_PR_copy));
- std::string Getr;
- if (GenGetProperty && !objcGetPropertyDefined) {
- objcGetPropertyDefined = true;
- // FIXME. Is this attribute correct in all cases?
- Getr = "\nextern \"C\" __declspec(dllimport) "
- "id objc_getProperty(id, SEL, long, bool);\n";
- }
- RewriteObjCMethodDecl(OID->getContainingInterface(),
- PD->getGetterMethodDecl(), Getr);
- Getr += "{ ";
- // Synthesize an explicit cast to gain access to the ivar.
- // See objc-act.c:objc_synthesize_new_getter() for details.
- if (GenGetProperty) {
- // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
- Getr += "typedef ";
- const FunctionType *FPRetType = 0;
- RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr,
- FPRetType);
- Getr += " _TYPE";
- if (FPRetType) {
- Getr += ")"; // close the precedence "scope" for "*".
-
- // Now, emit the argument types (if any).
- if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
- Getr += "(";
- for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
- if (i) Getr += ", ";
- std::string ParamStr = FT->getArgType(i).getAsString(
- Context->getPrintingPolicy());
- Getr += ParamStr;
- }
- if (FT->isVariadic()) {
- if (FT->getNumArgs()) Getr += ", ";
- Getr += "...";
- }
- Getr += ")";
- } else
- Getr += "()";
- }
- Getr += ";\n";
- Getr += "return (_TYPE)";
- Getr += "objc_getProperty(self, _cmd, ";
- RewriteIvarOffsetComputation(OID, Getr);
- Getr += ", 1)";
- }
- else
- Getr += "return " + getIvarAccessString(OID);
- Getr += "; }";
- InsertText(startGetterSetterLoc, Getr);
- }
-
- if (PD->isReadOnly() ||
- !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/))
- return;
- // Generate the 'setter' function.
- std::string Setr;
- bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
- ObjCPropertyDecl::OBJC_PR_copy);
- if (GenSetProperty && !objcSetPropertyDefined) {
- objcSetPropertyDefined = true;
- // FIXME. Is this attribute correct in all cases?
- Setr = "\nextern \"C\" __declspec(dllimport) "
- "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
- }
-
- RewriteObjCMethodDecl(OID->getContainingInterface(),
- PD->getSetterMethodDecl(), Setr);
- Setr += "{ ";
- // Synthesize an explicit cast to initialize the ivar.
- // See objc-act.c:objc_synthesize_new_setter() for details.
- if (GenSetProperty) {
- Setr += "objc_setProperty (self, _cmd, ";
- RewriteIvarOffsetComputation(OID, Setr);
- Setr += ", (id)";
- Setr += PD->getName();
- Setr += ", ";
- if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
- Setr += "0, ";
- else
- Setr += "1, ";
- if (Attributes & ObjCPropertyDecl::OBJC_PR_copy)
- Setr += "1)";
- else
- Setr += "0)";
- }
- else {
- Setr += getIvarAccessString(OID) + " = ";
- Setr += PD->getName();
- }
- Setr += "; }\n";
- InsertText(startGetterSetterLoc, Setr);
- }
- static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
- std::string &typedefString) {
- typedefString += "#ifndef _REWRITER_typedef_";
- typedefString += ForwardDecl->getNameAsString();
- typedefString += "\n";
- typedefString += "#define _REWRITER_typedef_";
- typedefString += ForwardDecl->getNameAsString();
- typedefString += "\n";
- typedefString += "typedef struct objc_object ";
- typedefString += ForwardDecl->getNameAsString();
- // typedef struct { } _objc_exc_Classname;
- typedefString += ";\ntypedef struct {} _objc_exc_";
- typedefString += ForwardDecl->getNameAsString();
- typedefString += ";\n#endif\n";
- }
- void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
- const std::string &typedefString) {
- SourceLocation startLoc = ClassDecl->getLocStart();
- const char *startBuf = SM->getCharacterData(startLoc);
- const char *semiPtr = strchr(startBuf, ';');
- // Replace the @class with typedefs corresponding to the classes.
- ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
- }
- void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {
- std::string typedefString;
- for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
- ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I);
- if (I == D.begin()) {
- // Translate to typedef's that forward reference structs with the same name
- // as the class. As a convenience, we include the original declaration
- // as a comment.
- typedefString += "// @class ";
- typedefString += ForwardDecl->getNameAsString();
- typedefString += ";\n";
- }
- RewriteOneForwardClassDecl(ForwardDecl, typedefString);
- }
- DeclGroupRef::iterator I = D.begin();
- RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
- }
- void RewriteModernObjC::RewriteForwardClassDecl(
- const llvm::SmallVector<Decl*, 8> &D) {
- std::string typedefString;
- for (unsigned i = 0; i < D.size(); i++) {
- ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
- if (i == 0) {
- typedefString += "// @class ";
- typedefString += ForwardDecl->getNameAsString();
- typedefString += ";\n";
- }
- RewriteOneForwardClassDecl(ForwardDecl, typedefString);
- }
- RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
- }
- void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
- // When method is a synthesized one, such as a getter/setter there is
- // nothing to rewrite.
- if (Method->isImplicit())
- return;
- SourceLocation LocStart = Method->getLocStart();
- SourceLocation LocEnd = Method->getLocEnd();
- if (SM->getExpansionLineNumber(LocEnd) >
- SM->getExpansionLineNumber(LocStart)) {
- InsertText(LocStart, "#if 0\n");
- ReplaceText(LocEnd, 1, ";\n#endif\n");
- } else {
- InsertText(LocStart, "// ");
- }
- }
- void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {
- SourceLocation Loc = prop->getAtLoc();
- ReplaceText(Loc, 0, "// ");
- // FIXME: handle properties that are declared across multiple lines.
- }
- void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
- SourceLocation LocStart = CatDecl->getLocStart();
- // FIXME: handle category headers that are declared across multiple lines.
- if (CatDecl->getIvarRBraceLoc().isValid()) {
- ReplaceText(LocStart, 1, "/** ");
- ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ ");
- }
- else {
- ReplaceText(LocStart, 0, "// ");
- }
-
- for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(),
- E = CatDecl->prop_end(); I != E; ++I)
- RewriteProperty(*I);
-
- for (ObjCCategoryDecl::instmeth_iterator
- I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end();
- I != E; ++I)
- RewriteMethodDeclaration(*I);
- for (ObjCCategoryDecl::classmeth_iterator
- I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end();
- I != E; ++I)
- RewriteMethodDeclaration(*I);
- // Lastly, comment out the @end.
- ReplaceText(CatDecl->getAtEndRange().getBegin(),
- strlen("@end"), "/* @end */");
- }
- void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
- SourceLocation LocStart = PDecl->getLocStart();
- assert(PDecl->isThisDeclarationADefinition());
-
- // FIXME: handle protocol headers that are declared across multiple lines.
- ReplaceText(LocStart, 0, "// ");
- for (ObjCProtocolDecl::instmeth_iterator
- I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
- I != E; ++I)
- RewriteMethodDeclaration(*I);
- for (ObjCProtocolDecl::classmeth_iterator
- I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
- I != E; ++I)
- RewriteMethodDeclaration(*I);
- for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(),
- E = PDecl->prop_end(); I != E; ++I)
- RewriteProperty(*I);
-
- // Lastly, comment out the @end.
- SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
- ReplaceText(LocEnd, strlen("@end"), "/* @end */");
- // Must comment out @optional/@required
- const char *startBuf = SM->getCharacterData(LocStart);
- const char *endBuf = SM->getCharacterData(LocEnd);
- for (const char *p = startBuf; p < endBuf; p++) {
- if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
- SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
- ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
- }
- else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
- SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
- ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
- }
- }
- }
- void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
- SourceLocation LocStart = (*D.begin())->getLocStart();
- if (LocStart.isInvalid())
- llvm_unreachable("Invalid SourceLocation");
- // FIXME: handle forward protocol that are declared across multiple lines.
- ReplaceText(LocStart, 0, "// ");
- }
- void
- RewriteModernObjC::RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG) {
- SourceLocation LocStart = DG[0]->getLocStart();
- if (LocStart.isInvalid())
- llvm_unreachable("Invalid SourceLocation");
- // FIXME: handle forward protocol that are declared across multiple lines.
- ReplaceText(LocStart, 0, "// ");
- }
- void
- RewriteModernObjC::RewriteLinkageSpec(LinkageSpecDecl *LSD) {
- SourceLocation LocStart = LSD->getExternLoc();
- if (LocStart.isInvalid())
- llvm_unreachable("Invalid extern SourceLocation");
-
- ReplaceText(LocStart, 0, "// ");
- if (!LSD->hasBraces())
- return;
- // FIXME. We don't rewrite well if '{' is not on same line as 'extern'.
- SourceLocation LocRBrace = LSD->getRBraceLoc();
- if (LocRBrace.isInvalid())
- llvm_unreachable("Invalid rbrace SourceLocation");
- ReplaceText(LocRBrace, 0, "// ");
- }
- void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
- const FunctionType *&FPRetType) {
- if (T->isObjCQualifiedIdType())
- ResultStr += "id";
- else if (T->isFunctionPointerType() ||
- T->isBlockPointerType()) {
- // needs special handling, since pointer-to-functions have special
- // syntax (where a decaration models use).
- QualType retType = T;
- QualType PointeeTy;
- if (const PointerType* PT = retType->getAs<PointerType>())
- PointeeTy = PT->getPointeeType();
- else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
- PointeeTy = BPT->getPointeeType();
- if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
- ResultStr += FPRetType->getResultType().getAsString(
- Context->getPrintingPolicy());
- ResultStr += "(*";
- }
- } else
- ResultStr += T.getAsString(Context->getPrintingPolicy());
- }
- void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
- ObjCMethodDecl *OMD,
- std::string &ResultStr) {
- //fprintf(stderr,"In RewriteObjCMethodDecl\n");
- const FunctionType *FPRetType = 0;
- ResultStr += "\nstatic ";
- RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType);
- ResultStr += " ";
- // Unique method name
- std::string NameStr;
- if (OMD->isInstanceMethod())
- NameStr += "_I_";
- else
- NameStr += "_C_";
- NameStr += IDecl->getNameAsString();
- NameStr += "_";
- if (ObjCCategoryImplDecl *CID =
- dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
- NameStr += CID->getNameAsString();
- NameStr += "_";
- }
- // Append selector names, replacing ':' with '_'
- {
- std::string selString = OMD->getSelector().getAsString();
- int len = selString.size();
- for (int i = 0; i < len; i++)
- if (selString[i] == ':')
- selString[i] = '_';
- NameStr += selString;
- }
- // Remember this name for metadata emission
- MethodInternalNames[OMD] = NameStr;
- ResultStr += NameStr;
- // Rewrite arguments
- ResultStr += "(";
- // invisible arguments
- if (OMD->isInstanceMethod()) {
- QualType selfTy = Context->getObjCInterfaceType(IDecl);
- selfTy = Context->getPointerType(selfTy);
- if (!LangOpts.MicrosoftExt) {
- if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
- ResultStr += "struct ";
- }
- // When rewriting for Microsoft, explicitly omit the structure name.
- ResultStr += IDecl->getNameAsString();
- ResultStr += " *";
- }
- else
- ResultStr += Context->getObjCClassType().getAsString(
- Context->getPrintingPolicy());
- ResultStr += " self, ";
- ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
- ResultStr += " _cmd";
- // Method arguments.
- for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
- E = OMD->param_end(); PI != E; ++PI) {
- ParmVarDecl *PDecl = *PI;
- ResultStr += ", ";
- if (PDecl->getType()->isObjCQualifiedIdType()) {
- ResultStr += "id ";
- ResultStr += PDecl->getNameAsString();
- } else {
- std::string Name = PDecl->getNameAsString();
- QualType QT = PDecl->getType();
- // Make sure we convert "t (^)(...)" to "t (*)(...)".
- (void)convertBlockPointerToFunctionPointer(QT);
- QT.getAsStringInternal(Name, Context->getPrintingPolicy());
- ResultStr += Name;
- }
- }
- if (OMD->isVariadic())
- ResultStr += "…
Large files files are truncated, but you can click here to view the full file