diff options
author | Steve Naroff <snaroff@apple.com> | 2008-04-14 22:05:54 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2008-04-14 22:05:54 +0000 |
commit | 8beca118bc82fbebaaf00b54a7871549b2ab4f5c (patch) | |
tree | 6c9663552cdca4317c2bf79e5e1897a684e1adba /Driver/RewriteTest.cpp | |
parent | b29b427fa977e8e13ea104d22b193b2cd8a4a52f (diff) |
Rename a file and update the Xcode project.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49693 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Driver/RewriteTest.cpp')
-rw-r--r-- | Driver/RewriteTest.cpp | 2990 |
1 files changed, 0 insertions, 2990 deletions
diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp deleted file mode 100644 index df214a0430..0000000000 --- a/Driver/RewriteTest.cpp +++ /dev/null @@ -1,2990 +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 "ASTConsumers.h" -#include "clang/Rewrite/Rewriter.h" -#include "clang/AST/AST.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Lex/Lexer.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/System/Path.h" -#include <sstream>RewriteObjC -#include <fstream> -using namespace clang; -using llvm::utostr; - -static llvm::cl::opt<bool> -SilenceRewriteMacroWarning("Wno-rewrite-macros", llvm::cl::init(false), - llvm::cl::desc("Silence ObjC rewriting warnings")); - -namespace { - class RewriteObjC : public ASTConsumer { - Rewriter Rewrite; - Diagnostic &Diags; - const LangOptions &LangOpts; - unsigned RewriteFailedDiag; - - ASTContext *Context; - SourceManager *SM; - unsigned MainFileID; - const char *MainFileStart, *MainFileEnd; - SourceLocation LastIncLoc; - - llvm::SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; - llvm::SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; - llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; - llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls; - llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; - llvm::SmallVector<Stmt *, 32> Stmts; - llvm::SmallVector<int, 8> ObjCBcLabelNo; - llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes; - - unsigned NumObjCStringLiterals; - - FunctionDecl *MsgSendFunctionDecl; - FunctionDecl *MsgSendSuperFunctionDecl; - FunctionDecl *MsgSendStretFunctionDecl; - FunctionDecl *MsgSendSuperStretFunctionDecl; - FunctionDecl *MsgSendFpretFunctionDecl; - FunctionDecl *GetClassFunctionDecl; - FunctionDecl *GetMetaClassFunctionDecl; - FunctionDecl *SelGetUidFunctionDecl; - FunctionDecl *CFStringFunctionDecl; - FunctionDecl *GetProtocolFunctionDecl; - FunctionDecl *SuperContructorFunctionDecl; - - // ObjC string constant support. - FileVarDecl *ConstantStringClassReference; - RecordDecl *NSStringRecord; - - // ObjC foreach break/continue generation support. - int BcLabelCount; - - // Needed for super. - ObjCMethodDecl *CurMethodDecl; - RecordDecl *SuperStructDecl; - RecordDecl *ConstantStringDecl; - - // Needed for header files being rewritten - bool IsHeader; - - std::string InFileName; - std::string OutFileName; - - std::string Preamble; - - static const int OBJC_ABI_VERSION =7 ; - public: - void Initialize(ASTContext &context); - - - // Top Level Driver code. - virtual void HandleTopLevelDecl(Decl *D); - void HandleDeclInMainFile(Decl *D); - RewriteObjC(std::string inFile, std::string outFile, - Diagnostic &D, const LangOptions &LOpts); - ~RewriteObjC(); - - void ReplaceStmt(Stmt *Old, Stmt *New) { - // If replacement succeeded or warning disabled return with no warning. - if (!Rewrite.ReplaceStmt(Old, New) || SilenceRewriteMacroWarning) - return; - - SourceRange Range = Old->getSourceRange(); - Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag, - 0, 0, &Range, 1); - } - - void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen, - bool InsertAfter = true) { - // If insertion succeeded or warning disabled return with no warning. - if (!Rewrite.InsertText(Loc, StrData, StrLen, InsertAfter) || - SilenceRewriteMacroWarning) - return; - - Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); - } - - void RemoveText(SourceLocation Loc, unsigned StrLen) { - // If removal succeeded or warning disabled return with no warning. - if (!Rewrite.RemoveText(Loc, StrLen) || SilenceRewriteMacroWarning) - return; - - Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); - } - - void ReplaceText(SourceLocation Start, unsigned OrigLength, - const char *NewStr, unsigned NewLength) { - // If removal succeeded or warning disabled return with no warning. - if (!Rewrite.ReplaceText(Start, OrigLength, NewStr, NewLength) || - SilenceRewriteMacroWarning) - return; - - Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); - } - - // Syntactic Rewriting. - void RewritePrologue(SourceLocation Loc); - void RewriteInclude(); - void RewriteTabs(); - void RewriteForwardClassDecl(ObjCClassDecl *Dcl); - void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); - void RewriteImplementationDecl(NamedDecl *Dcl); - void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr); - void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); - void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); - void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl); - void RewriteMethodDeclaration(ObjCMethodDecl *Method); - void RewriteProperties(unsigned nProperties, ObjCPropertyDecl **Properties); - void RewriteFunctionDecl(FunctionDecl *FD); - void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); - bool needToScanForQualifiers(QualType T); - ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr); - QualType getSuperStructType(); - QualType getConstantStringStructType(); - - // Expression Rewriting. - Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); - Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); - Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV); - Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); - Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); - Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); - Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); - Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); - Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); - Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S); - Stmt *RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S); - Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); - Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, - SourceLocation OrigEnd); - CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, - Expr **args, unsigned nargs); - Stmt *SynthMessageExpr(ObjCMessageExpr *Exp); - Stmt *RewriteBreakStmt(BreakStmt *S); - Stmt *RewriteContinueStmt(ContinueStmt *S); - void SynthCountByEnumWithState(std::string &buf); - - void SynthMsgSendFunctionDecl(); - void SynthMsgSendSuperFunctionDecl(); - void SynthMsgSendStretFunctionDecl(); - void SynthMsgSendFpretFunctionDecl(); - void SynthMsgSendSuperStretFunctionDecl(); - void SynthGetClassFunctionDecl(); - void SynthGetMetaClassFunctionDecl(); - void SynthSelGetUidFunctionDecl(); - void SynthGetProtocolFunctionDecl(); - void SynthSuperContructorFunctionDecl(); - - // Metadata emission. - void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, - std::string &Result); - - void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, - std::string &Result); - - typedef ObjCCategoryImplDecl::instmeth_iterator instmeth_iterator; - void RewriteObjCMethodsMetaData(instmeth_iterator MethodBegin, - instmeth_iterator MethodEnd, - bool IsInstanceMethod, - const char *prefix, - const char *ClassName, - std::string &Result); - - void RewriteObjCProtocolsMetaData(ObjCProtocolDecl **Protocols, - int NumProtocols, - const char *prefix, - const char *ClassName, - std::string &Result); - void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, - std::string &Result); - void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, - ObjCIvarDecl *ivar, - std::string &Result); - void RewriteImplementations(std::string &Result); - }; -} - -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, std::string outFile, - Diagnostic &D, const LangOptions &LOpts) - : Diags(D), LangOpts(LOpts) { - IsHeader = IsHeaderFile(inFile); - InFileName = inFile; - OutFileName = outFile; - RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, - "rewriting sub-expression within a macro (may not be correct)"); -} - -ASTConsumer *clang::CreateCodeRewriterTest(const std::string& InFile, - const std::string& OutFile, - Diagnostic &Diags, - const LangOptions &LOpts) { - return new RewriteObjC(InFile, OutFile, Diags, LOpts); -} - -void RewriteObjC::Initialize(ASTContext &context) { - Context = &context; - SM = &Context->getSourceManager(); - MsgSendFunctionDecl = 0; - MsgSendSuperFunctionDecl = 0; - MsgSendStretFunctionDecl = 0; - MsgSendSuperStretFunctionDecl = 0; - MsgSendFpretFunctionDecl = 0; - GetClassFunctionDecl = 0; - GetMetaClassFunctionDecl = 0; - SelGetUidFunctionDecl = 0; - CFStringFunctionDecl = 0; - GetProtocolFunctionDecl = 0; - ConstantStringClassReference = 0; - NSStringRecord = 0; - CurMethodDecl = 0; - SuperStructDecl = 0; - ConstantStringDecl = 0; - BcLabelCount = 0; - SuperContructorFunctionDecl = 0; - NumObjCStringLiterals = 0; - - // 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()); - - // declaring objc_selector outside the parameter list removes a silly - // scope related warning... - if (IsHeader) - Preamble = "#pragma once\n"; - Preamble += "struct objc_selector; struct objc_class;\n"; - Preamble += "#ifndef OBJC_SUPER\n"; - Preamble += "struct objc_super { struct objc_object *object; "; - Preamble += "struct objc_object *superClass; "; - if (LangOpts.Microsoft) { - // Add a constructor for creating temporary objects. - Preamble += "objc_super(struct objc_object *o, struct objc_object *s) : "; - Preamble += "object(o), superClass(s) {} "; - } - Preamble += "};\n"; - Preamble += "#define OBJC_SUPER\n"; - Preamble += "#endif\n"; - Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; - Preamble += "typedef struct objc_object Protocol;\n"; - Preamble += "#define _REWRITER_typedef_Protocol\n"; - Preamble += "#endif\n"; - if (LangOpts.Microsoft) - Preamble += "extern \"C\" {\n"; - Preamble += "struct objc_object *objc_msgSend"; - Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; - Preamble += "extern struct objc_object *objc_msgSendSuper"; - Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; - Preamble += "extern struct objc_object *objc_msgSend_stret"; - Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; - Preamble += "extern struct objc_object *objc_msgSendSuper_stret"; - Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; - Preamble += "extern struct objc_object *objc_msgSend_fpret"; - Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; - Preamble += "struct objc_object *objc_getClass"; - Preamble += "(const char *);\n"; - Preamble += "extern struct objc_object *objc_getMetaClass"; - Preamble += "(const char *);\n"; - Preamble += "extern void objc_exception_throw(struct objc_object *);\n"; - Preamble += "extern void objc_exception_try_enter(void *);\n"; - Preamble += "extern void objc_exception_try_exit(void *);\n"; - Preamble += "extern struct objc_object *objc_exception_extract(void *);\n"; - Preamble += "extern int objc_exception_match"; - Preamble += "(struct objc_class *, struct objc_object *, ...);\n"; - Preamble += "extern Protocol *objc_getProtocol(const char *);\n"; - if (LangOpts.Microsoft) - Preamble += "} // end extern \"C\"\n"; - Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; - Preamble += "struct __objcFastEnumerationState {\n\t"; - Preamble += "unsigned long state;\n\t"; - Preamble += "void **itemsPtr;\n\t"; - Preamble += "unsigned long *mutationsPtr;\n\t"; - Preamble += "unsigned long extra[5];\n};\n"; - Preamble += "#define __FASTENUMERATIONSTATE\n"; - Preamble += "#endif\n"; - Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; - Preamble += "struct __NSConstantStringImpl {\n"; - Preamble += " int *isa;\n"; - Preamble += " int flags;\n"; - Preamble += " char *str;\n"; - Preamble += " long length;\n"; - Preamble += "};\n"; - Preamble += "extern int __CFConstantStringClassReference[];\n"; - Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; - Preamble += "#endif\n"; - if (LangOpts.Microsoft) - Preamble += "#define __attribute__(X)\n"; -} - - -//===----------------------------------------------------------------------===// -// Top Level Driver Code -//===----------------------------------------------------------------------===// - -void RewriteObjC::HandleTopLevelDecl(Decl *D) { - // 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->getLogicalLoc(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 (FileVarDecl *FVD = dyn_cast<FileVarDecl>(D)) { - // declared in <Foundation/NSString.h> - if (strcmp(FVD->getName(), "_NSConstantStringClassReference") == 0) { - ConstantStringClassReference = FVD; - return; - } - } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) { - RewriteInterfaceDecl(MD); - } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { - RewriteCategoryDecl(CD); - } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { - RewriteProtocolDecl(PD); - } else if (ObjCForwardProtocolDecl *FP = - dyn_cast<ObjCForwardProtocolDecl>(D)){ - RewriteForwardProtocolDecl(FP); - } - // If we have a decl in the main file, see if we should rewrite it. - if (SM->isFromMainFile(Loc)) - return HandleDeclInMainFile(D); -} - -/// HandleDeclInMainFile - This is called for each top-level decl defined in the -/// main file of the input. -void RewriteObjC::HandleDeclInMainFile(Decl *D) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - if (Stmt *Body = FD->getBody()) - FD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body)); - - if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { - if (Stmt *Body = MD->getBody()) { - //Body->dump(); - CurMethodDecl = MD; - MD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body)); - CurMethodDecl = 0; - } - } - if (ObjCImplementationDecl *CI = dyn_cast<ObjCImplementationDecl>(D)) - ClassImplementation.push_back(CI); - else if (ObjCCategoryImplDecl *CI = dyn_cast<ObjCCategoryImplDecl>(D)) - CategoryImplementation.push_back(CI); - else if (ObjCClassDecl *CD = dyn_cast<ObjCClassDecl>(D)) - RewriteForwardClassDecl(CD); - else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - RewriteObjCQualifiedInterfaceTypes(VD); - if (VD->getInit()) - RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); - } - // Nothing yet. -} - -RewriteObjC::~RewriteObjC() { - // Get the top-level buffer that this corresponds to. - - // Rewrite tabs if we care. - //RewriteTabs(); - - if (Diags.hasErrorOccurred()) - return; - - // Create the output file. - - std::ostream *OutFile; - if (OutFileName == "-") { - OutFile = llvm::cout.stream(); - } else if (!OutFileName.empty()) { - OutFile = new std::ofstream(OutFileName.c_str(), - std::ios_base::binary|std::ios_base::out); - } else if (InFileName == "-") { - OutFile = llvm::cout.stream(); - } else { - llvm::sys::Path Path(InFileName); - Path.eraseSuffix(); - Path.appendSuffix("cpp"); - OutFile = new std::ofstream(Path.toString().c_str(), - std::ios_base::binary|std::ios_base::out); - } - - RewriteInclude(); - - InsertText(SourceLocation::getFileLoc(MainFileID, 0), - Preamble.c_str(), Preamble.size(), false); - - // Rewrite Objective-c meta data* - std::string ResultStr; - RewriteImplementations(ResultStr); - - // Get the buffer corresponding to MainFileID. If we haven't changed it, then - // we are done. - if (const RewriteBuffer *RewriteBuf = - Rewrite.getRewriteBufferFor(MainFileID)) { - //printf("Changed:\n"); - *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); - } else { - fprintf(stderr, "No changes\n"); - } - // Emit metadata. - *OutFile << ResultStr; -} - -//===----------------------------------------------------------------------===// -// Syntactic (non-AST) Rewriting Code -//===----------------------------------------------------------------------===// - -void RewriteObjC::RewriteInclude() { - SourceLocation LocStart = SourceLocation::getFileLoc(MainFileID, 0); - std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID); - const char *MainBufStart = MainBuf.first; - const char *MainBufEnd = MainBuf.second; - size_t ImportLen = strlen("import"); - size_t IncludeLen = strlen("include"); - - // 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.getFileLocWithOffset(BufPtr-MainBufStart); - ReplaceText(ImportLoc, ImportLen, "include", IncludeLen); - BufPtr += ImportLen; - } - } - } -} - -void RewriteObjC::RewriteTabs() { - std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID); - const char *MainBufStart = MainBuf.first; - const char *MainBufEnd = MainBuf.second; - - // Loop over the whole file, looking for tabs. - for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) { - if (*BufPtr != '\t') - continue; - - // Okay, we found a tab. This tab will turn into at least one character, - // but it depends on which 'virtual column' it is in. Compute that now. - unsigned VCol = 0; - while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' && - BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r') - ++VCol; - - // Okay, now that we know the virtual column, we know how many spaces to - // insert. We assume 8-character tab-stops. - unsigned Spaces = 8-(VCol & 7); - - // Get the location of the tab. - SourceLocation TabLoc = - SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart); - - // Rewrite the single tab character into a sequence of spaces. - ReplaceText(TabLoc, 1, " ", Spaces); - } -} - - -void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { - int numDecls = ClassDecl->getNumForwardDecls(); - ObjCInterfaceDecl **ForwardDecls = ClassDecl->getForwardDecls(); - - // Get the start location and compute the semi location. - SourceLocation startLoc = ClassDecl->getLocation(); - const char *startBuf = SM->getCharacterData(startLoc); - const char *semiPtr = strchr(startBuf, ';'); - - // 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. - std::string typedefString; - typedefString += "// "; - typedefString.append(startBuf, semiPtr-startBuf+1); - typedefString += "\n"; - for (int i = 0; i < numDecls; i++) { - ObjCInterfaceDecl *ForwardDecl = ForwardDecls[i]; - typedefString += "#ifndef _REWRITER_typedef_"; - typedefString += ForwardDecl->getName(); - typedefString += "\n"; - typedefString += "#define _REWRITER_typedef_"; - typedefString += ForwardDecl->getName(); - typedefString += "\n"; - typedefString += "typedef struct objc_object "; - typedefString += ForwardDecl->getName(); - typedefString += ";\n#endif\n"; - } - - // Replace the @class with typedefs corresponding to the classes. - ReplaceText(startLoc, semiPtr-startBuf+1, - typedefString.c_str(), typedefString.size()); -} - -void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { - SourceLocation LocStart = Method->getLocStart(); - SourceLocation LocEnd = Method->getLocEnd(); - - if (SM->getLineNumber(LocEnd) > SM->getLineNumber(LocStart)) { - InsertText(LocStart, "/* ", 3); - ReplaceText(LocEnd, 1, ";*/ ", 4); - } else { - InsertText(LocStart, "// ", 3); - } -} - -void RewriteObjC::RewriteProperties(unsigned nProperties, ObjCPropertyDecl **Properties) -{ - for (unsigned i = 0; i < nProperties; i++) { - ObjCPropertyDecl *Property = Properties[i]; - SourceLocation Loc = Property->getLocation(); - - ReplaceText(Loc, 0, "// ", 3); - - // FIXME: handle properties that are declared across multiple lines. - } -} - -void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { - SourceLocation LocStart = CatDecl->getLocStart(); - - // FIXME: handle category headers that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); - - 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->getAtEndLoc(), 0, "// ", 3); -} - -void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { - std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID); - - SourceLocation LocStart = PDecl->getLocStart(); - - // FIXME: handle protocol headers that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); - - 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); - - // Lastly, comment out the @end. - SourceLocation LocEnd = PDecl->getAtEndLoc(); - ReplaceText(LocEnd, 0, "// ", 3); - - // 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"))) { - std::string CommentedOptional = "/* @optional */"; - SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); - ReplaceText(OptionalLoc, strlen("@optional"), - CommentedOptional.c_str(), CommentedOptional.size()); - - } - else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { - std::string CommentedRequired = "/* @required */"; - SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); - ReplaceText(OptionalLoc, strlen("@required"), - CommentedRequired.c_str(), CommentedRequired.size()); - - } - } -} - -void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) { - SourceLocation LocStart = PDecl->getLocation(); - if (LocStart.isInvalid()) - assert(false && "Invalid SourceLocation"); - // FIXME: handle forward protocol that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); -} - -void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, - std::string &ResultStr) { - ResultStr += "\nstatic "; - if (OMD->getResultType()->isObjCQualifiedIdType()) - ResultStr += "id"; - else - ResultStr += OMD->getResultType().getAsString(); - ResultStr += " "; - - // Unique method name - std::string NameStr; - - if (OMD->isInstance()) - NameStr += "_I_"; - else - NameStr += "_C_"; - - NameStr += OMD->getClassInterface()->getName(); - NameStr += "_"; - - NamedDecl *MethodContext = OMD->getMethodContext(); - if (ObjCCategoryImplDecl *CID = - dyn_cast<ObjCCategoryImplDecl>(MethodContext)) { - NameStr += CID->getName(); - NameStr += "_"; - } - // Append selector names, replacing ':' with '_' - if (OMD->getSelector().getName().find(':') == std::string::npos) - NameStr += OMD->getSelector().getName(); - else { - std::string selString = OMD->getSelector().getName(); - 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->isInstance()) { - QualType selfTy = Context->getObjCInterfaceType(OMD->getClassInterface()); - selfTy = Context->getPointerType(selfTy); - if (!LangOpts.Microsoft) { - if (ObjCSynthesizedStructs.count(OMD->getClassInterface())) - ResultStr += "struct "; - } - // When rewriting for Microsoft, explicitly omit the structure name. - ResultStr += OMD->getClassInterface()->getName(); - ResultStr += " *"; - } - else - ResultStr += Context->getObjCIdType().getAsString(); - - ResultStr += " self, "; - ResultStr += Context->getObjCSelType().getAsString(); - ResultStr += " _cmd"; - - // Method arguments. - for (unsigned i = 0; i < OMD->getNumParams(); i++) { - ParmVarDecl *PDecl = OMD->getParamDecl(i); - ResultStr += ", "; - if (PDecl->getType()->isObjCQualifiedIdType()) - ResultStr += "id"; - else - ResultStr += PDecl->getType().getAsString(); - ResultStr += " "; - ResultStr += PDecl->getName(); - } - if (OMD->isVariadic()) - ResultStr += ", ..."; - ResultStr += ") "; - -} -void RewriteObjC::RewriteImplementationDecl(NamedDecl *OID) { - ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); - ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); - - if (IMD) - InsertText(IMD->getLocStart(), "// ", 3); - else - InsertText(CID->getLocStart(), "// ", 3); - - for (ObjCCategoryImplDecl::instmeth_iterator - I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), - E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); I != E; ++I) { - std::string ResultStr; - ObjCMethodDecl *OMD = *I; - RewriteObjCMethodDecl(OMD, ResultStr); - SourceLocation LocStart = OMD->getLocStart(); - SourceLocation LocEnd = OMD->getBody()->getLocStart(); - - const char *startBuf = SM->getCharacterData(LocStart); - const char *endBuf = SM->getCharacterData(LocEnd); - ReplaceText(LocStart, endBuf-startBuf, - ResultStr.c_str(), ResultStr.size()); - } - - for (ObjCCategoryImplDecl::classmeth_iterator - I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), - E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); I != E; ++I) { - std::string ResultStr; - ObjCMethodDecl *OMD = *I; - RewriteObjCMethodDecl(OMD, ResultStr); - SourceLocation LocStart = OMD->getLocStart(); - SourceLocation LocEnd = OMD->getBody()->getLocStart(); - - const char *startBuf = SM->getCharacterData(LocStart); - const char *endBuf = SM->getCharacterData(LocEnd); - ReplaceText(LocStart, endBuf-startBuf, - ResultStr.c_str(), ResultStr.size()); - } - if (IMD) - InsertText(IMD->getLocEnd(), "// ", 3); - else - InsertText(CID->getLocEnd(), "// ", 3); -} - -void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { - std::string ResultStr; - if (!ObjCForwardDecls.count(ClassDecl)) { - // we haven't seen a forward decl - generate a typedef. - ResultStr = "#ifndef _REWRITER_typedef_"; - ResultStr += ClassDecl->getName(); - ResultStr += "\n"; - ResultStr += "#define _REWRITER_typedef_"; - ResultStr += ClassDecl->getName(); - ResultStr += "\n"; - ResultStr += "typedef struct objc_object "; - ResultStr += ClassDecl->getName(); - ResultStr += ";\n#endif\n"; - // Mark this typedef as having been generated. - ObjCForwardDecls.insert(ClassDecl); - } - SynthesizeObjCInternalStruct(ClassDecl, ResultStr); - - RewriteProperties(ClassDecl->getNumPropertyDecl(), - ClassDecl->getPropertyDecl()); - for (ObjCInterfaceDecl::instmeth_iterator I = ClassDecl->instmeth_begin(), - E = ClassDecl->instmeth_end(); I != E; ++I) - RewriteMethodDeclaration(*I); - for (ObjCInterfaceDecl::classmeth_iterator I = ClassDecl->classmeth_begin(), - E = ClassDecl->classmeth_end(); I != E; ++I) - RewriteMethodDeclaration(*I); - - // Lastly, comment out the @end. - ReplaceText(ClassDecl->getAtEndLoc(), 0, "// ", 3); -} - -Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { - ObjCIvarDecl *D = IV->getDecl(); - if (CurMethodDecl) { - if (const PointerType *pType = IV->getBase()->getType()->getAsPointerType()) { - ObjCInterfaceType *intT = dyn_cast<ObjCInterfaceType>(pType->getPointeeType()); - if (CurMethodDecl->getClassInterface() == intT->getDecl()) { - // lookup which class implements the instance variable. - ObjCInterfaceDecl *clsDeclared = 0; - intT->getDecl()->lookupInstanceVariable(D->getIdentifier(), clsDeclared); - assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); - - // Synthesize an explicit cast to gain access to the ivar. - std::string RecName = clsDeclared->getIdentifier()->getName(); - RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName.c_str()); - RecordDecl *RD = RecordDecl::Create(*Context, Decl::Struct, NULL, - SourceLocation(), II, 0); - assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); - QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); - CastExpr *castExpr = new CastExpr(castT, IV->getBase(), SourceLocation()); - // Don't forget the parens to enforce the proper binding. - ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), castExpr); - if (IV->isFreeIvar()) { - MemberExpr *ME = new MemberExpr(PE, true, D, IV->getLocation(), D->getType()); - ReplaceStmt(IV, ME); - delete IV; - return ME; - } else { - ReplaceStmt(IV->getBase(), PE); - // Cannot delete IV->getBase(), since PE points to it. - // Replace the old base with the cast. This is important when doing - // embedded rewrites. For example, [newInv->_container addObject:0]. - IV->setBase(PE); - return IV; - } - } - } - } - // FIXME: Implement public ivar access from a function. - Expr *Replacement = new MemberExpr(IV->getBase(), true, D, - IV->getLocation(), D->getType()); - ReplaceStmt(IV, Replacement); - delete IV; - return Replacement; -} - -//===----------------------------------------------------------------------===// -// Function Body / Expression rewriting -//===----------------------------------------------------------------------===// - -Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { - if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || - isa<DoStmt>(S) || isa<ForStmt>(S)) - Stmts.push_back(S); - else if (isa<ObjCForCollectionStmt>(S)) { - Stmts.push_back(S); - ObjCBcLabelNo.push_back(++BcLabelCount); - } - - SourceLocation OrigStmtEnd = S->getLocEnd(); - - // Start by rewriting all children. - for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); - CI != E; ++CI) - if (*CI) { - Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(*CI); - if (newStmt) - *CI = newStmt; - } - - // Handle specific things. - if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) - return RewriteAtEncode(AtEncode); - - if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) - return RewriteObjCIvarRefExpr(IvarRefExpr); - - if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) - return RewriteAtSelector(AtSelector); - - if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) - return RewriteObjCStringLiteral(AtString); - - if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { - // Before we rewrite it, put the original message expression in a comment. - SourceLocation startLoc = MessExpr->getLocStart(); - SourceLocation endLoc = MessExpr->getLocEnd(); - - const char *startBuf = SM->getCharacterData(startLoc); - const char *endBuf = SM->getCharacterData(endLoc); - - std::string messString; - messString += "// "; - messString.append(startBuf, endBuf-startBuf+1); - messString += "\n"; - - // FIXME: Missing definition of - // InsertText(clang::SourceLocation, char const*, unsigned int). - // InsertText(startLoc, messString.c_str(), messString.size()); - // Tried this, but it didn't work either... - // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); - return RewriteMessageExpr(MessExpr); - } - - if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) - return RewriteObjCTryStmt(StmtTry); - - if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) - return RewriteObjCSynchronizedStmt(StmtTry); - - if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) - return RewriteObjCThrowStmt(StmtThrow); - - if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) - return RewriteObjCProtocolExpr(ProtocolExp); - - if (ObjCForCollectionStmt *StmtForCollection = - dyn_cast<ObjCForCollectionStmt>(S)) - return RewriteObjCForCollectionStmt(StmtForCollection, OrigStmtEnd); - if (BreakStmt *StmtBreakStmt = - dyn_cast<BreakStmt>(S)) - return RewriteBreakStmt(StmtBreakStmt); - if (ContinueStmt *StmtContinueStmt = - dyn_cast<ContinueStmt>(S)) - return RewriteContinueStmt(StmtContinueStmt); - - if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || - isa<DoStmt>(S) || isa<ForStmt>(S)) { - assert(!Stmts.empty() && "Statement stack is empty"); - assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || - isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) - && "Statement stack mismatch"); - Stmts.pop_back();< |