aboutsummaryrefslogtreecommitdiff
path: root/Driver/RewriteTest.cpp
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2008-04-14 22:05:54 +0000
committerSteve Naroff <snaroff@apple.com>2008-04-14 22:05:54 +0000
commit8beca118bc82fbebaaf00b54a7871549b2ab4f5c (patch)
tree6c9663552cdca4317c2bf79e5e1897a684e1adba /Driver/RewriteTest.cpp
parentb29b427fa977e8e13ea104d22b193b2cd8a4a52f (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.cpp2990
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();<