aboutsummaryrefslogtreecommitdiff
path: root/lib/Rewrite/RewriteObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Rewrite/RewriteObjC.cpp')
-rw-r--r--lib/Rewrite/RewriteObjC.cpp6028
1 files changed, 0 insertions, 6028 deletions
diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp
deleted file mode 100644
index 37f58aa0e9..0000000000
--- a/lib/Rewrite/RewriteObjC.cpp
+++ /dev/null
@@ -1,6028 +0,0 @@
-//===--- 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 RewriteObjC : 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;
- unsigned RewriteFailedDiag;
- // 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;
- FunctionDecl *CurFunctionDeclToDeclareForBlock;
-
- /* 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> ObjCForwardDecls;
- llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
- 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;
-
- // 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 {
- RewriteObjC &R;
- bool SavedValue;
-
- public:
- DisableReplaceStmtScope(RewriteObjC &R)
- : R(R), SavedValue(R.DisableReplaceStmt) {
- R.DisableReplaceStmt = true;
- }
- ~DisableReplaceStmtScope() {
- R.DisableReplaceStmt = SavedValue;
- }
- };
- void InitializeCommon(ASTContext &context);
-
- public:
-
- // 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;
- }
- }
-
- 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);
- RewriteObjC(std::string inFile, raw_ostream *OS,
- DiagnosticsEngine &D, const LangOptions &LOpts,
- bool silenceMacroWarn);
-
- ~RewriteObjC() {}
-
- 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);
-
- // 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 *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
- void RewriteTryReturnStmts(Stmt *S);
- void RewriteSyncReturnStmts(Stmt *S, std::string buf);
- Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *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);
-
- // Block rewriting.
- void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
-
- // Block specific rewrite rules.
- void RewriteBlockPointerDecl(NamedDecl *VD);
- void RewriteByRefVar(VarDecl *VD);
- Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
- Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
- void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
-
- void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
- std::string &Result);
-
- virtual void Initialize(ASTContext &context) = 0;
-
- // Metadata Rewriting.
- virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;
- virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result) = 0;
- virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
- std::string &Result) = 0;
- virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result) = 0;
- virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
- std::string &Result) = 0;
-
- // Rewriting ivar access
- virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;
- virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
- std::string &Result) = 0;
-
- // 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());
- CallExpr *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();
-
- 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 HasReturnStmts(Stmt *S, bool &hasReturns);
- 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 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())
- T = 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());
- }
- };
-
- class RewriteObjCFragileABI : public RewriteObjC {
- public:
-
- RewriteObjCFragileABI(std::string inFile, raw_ostream *OS,
- DiagnosticsEngine &D, const LangOptions &LOpts,
- bool silenceMacroWarn) : RewriteObjC(inFile, OS,
- D, LOpts,
- silenceMacroWarn) {}
-
- ~RewriteObjCFragileABI() {}
- virtual void Initialize(ASTContext &context);
-
- // Rewriting metadata
- template<typename MethodIterator>
- void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
- MethodIterator MethodEnd,
- bool IsInstanceMethod,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result);
- virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
- StringRef prefix,
- StringRef ClassName,
- std::string &Result);
- virtual void RewriteObjCProtocolListMetaData(
- const ObjCList<ObjCProtocolDecl> &Prots,
- StringRef prefix, StringRef ClassName, std::string &Result);
- virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
- std::string &Result);
- virtual void RewriteMetaDataIntoBuffer(std::string &Result);
- virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
- std::string &Result);
-
- // Rewriting ivar
- virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
- std::string &Result);
- virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
- };
-}
-
-void RewriteObjC::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 RewriteObjC::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";
-}
-
-RewriteObjC::RewriteObjC(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)");
- TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
- DiagnosticsEngine::Warning,
- "rewriter doesn't support user-specified control flow semantics "
- "for @try/@finally (code may not execute properly)");
-}
-
-ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile,
- raw_ostream* OS,
- DiagnosticsEngine &Diags,
- const LangOptions &LOpts,
- bool SilenceRewriteMacroWarning) {
- return new RewriteObjCFragileABI(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
-}
-
-void RewriteObjC::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;
- CurFunctionDeclToDeclareForBlock = 0;
- GlobalVarDecl = 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 RewriteObjC::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 (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
- if (ID->isThisDeclarationADefinition())
- RewriteInterfaceDecl(ID);
- } 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)) {
- // 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;
- }
- }
-
- 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 RewriteObjC::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 std::string getIvarAccessString(ObjCIvarDecl *OID) {
- const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface();
- std::string S;
- S = "((struct ";
- S += ClassDecl->getIdentifier()->getName();
- S += "_IMPL *)self)->";
- S += OID->getName();
- return S;
-}
-
-void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
- ObjCImplementationDecl *IMD,
- ObjCCategoryImplDecl *CID) {
- static bool objcGetPropertyDefined = false;
- static bool objcSetPropertyDefined = false;
- 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 ';'");
- SourceLocation onePastSemiLoc =
- startLoc.getLocWithOffset(semiBuf-startBuf+1);
-
- 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 (!PD->getGetterMethodDecl()->isDefined()) {
- 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(onePastSemiLoc, Getr);
- }
-
- if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined())
- 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 += "; }";
- InsertText(onePastSemiLoc, 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();
- typedefString += ";\n#endif\n";
-}
-
-void RewriteObjC::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 RewriteObjC::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 RewriteObjC::RewriteForwardClassDecl(
- const llvm::SmallVector<Decl*, 8> &D) {
- std::string typedefString;
- for (unsigned i = 0; i < D.size(); i++) {
- ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>