2008-04-15 06:03:09 +08:00
|
|
|
//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
|
2007-10-11 08:43:27 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-10-11 08:43:27 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Hacks and fun related to the code rewriter.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-06-16 01:48:49 +08:00
|
|
|
#include "clang/Rewrite/ASTConsumers.h"
|
2007-10-12 02:38:32 +08:00
|
|
|
#include "clang/Rewrite/Rewriter.h"
|
2007-10-11 08:43:27 +08:00
|
|
|
#include "clang/AST/AST.h"
|
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2008-12-09 00:43:47 +08:00
|
|
|
#include "clang/AST/ParentMap.h"
|
2007-10-12 02:38:32 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2007-10-24 07:50:29 +08:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
2007-12-01 06:53:43 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2007-12-02 09:13:47 +08:00
|
|
|
#include "clang/Lex/Lexer.h"
|
2009-08-23 20:08:50 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2007-10-26 01:07:24 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2007-10-27 03:46:17 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2008-09-13 13:16:45 +08:00
|
|
|
#include "llvm/ADT/OwningPtr.h"
|
2010-01-06 02:04:40 +08:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2010-03-02 07:36:21 +08:00
|
|
|
|
2007-10-11 08:43:27 +08:00
|
|
|
using namespace clang;
|
2007-10-26 01:07:24 +08:00
|
|
|
using llvm::utostr;
|
2007-10-11 08:43:27 +08:00
|
|
|
|
|
|
|
namespace {
|
2008-04-15 06:03:09 +08:00
|
|
|
class RewriteObjC : public ASTConsumer {
|
2011-12-09 02:25:15 +08:00
|
|
|
protected:
|
|
|
|
|
2009-12-24 05:18:41 +08:00
|
|
|
enum {
|
2010-11-22 18:26:41 +08:00
|
|
|
BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
|
2009-12-24 05:18:41 +08:00
|
|
|
block, ... */
|
|
|
|
BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
|
|
|
|
BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
|
|
|
|
__block variable */
|
2010-11-22 18:26:41 +08:00
|
|
|
BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
|
2009-12-24 05:18:41 +08:00
|
|
|
helpers */
|
2010-11-22 18:26:41 +08:00
|
|
|
BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
|
2009-12-24 05:18:41 +08:00
|
|
|
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)
|
|
|
|
};
|
2011-12-06 02:43:13 +08:00
|
|
|
static const int OBJC_ABI_VERSION = 7;
|
2011-12-09 02:25:15 +08:00
|
|
|
|
2007-10-17 05:07:07 +08:00
|
|
|
Rewriter Rewrite;
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags;
|
2008-03-11 04:43:59 +08:00
|
|
|
const LangOptions &LangOpts;
|
2007-10-18 06:35:30 +08:00
|
|
|
ASTContext *Context;
|
2007-10-11 08:43:27 +08:00
|
|
|
SourceManager *SM;
|
2008-04-17 22:40:12 +08:00
|
|
|
TranslationUnitDecl *TUDecl;
|
2009-01-17 14:22:33 +08:00
|
|
|
FileID MainFileID;
|
2007-12-02 09:13:47 +08:00
|
|
|
const char *MainFileStart, *MainFileEnd;
|
2011-12-06 02:43:13 +08:00
|
|
|
Stmt *CurrentBody;
|
|
|
|
ParentMap *PropParentMap; // created lazily.
|
2011-12-06 03:50:04 +08:00
|
|
|
std::string InFileName;
|
|
|
|
raw_ostream* OutFile;
|
|
|
|
std::string Preamble;
|
2010-01-06 02:04:40 +08:00
|
|
|
|
2011-12-06 03:50:04 +08:00
|
|
|
TypeDecl *ProtocolTypeDecl;
|
|
|
|
VarDecl *GlobalVarDecl;
|
|
|
|
unsigned RewriteFailedDiag;
|
|
|
|
// ObjC string constant support.
|
2008-03-15 08:55:56 +08:00
|
|
|
unsigned NumObjCStringLiterals;
|
2011-12-06 03:50:04 +08:00
|
|
|
VarDecl *ConstantStringClassReference;
|
|
|
|
RecordDecl *NSStringRecord;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-06 03:50:04 +08:00
|
|
|
// ObjC foreach break/continue generation support.
|
|
|
|
int BcLabelCount;
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
unsigned TryFinallyContainsReturnDiag;
|
2011-12-06 03:50:04 +08:00
|
|
|
// Needed for super.
|
|
|
|
ObjCMethodDecl *CurMethodDef;
|
|
|
|
RecordDecl *SuperStructDecl;
|
|
|
|
RecordDecl *ConstantStringDecl;
|
|
|
|
|
2007-10-24 07:50:29 +08:00
|
|
|
FunctionDecl *MsgSendFunctionDecl;
|
2007-11-15 18:28:18 +08:00
|
|
|
FunctionDecl *MsgSendSuperFunctionDecl;
|
2007-12-04 03:17:29 +08:00
|
|
|
FunctionDecl *MsgSendStretFunctionDecl;
|
|
|
|
FunctionDecl *MsgSendSuperStretFunctionDecl;
|
2007-12-04 05:26:48 +08:00
|
|
|
FunctionDecl *MsgSendFpretFunctionDecl;
|
2007-10-24 07:50:29 +08:00
|
|
|
FunctionDecl *GetClassFunctionDecl;
|
2007-12-07 11:50:46 +08:00
|
|
|
FunctionDecl *GetMetaClassFunctionDecl;
|
2010-03-11 05:17:41 +08:00
|
|
|
FunctionDecl *GetSuperClassFunctionDecl;
|
2007-10-25 06:48:43 +08:00
|
|
|
FunctionDecl *SelGetUidFunctionDecl;
|
2007-11-08 22:30:50 +08:00
|
|
|
FunctionDecl *CFStringFunctionDecl;
|
2008-03-12 01:37:02 +08:00
|
|
|
FunctionDecl *SuperContructorFunctionDecl;
|
2011-12-06 03:50:04 +08:00
|
|
|
FunctionDecl *CurFunctionDef;
|
|
|
|
FunctionDecl *CurFunctionDeclToDeclareForBlock;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-06 03:50:04 +08:00
|
|
|
/* 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;
|
2008-10-28 01:20:55 +08:00
|
|
|
|
|
|
|
// Block expressions.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<BlockExpr *, 32> Blocks;
|
|
|
|
SmallVector<int, 32> InnerDeclRefsCount;
|
|
|
|
SmallVector<BlockDeclRefExpr *, 32> InnerDeclRefs;
|
2010-02-25 06:48:18 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
// Block related declarations.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ValueDecl *, 8> BlockByCopyDecls;
|
2010-02-12 07:35:57 +08:00
|
|
|
llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ValueDecl *, 8> BlockByRefDecls;
|
2010-02-12 07:35:57 +08:00
|
|
|
llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
|
2010-01-15 07:05:52 +08:00
|
|
|
llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
|
2008-10-28 01:20:55 +08:00
|
|
|
llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
|
2010-03-12 02:20:03 +08:00
|
|
|
llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
|
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
|
|
|
|
|
2008-12-05 07:50:32 +08:00
|
|
|
// 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;
|
2008-12-03 08:56:33 +08:00
|
|
|
|
2011-12-06 03:50:04 +08:00
|
|
|
// Needed for header files being rewritten
|
|
|
|
bool IsHeader;
|
|
|
|
bool SilenceRewriteMacroWarning;
|
|
|
|
bool objc_impl_method;
|
|
|
|
|
2008-12-09 20:56:34 +08:00
|
|
|
bool DisableReplaceStmt;
|
2011-11-06 17:01:30 +08:00
|
|
|
class DisableReplaceStmtScope {
|
|
|
|
RewriteObjC &R;
|
|
|
|
bool SavedValue;
|
2011-12-06 02:43:13 +08:00
|
|
|
|
2011-11-06 17:01:30 +08:00
|
|
|
public:
|
|
|
|
DisableReplaceStmtScope(RewriteObjC &R)
|
|
|
|
: R(R), SavedValue(R.DisableReplaceStmt) {
|
|
|
|
R.DisableReplaceStmt = true;
|
|
|
|
}
|
|
|
|
~DisableReplaceStmtScope() {
|
|
|
|
R.DisableReplaceStmt = SavedValue;
|
|
|
|
}
|
|
|
|
};
|
2011-12-09 02:25:15 +08:00
|
|
|
void InitializeCommon(ASTContext &context);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-11 08:43:27 +08:00
|
|
|
public:
|
2008-06-01 04:11:04 +08:00
|
|
|
|
2007-10-25 01:06:59 +08:00
|
|
|
// Top Level Driver code.
|
2011-11-18 08:26:59 +08:00
|
|
|
virtual bool HandleTopLevelDecl(DeclGroupRef D) {
|
2011-08-28 04:50:59 +08:00
|
|
|
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
|
2011-12-28 06:43:10 +08:00
|
|
|
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
|
|
|
|
if (!Class->isThisDeclarationADefinition()) {
|
|
|
|
RewriteForwardClassDecl(D);
|
|
|
|
break;
|
|
|
|
}
|
2011-08-28 04:50:59 +08:00
|
|
|
}
|
2011-12-28 06:43:10 +08:00
|
|
|
|
2012-01-02 05:23:57 +08:00
|
|
|
if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
|
|
|
|
if (!Proto->isThisDeclarationADefinition()) {
|
|
|
|
RewriteForwardProtocolDecl(D);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-30 00:50:03 +08:00
|
|
|
HandleTopLevelSingleDecl(*I);
|
2011-08-28 04:50:59 +08:00
|
|
|
}
|
2011-11-18 08:26:59 +08:00
|
|
|
return true;
|
2009-03-30 00:50:03 +08:00
|
|
|
}
|
|
|
|
void HandleTopLevelSingleDecl(Decl *D);
|
2007-10-17 05:07:07 +08:00
|
|
|
void HandleDeclInMainFile(Decl *D);
|
2011-07-23 18:55:15 +08:00
|
|
|
RewriteObjC(std::string inFile, raw_ostream *OS,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &D, const LangOptions &LOpts,
|
2009-05-19 06:39:16 +08:00
|
|
|
bool silenceMacroWarn);
|
2008-08-08 12:15:52 +08:00
|
|
|
|
|
|
|
~RewriteObjC() {}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-28 12:11:33 +08:00
|
|
|
virtual void HandleTranslationUnit(ASTContext &C);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-06 00:43:40 +08:00
|
|
|
void ReplaceStmt(Stmt *Old, Stmt *New) {
|
2008-12-05 07:50:32 +08:00
|
|
|
Stmt *ReplacingStmt = ReplacedNodes[Old];
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-05 07:50:32 +08:00
|
|
|
if (ReplacingStmt)
|
|
|
|
return; // We can't rewrite the same node twice.
|
|
|
|
|
2008-12-09 20:56:34 +08:00
|
|
|
if (DisableReplaceStmt)
|
2011-11-06 17:01:30 +08:00
|
|
|
return;
|
2008-12-09 20:56:34 +08:00
|
|
|
|
2008-02-01 03:42:41 +08:00
|
|
|
// If replacement succeeded or warning disabled return with no warning.
|
2010-02-06 00:43:40 +08:00
|
|
|
if (!Rewrite.ReplaceStmt(Old, New)) {
|
2008-12-05 07:50:32 +08:00
|
|
|
ReplacedNodes[Old] = New;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (SilenceRewriteMacroWarning)
|
2008-02-01 03:37:57 +08:00
|
|
|
return;
|
This reworks some of the Diagnostic interfaces a bit to change how diagnostics
are formed. In particular, a diagnostic with all its strings and ranges is now
packaged up and sent to DiagnosticClients as a DiagnosticInfo instead of as a
ton of random stuff. This has the benefit of simplifying the interface, making
it more extensible, and allowing us to do more checking for things like access
past the end of the various arrays passed in.
In addition to introducing DiagnosticInfo, this also substantially changes how
Diagnostic::Report works. Instead of being passed in all of the info required
to issue a diagnostic, Report now takes only the required info (a location and
ID) and returns a fresh DiagnosticInfo *by value*. The caller is then free to
stuff strings and ranges into the DiagnosticInfo with the << operator. When
the dtor runs on the DiagnosticInfo object (which should happen at the end of
the statement), the diagnostic is actually emitted with all of the accumulated
information. This is a somewhat tricky dance, but it means that the
accumulated DiagnosticInfo is allowed to keep pointers to other expression
temporaries without those pointers getting invalidated.
This is just the minimal change to get this stuff working, but this will allow
us to eliminate the zillions of variant "Diag" methods scattered throughout
(e.g.) sema. For example, instead of calling:
Diag(BuiltinLoc, diag::err_overload_no_match, typeNames,
SourceRange(BuiltinLoc, RParenLoc));
We will soon be able to just do:
Diag(BuiltinLoc, diag::err_overload_no_match)
<< typeNames << SourceRange(BuiltinLoc, RParenLoc));
This scales better to support arbitrary types being passed in (not just
strings) in a type-safe way. Go operator overloading?!
llvm-svn: 59502
2008-11-18 15:04:44 +08:00
|
|
|
Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
|
|
|
|
<< Old->getSourceRange();
|
2008-02-01 03:37:57 +08:00
|
|
|
}
|
2008-12-09 20:56:34 +08:00
|
|
|
|
|
|
|
void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
|
2011-11-06 17:01:30 +08:00
|
|
|
if (DisableReplaceStmt)
|
|
|
|
return;
|
|
|
|
|
2010-11-01 05:07:24 +08:00
|
|
|
// Measure the old text.
|
2008-12-09 20:56:34 +08:00
|
|
|
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);
|
2009-06-30 09:26:17 +08:00
|
|
|
New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts));
|
2008-12-09 20:56:34 +08:00
|
|
|
const std::string &Str = S.str();
|
|
|
|
|
|
|
|
// If replacement succeeded or warning disabled return with no warning.
|
2009-08-20 03:10:30 +08:00
|
|
|
if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
|
2008-12-09 20:56:34 +08:00
|
|
|
ReplacedNodes[Old] = New;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (SilenceRewriteMacroWarning)
|
|
|
|
return;
|
|
|
|
Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
|
|
|
|
<< Old->getSourceRange();
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
void InsertText(SourceLocation Loc, StringRef Str,
|
2008-03-28 06:29:16 +08:00
|
|
|
bool InsertAfter = true) {
|
2008-02-01 03:51:04 +08:00
|
|
|
// If insertion succeeded or warning disabled return with no warning.
|
2010-02-14 22:14:16 +08:00
|
|
|
if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
|
2008-02-01 03:42:41 +08:00
|
|
|
SilenceRewriteMacroWarning)
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-02-01 03:42:41 +08:00
|
|
|
Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-02-01 03:51:04 +08:00
|
|
|
void ReplaceText(SourceLocation Start, unsigned OrigLength,
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Str) {
|
2008-02-01 03:51:04 +08:00
|
|
|
// If removal succeeded or warning disabled return with no warning.
|
2010-02-14 22:14:16 +08:00
|
|
|
if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
|
2008-02-01 03:51:04 +08:00
|
|
|
SilenceRewriteMacroWarning)
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-02-01 03:51:04 +08:00
|
|
|
Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-25 01:06:59 +08:00
|
|
|
// Syntactic Rewriting.
|
2011-12-06 02:43:13 +08:00
|
|
|
void RewriteRecordBody(RecordDecl *RD);
|
2008-01-19 08:30:35 +08:00
|
|
|
void RewriteInclude();
|
2011-08-28 04:50:59 +08:00
|
|
|
void RewriteForwardClassDecl(DeclGroupRef D);
|
2011-08-30 06:21:46 +08:00
|
|
|
void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG);
|
2011-12-28 06:43:10 +08:00
|
|
|
void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
|
2011-08-30 06:21:46 +08:00
|
|
|
const std::string &typedefString);
|
2011-12-06 02:43:13 +08:00
|
|
|
void RewriteImplementations();
|
2008-12-03 01:36:43 +08:00
|
|
|
void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|
|
|
ObjCImplementationDecl *IMD,
|
|
|
|
ObjCCategoryImplDecl *CID);
|
2008-01-08 03:49:32 +08:00
|
|
|
void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
|
2009-01-20 09:17:11 +08:00
|
|
|
void RewriteImplementationDecl(Decl *Dcl);
|
2010-10-16 08:29:27 +08:00
|
|
|
void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
|
|
|
|
ObjCMethodDecl *MDecl, std::string &ResultStr);
|
2010-02-26 09:42:20 +08:00
|
|
|
void RewriteTypeIntoString(QualType T, std::string &ResultStr,
|
|
|
|
const FunctionType *&FPRetType);
|
2010-01-15 07:05:52 +08:00
|
|
|
void RewriteByRefString(std::string &ResultStr, const std::string &Name,
|
2011-01-28 07:18:15 +08:00
|
|
|
ValueDecl *VD, bool def=false);
|
2008-01-08 03:49:32 +08:00
|
|
|
void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
|
|
|
|
void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
|
2012-01-02 05:23:57 +08:00
|
|
|
void RewriteForwardProtocolDecl(DeclGroupRef D);
|
|
|
|
void RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG);
|
2008-01-08 03:49:32 +08:00
|
|
|
void RewriteMethodDeclaration(ObjCMethodDecl *Method);
|
2009-01-11 09:06:09 +08:00
|
|
|
void RewriteProperty(ObjCPropertyDecl *prop);
|
2007-10-31 07:14:51 +08:00
|
|
|
void RewriteFunctionDecl(FunctionDecl *FD);
|
2010-07-01 03:16:53 +08:00
|
|
|
void RewriteBlockPointerType(std::string& Str, QualType Type);
|
|
|
|
void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
|
2010-01-14 08:35:56 +08:00
|
|
|
void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
|
2008-01-08 03:49:32 +08:00
|
|
|
void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
|
2010-02-11 02:54:22 +08:00
|
|
|
void RewriteTypeOfDecl(VarDecl *VD);
|
2008-07-30 02:15:38 +08:00
|
|
|
void RewriteObjCQualifiedInterfaceTypes(Expr *E);
|
2011-12-06 02:43:13 +08:00
|
|
|
|
2007-10-25 01:06:59 +08:00
|
|
|
// Expression Rewriting.
|
2007-11-09 23:20:18 +08:00
|
|
|
Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
|
2007-10-25 00:57:36 +08:00
|
|
|
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
|
2011-11-06 17:01:30 +08:00
|
|
|
Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
|
|
|
|
Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
|
2007-11-05 22:50:49 +08:00
|
|
|
Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
|
2007-10-25 00:57:36 +08:00
|
|
|
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
|
2007-11-03 19:27:19 +08:00
|
|
|
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
|
2007-12-08 02:47:10 +08:00
|
|
|
Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
|
2009-12-06 05:43:12 +08:00
|
|
|
void RewriteTryReturnStmts(Stmt *S);
|
|
|
|
void RewriteSyncReturnStmts(Stmt *S, std::string buf);
|
2008-01-08 03:49:32 +08:00
|
|
|
Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
|
2008-01-30 06:59:37 +08:00
|
|
|
Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
|
2008-01-08 03:49:32 +08:00
|
|
|
Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
|
2008-01-31 13:10:40 +08:00
|
|
|
Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
|
|
|
|
SourceLocation OrigEnd);
|
2008-01-16 07:58:23 +08:00
|
|
|
Stmt *RewriteBreakStmt(BreakStmt *S);
|
|
|
|
Stmt *RewriteContinueStmt(ContinueStmt *S);
|
2011-12-06 02:43:13 +08:00
|
|
|
void RewriteCastExpr(CStyleCastExpr *CE);
|
2011-12-09 02:25:15 +08:00
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
// Block rewriting.
|
2009-09-09 23:08:12 +08:00
|
|
|
void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
|
2011-12-06 02:43:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// Block specific rewrite rules.
|
2008-10-28 01:20:55 +08:00
|
|
|
void RewriteBlockPointerDecl(NamedDecl *VD);
|
2009-12-23 10:07:37 +08:00
|
|
|
void RewriteByRefVar(VarDecl *VD);
|
2010-01-05 03:50:07 +08:00
|
|
|
Stmt *RewriteBlockDeclRefExpr(Expr *VD);
|
2010-03-12 02:20:03 +08:00
|
|
|
Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
|
2008-10-28 01:20:55 +08:00
|
|
|
void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
|
2011-12-06 02:43:13 +08:00
|
|
|
|
|
|
|
void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
|
|
|
|
std::string &Result);
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
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;
|
2011-12-06 02:43:13 +08:00
|
|
|
|
|
|
|
// Misc. AST transformation routines. Somtimes they end up calling
|
|
|
|
// rewriting routines on the new ASTs.
|
|
|
|
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
|
|
|
|
Expr **args, unsigned nargs,
|
|
|
|
SourceLocation StartLoc=SourceLocation(),
|
|
|
|
SourceLocation EndLoc=SourceLocation());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-06 02:43:13 +08:00
|
|
|
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);
|
2009-09-09 23:08:12 +08:00
|
|
|
std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef funcName, std::string Tag);
|
2009-09-09 23:08:12 +08:00
|
|
|
std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef funcName, std::string Tag);
|
2009-12-07 05:14:13 +08:00
|
|
|
std::string SynthesizeBlockImpl(BlockExpr *CE,
|
|
|
|
std::string Tag, std::string Desc);
|
|
|
|
std::string SynthesizeBlockDescriptor(std::string DescTag,
|
|
|
|
std::string ImplTag,
|
2011-07-23 18:55:15 +08:00
|
|
|
int i, StringRef funcName,
|
2009-12-07 05:14:13 +08:00
|
|
|
unsigned hasCopy);
|
2009-12-16 01:30:20 +08:00
|
|
|
Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
|
2008-10-28 01:20:55 +08:00
|
|
|
void SynthesizeBlockLiterals(SourceLocation FunLocStart,
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef FunName);
|
2011-12-06 02:43:13 +08:00
|
|
|
FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
|
|
|
|
Stmt *SynthBlockInitExpr(BlockExpr *Exp,
|
|
|
|
const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs);
|
|
|
|
|
|
|
|
// Misc. helper routines.
|
2011-12-06 03:50:04 +08:00
|
|
|
QualType getProtocolType();
|
2011-12-06 02:43:13 +08:00
|
|
|
void WarnAboutReturnGotoStmts(Stmt *S);
|
|
|
|
void HasReturnStmts(Stmt *S, bool &hasReturns);
|
|
|
|
void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
|
|
|
|
void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
|
|
|
|
void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-06 02:43:13 +08:00
|
|
|
bool IsDeclStmtInForeachHeader(DeclStmt *DS);
|
2008-10-28 01:20:55 +08:00
|
|
|
void CollectBlockDeclRefInfo(BlockExpr *Exp);
|
|
|
|
void GetBlockDeclRefExprs(Stmt *S);
|
2010-02-25 06:48:18 +08:00
|
|
|
void GetInnerBlockDeclRefExprs(Stmt *S,
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
|
2010-03-02 07:36:21 +08:00
|
|
|
llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
// We avoid calling Type::isBlockPointerType(), since it operates on the
|
|
|
|
// canonical type. We only care if the top-level type is a closure pointer.
|
2009-02-07 09:47:29 +08:00
|
|
|
bool isTopLevelBlockPointerType(QualType T) {
|
|
|
|
return isa<BlockPointerType>(T);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-05-26 01:12:52 +08:00
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
|
2011-12-06 02:43:13 +08:00
|
|
|
bool needToScanForQualifiers(QualType T);
|
|
|
|
QualType getSuperStructType();
|
|
|
|
QualType getConstantStringStructType();
|
|
|
|
QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
|
|
|
|
bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
|
|
|
|
|
2010-11-06 02:34:46 +08:00
|
|
|
void convertToUnqualifiedObjCType(QualType &T) {
|
|
|
|
if (T->isObjCQualifiedIdType())
|
|
|
|
T = Context->getObjCIdType();
|
|
|
|
else if (T->isObjCQualifiedClassType())
|
|
|
|
T = Context->getObjCClassType();
|
|
|
|
else if (T->isObjCObjectPointerType() &&
|
2011-09-11 01:01:56 +08:00
|
|
|
T->getPointeeType()->isObjCQualifiedInterfaceType()) {
|
|
|
|
if (const ObjCObjectPointerType * OBJPT =
|
|
|
|
T->getAsObjCInterfacePointerType()) {
|
|
|
|
const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
|
|
|
|
T = QualType(IFaceT, 0);
|
|
|
|
T = Context->getPointerType(T);
|
|
|
|
}
|
|
|
|
}
|
2010-11-06 02:34:46 +08:00
|
|
|
}
|
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
// FIXME: This predicate seems like it would be useful to add to ASTContext.
|
|
|
|
bool isObjCType(QualType T) {
|
|
|
|
if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
|
|
|
|
OCT == Context->getCanonicalType(Context->getObjCClassType()))
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const PointerType *PT = OCT->getAs<PointerType>()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
|
2009-06-18 06:40:22 +08:00
|
|
|
PT->getPointeeType()->isObjCQualifiedIdType())
|
2008-10-28 01:20:55 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool PointerTypeTakesAnyBlockArguments(QualType QT);
|
2010-11-04 07:29:24 +08:00
|
|
|
bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
|
2009-02-07 09:47:29 +08:00
|
|
|
void GetExtentOfArgList(const char *Name, const char *&LParen,
|
|
|
|
const char *&RParen);
|
2011-12-06 02:43:13 +08:00
|
|
|
|
2009-04-30 00:37:50 +08:00
|
|
|
void QuoteDoublequotes(std::string &From, std::string &To) {
|
2009-09-09 23:08:12 +08:00
|
|
|
for (unsigned i = 0; i < From.length(); i++) {
|
2009-04-30 00:37:50 +08:00
|
|
|
if (From[i] == '"')
|
|
|
|
To += "\\\"";
|
|
|
|
else
|
|
|
|
To += From[i];
|
|
|
|
}
|
|
|
|
}
|
2010-12-14 16:05:40 +08:00
|
|
|
|
|
|
|
QualType getSimpleFunctionType(QualType result,
|
|
|
|
const QualType *args,
|
|
|
|
unsigned numArgs,
|
|
|
|
bool variadic = false) {
|
2011-09-10 04:35:22 +08:00
|
|
|
if (result == Context->getObjCInstanceType())
|
|
|
|
result = Context->getObjCIdType();
|
2010-12-14 16:05:40 +08:00
|
|
|
FunctionProtoType::ExtProtoInfo fpi;
|
|
|
|
fpi.Variadic = variadic;
|
|
|
|
return Context->getFunctionType(result, args, numArgs, fpi);
|
|
|
|
}
|
2010-01-16 02:39:57 +08:00
|
|
|
|
2011-12-06 02:43:13 +08:00
|
|
|
// 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());
|
|
|
|
}
|
|
|
|
};
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
};
|
2007-10-11 08:43:27 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
|
|
|
|
NamedDecl *D) {
|
2011-01-19 14:33:43 +08:00
|
|
|
if (const FunctionProtoType *fproto
|
2010-12-15 06:11:44 +08:00
|
|
|
= dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
|
2009-09-09 23:08:12 +08:00
|
|
|
for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(),
|
2008-10-28 01:20:55 +08:00
|
|
|
E = fproto->arg_type_end(); I && (I != E); ++I)
|
2008-12-12 05:05:33 +08:00
|
|
|
if (isTopLevelBlockPointerType(*I)) {
|
2008-10-28 01:20:55 +08:00
|
|
|
// All the args are checked/rewritten. Don't call twice!
|
|
|
|
RewriteBlockPointerDecl(D);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
|
2009-07-30 05:53:49 +08:00
|
|
|
const PointerType *PT = funcType->getAs<PointerType>();
|
2008-10-28 01:20:55 +08:00
|
|
|
if (PT && PointerTypeTakesAnyBlockArguments(funcType))
|
2009-02-27 07:50:07 +08:00
|
|
|
RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
|
2008-01-18 09:15:54 +08:00
|
|
|
static bool IsHeaderFile(const std::string &Filename) {
|
|
|
|
std::string::size_type DotPos = Filename.rfind('.');
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-18 09:15:54 +08:00
|
|
|
if (DotPos == std::string::npos) {
|
|
|
|
// no file extension
|
2009-09-09 23:08:12 +08:00
|
|
|
return false;
|
2008-01-18 09:15:54 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-18 09:15:54 +08:00
|
|
|
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";
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2008-01-18 09:15:54 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
RewriteObjC::RewriteObjC(std::string inFile, raw_ostream* OS,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &D, const LangOptions &LOpts,
|
2009-05-19 06:39:16 +08:00
|
|
|
bool silenceMacroWarn)
|
|
|
|
: Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS),
|
|
|
|
SilenceRewriteMacroWarning(silenceMacroWarn) {
|
2008-03-29 06:26:09 +08:00
|
|
|
IsHeader = IsHeaderFile(inFile);
|
2011-09-26 07:23:43 +08:00
|
|
|
RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
|
2008-03-29 06:26:09 +08:00
|
|
|
"rewriting sub-expression within a macro (may not be correct)");
|
2011-09-26 07:23:43 +08:00
|
|
|
TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
|
|
|
|
DiagnosticsEngine::Warning,
|
2009-02-07 09:47:29 +08:00
|
|
|
"rewriter doesn't support user-specified control flow semantics "
|
|
|
|
"for @try/@finally (code may not execute properly)");
|
2008-03-29 06:26:09 +08:00
|
|
|
}
|
|
|
|
|
2009-05-19 06:29:17 +08:00
|
|
|
ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile,
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream* OS,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags,
|
2009-05-19 06:39:16 +08:00
|
|
|
const LangOptions &LOpts,
|
|
|
|
bool SilenceRewriteMacroWarning) {
|
2011-12-09 02:25:15 +08:00
|
|
|
if (true /*!LOpts.ObjCNonFragileABI*/)
|
|
|
|
return new RewriteObjCFragileABI(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
|
|
|
|
else {
|
|
|
|
assert(false && "objective-C rewriter for nonfragile ABI = NYI");
|
|
|
|
return 0;
|
|
|
|
}
|
2007-12-01 06:25:36 +08:00
|
|
|
}
|
2007-10-11 08:43:27 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::InitializeCommon(ASTContext &context) {
|
2008-02-01 03:38:44 +08:00
|
|
|
Context = &context;
|
|
|
|
SM = &Context->getSourceManager();
|
2008-04-17 22:40:12 +08:00
|
|
|
TUDecl = Context->getTranslationUnitDecl();
|
2008-02-01 03:38:44 +08:00
|
|
|
MsgSendFunctionDecl = 0;
|
|
|
|
MsgSendSuperFunctionDecl = 0;
|
|
|
|
MsgSendStretFunctionDecl = 0;
|
|
|
|
MsgSendSuperStretFunctionDecl = 0;
|
|
|
|
MsgSendFpretFunctionDecl = 0;
|
|
|
|
GetClassFunctionDecl = 0;
|
|
|
|
GetMetaClassFunctionDecl = 0;
|
2010-03-11 05:17:41 +08:00
|
|
|
GetSuperClassFunctionDecl = 0;
|
2008-02-01 03:38:44 +08:00
|
|
|
SelGetUidFunctionDecl = 0;
|
|
|
|
CFStringFunctionDecl = 0;
|
|
|
|
ConstantStringClassReference = 0;
|
|
|
|
NSStringRecord = 0;
|
2008-10-28 01:20:55 +08:00
|
|
|
CurMethodDef = 0;
|
|
|
|
CurFunctionDef = 0;
|
2010-01-14 08:35:56 +08:00
|
|
|
CurFunctionDeclToDeclareForBlock = 0;
|
2008-12-09 20:56:34 +08:00
|
|
|
GlobalVarDecl = 0;
|
2008-02-01 03:38:44 +08:00
|
|
|
SuperStructDecl = 0;
|
2009-04-30 00:37:50 +08:00
|
|
|
ProtocolTypeDecl = 0;
|
2008-03-28 06:59:54 +08:00
|
|
|
ConstantStringDecl = 0;
|
2008-02-01 03:38:44 +08:00
|
|
|
BcLabelCount = 0;
|
2008-03-12 01:37:02 +08:00
|
|
|
SuperContructorFunctionDecl = 0;
|
2008-03-15 08:55:56 +08:00
|
|
|
NumObjCStringLiterals = 0;
|
2008-12-09 04:01:41 +08:00
|
|
|
PropParentMap = 0;
|
|
|
|
CurrentBody = 0;
|
2008-12-09 20:56:34 +08:00
|
|
|
DisableReplaceStmt = false;
|
2010-01-08 06:51:18 +08:00
|
|
|
objc_impl_method = false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-02-01 03:38:44 +08:00
|
|
|
// 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();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-04-15 07:22:57 +08:00
|
|
|
Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions());
|
2008-02-01 03:38:44 +08:00
|
|
|
}
|
|
|
|
|
2007-10-25 01:06:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Top Level Driver Code
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-03-30 00:50:03 +08:00
|
|
|
void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
|
2010-02-06 05:28:51 +08:00
|
|
|
if (Diags.hasErrorOccurred())
|
|
|
|
return;
|
|
|
|
|
2007-10-17 05:07:07 +08:00
|
|
|
// 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();
|
2011-07-26 00:49:02 +08:00
|
|
|
Loc = SM->getExpansionLoc(Loc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-17 05:07:07 +08:00
|
|
|
// If this is for a builtin, ignore it.
|
|
|
|
if (Loc.isInvalid()) return;
|
|
|
|
|
2007-10-24 07:50:29 +08:00
|
|
|
// Look for built-in declarations that we need to refer during the rewrite.
|
|
|
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
2007-10-31 07:14:51 +08:00
|
|
|
RewriteFunctionDecl(FD);
|
2008-04-16 06:42:06 +08:00
|
|
|
} else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
|
2007-11-03 19:27:19 +08:00
|
|
|
// declared in <Foundation/NSString.h>
|
2010-08-18 06:39:59 +08:00
|
|
|
if (FVD->getName() == "_NSConstantStringClassReference") {
|
2007-11-03 19:27:19 +08:00
|
|
|
ConstantStringClassReference = FVD;
|
|
|
|
return;
|
|
|
|
}
|
2011-12-16 04:29:51 +08:00
|
|
|
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
|
|
|
|
if (ID->isThisDeclarationADefinition())
|
|
|
|
RewriteInterfaceDecl(ID);
|
2008-01-08 03:49:32 +08:00
|
|
|
} else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
|
2007-10-30 21:30:57 +08:00
|
|
|
RewriteCategoryDecl(CD);
|
2008-01-08 03:49:32 +08:00
|
|
|
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
|
2012-01-02 05:23:57 +08:00
|
|
|
if (PD->isThisDeclarationADefinition())
|
|
|
|
RewriteProtocolDecl(PD);
|
2009-01-09 08:49:46 +08:00
|
|
|
} else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
|
|
|
|
// Recurse into linkage specifications
|
2009-06-30 10:36:12 +08:00
|
|
|
for (DeclContext::decl_iterator DI = LSD->decls_begin(),
|
|
|
|
DIEnd = LSD->decls_end();
|
2011-08-30 06:21:46 +08:00
|
|
|
DI != DIEnd; ) {
|
2011-12-28 06:43:10 +08:00
|
|
|
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;
|
|
|
|
|
2011-12-16 04:29:51 +08:00
|
|
|
++DI;
|
2011-12-28 06:43:10 +08:00
|
|
|
} while (DI != DIEnd);
|
|
|
|
RewriteForwardClassDecl(DG);
|
|
|
|
continue;
|
2011-08-30 06:21:46 +08:00
|
|
|
}
|
|
|
|
}
|
2012-01-02 05:23:57 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-30 00:50:03 +08:00
|
|
|
HandleTopLevelSingleDecl(*DI);
|
2011-08-30 06:21:46 +08:00
|
|
|
++DI;
|
|
|
|
}
|
2007-10-24 07:50:29 +08:00
|
|
|
}
|
2007-10-25 01:06:59 +08:00
|
|
|
// If we have a decl in the main file, see if we should rewrite it.
|
2008-04-15 05:24:13 +08:00
|
|
|
if (SM->isFromMainFile(Loc))
|
2007-10-17 05:07:07 +08:00
|
|
|
return HandleDeclInMainFile(D);
|
|
|
|
}
|
|
|
|
|
2007-10-25 01:06:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Syntactic (non-AST) Rewriting Code
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::RewriteInclude() {
|
2009-01-17 14:22:33 +08:00
|
|
|
SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef MainBuf = SM->getBufferData(MainFileID);
|
2010-03-16 22:14:31 +08:00
|
|
|
const char *MainBufStart = MainBuf.begin();
|
|
|
|
const char *MainBufEnd = MainBuf.end();
|
2008-01-19 08:30:35 +08:00
|
|
|
size_t ImportLen = strlen("import");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-19 09:03:17 +08:00
|
|
|
// Loop over the whole file, looking for includes.
|
2008-01-19 08:30:35 +08:00
|
|
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation ImportLoc =
|
2011-09-20 04:40:19 +08:00
|
|
|
LocStart.getLocWithOffset(BufPtr-MainBufStart);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(ImportLoc, ImportLen, "include");
|
2008-01-19 08:30:35 +08:00
|
|
|
BufPtr += ImportLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-10-12 02:38:32 +08:00
|
|
|
}
|
|
|
|
|
2010-10-16 08:29:27 +08:00
|
|
|
static std::string getIvarAccessString(ObjCIvarDecl *OID) {
|
|
|
|
const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface();
|
2008-12-02 23:48:25 +08:00
|
|
|
std::string S;
|
|
|
|
S = "((struct ";
|
|
|
|
S += ClassDecl->getIdentifier()->getName();
|
|
|
|
S += "_IMPL *)self)->";
|
2009-10-19 04:26:27 +08:00
|
|
|
S += OID->getName();
|
2008-12-02 23:48:25 +08:00
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
2008-12-03 01:36:43 +08:00
|
|
|
void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|
|
|
ObjCImplementationDecl *IMD,
|
|
|
|
ObjCCategoryImplDecl *CID) {
|
2010-02-26 09:42:20 +08:00
|
|
|
static bool objcGetPropertyDefined = false;
|
|
|
|
static bool objcSetPropertyDefined = false;
|
2008-12-02 04:33:01 +08:00
|
|
|
SourceLocation startLoc = PID->getLocStart();
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(startLoc, "// ");
|
2008-12-02 23:48:25 +08:00
|
|
|
const char *startBuf = SM->getCharacterData(startLoc);
|
|
|
|
assert((*startBuf == '@') && "bogus @synthesize location");
|
|
|
|
const char *semiBuf = strchr(startBuf, ';');
|
|
|
|
assert((*semiBuf == ';') && "@synthesize: can't find ';'");
|
2009-02-07 09:47:29 +08:00
|
|
|
SourceLocation onePastSemiLoc =
|
2011-09-20 04:40:19 +08:00
|
|
|
startLoc.getLocWithOffset(semiBuf-startBuf+1);
|
2008-12-02 23:48:25 +08:00
|
|
|
|
|
|
|
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
|
|
|
|
return; // FIXME: is this correct?
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-02 23:48:25 +08:00
|
|
|
// Generate the 'getter' function.
|
|
|
|
ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
|
|
|
ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-03 00:05:55 +08:00
|
|
|
if (!OID)
|
|
|
|
return;
|
2010-02-26 09:42:20 +08:00
|
|
|
unsigned Attributes = PD->getPropertyAttributes();
|
2010-10-20 07:47:54 +08:00
|
|
|
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 "*".
|
2010-02-26 09:42:20 +08:00
|
|
|
|
2010-10-20 07:47:54 +08:00
|
|
|
// 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(
|
2011-09-28 06:38:19 +08:00
|
|
|
Context->getPrintingPolicy());
|
2010-10-20 07:47:54 +08:00
|
|
|
Getr += ParamStr;
|
|
|
|
}
|
|
|
|
if (FT->isVariadic()) {
|
|
|
|
if (FT->getNumArgs()) Getr += ", ";
|
|
|
|
Getr += "...";
|
|
|
|
}
|
|
|
|
Getr += ")";
|
|
|
|
} else
|
|
|
|
Getr += "()";
|
|
|
|
}
|
|
|
|
Getr += ";\n";
|
|
|
|
Getr += "return (_TYPE)";
|
|
|
|
Getr += "objc_getProperty(self, _cmd, ";
|
2011-12-06 02:43:13 +08:00
|
|
|
RewriteIvarOffsetComputation(OID, Getr);
|
2010-10-20 07:47:54 +08:00
|
|
|
Getr += ", 1)";
|
2010-02-26 09:42:20 +08:00
|
|
|
}
|
2010-10-20 07:47:54 +08:00
|
|
|
else
|
|
|
|
Getr += "return " + getIvarAccessString(OID);
|
|
|
|
Getr += "; }";
|
|
|
|
InsertText(onePastSemiLoc, Getr);
|
2010-02-26 09:42:20 +08:00
|
|
|
}
|
2010-10-20 07:47:54 +08:00
|
|
|
|
|
|
|
if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined())
|
2008-12-02 23:48:25 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-02 23:48:25 +08:00
|
|
|
// Generate the 'setter' function.
|
|
|
|
std::string Setr;
|
2010-02-26 09:42:20 +08:00
|
|
|
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";
|
|
|
|
}
|
|
|
|
|
2010-10-16 08:29:27 +08:00
|
|
|
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
|
|
|
PD->getSetterMethodDecl(), Setr);
|
2008-12-02 23:48:25 +08:00
|
|
|
Setr += "{ ";
|
2008-12-03 00:05:55 +08:00
|
|
|
// Synthesize an explicit cast to initialize the ivar.
|
2008-12-03 08:56:33 +08:00
|
|
|
// See objc-act.c:objc_synthesize_new_setter() for details.
|
2010-02-26 09:42:20 +08:00
|
|
|
if (GenSetProperty) {
|
|
|
|
Setr += "objc_setProperty (self, _cmd, ";
|
2011-12-06 02:43:13 +08:00
|
|
|
RewriteIvarOffsetComputation(OID, Setr);
|
2010-02-26 09:42:20 +08:00
|
|
|
Setr += ", (id)";
|
2010-08-18 06:39:59 +08:00
|
|
|
Setr += PD->getName();
|
2010-02-26 09:42:20 +08:00
|
|
|
Setr += ", ";
|
|
|
|
if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
|
|
|
|
Setr += "0, ";
|
|
|
|
else
|
|
|
|
Setr += "1, ";
|
|
|
|
if (Attributes & ObjCPropertyDecl::OBJC_PR_copy)
|
|
|
|
Setr += "1)";
|
|
|
|
else
|
|
|
|
Setr += "0)";
|
|
|
|
}
|
|
|
|
else {
|
2010-10-16 08:29:27 +08:00
|
|
|
Setr += getIvarAccessString(OID) + " = ";
|
2010-08-18 06:39:59 +08:00
|
|
|
Setr += PD->getName();
|
2010-02-26 09:42:20 +08:00
|
|
|
}
|
2008-12-03 00:05:55 +08:00
|
|
|
Setr += "; }";
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(onePastSemiLoc, Setr);
|
2008-12-02 04:33:01 +08:00
|
|
|
}
|
2007-10-12 02:38:32 +08:00
|
|
|
|
2011-08-30 06:21:46 +08:00
|
|
|
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";
|
|
|
|
}
|
|
|
|
|
2011-12-28 06:43:10 +08:00
|
|
|
void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
|
2011-08-30 06:21:46 +08:00
|
|
|
const std::string &typedefString) {
|
2011-12-28 06:43:10 +08:00
|
|
|
SourceLocation startLoc = ClassDecl->getLocStart();
|
2011-08-30 06:21:46 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-08-28 04:50:59 +08:00
|
|
|
void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {
|
2007-10-25 01:06:59 +08:00
|
|
|
std::string typedefString;
|
2011-08-28 04:50:59 +08:00
|
|
|
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
|
2011-12-28 06:43:10 +08:00
|
|
|
ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I);
|
2011-08-28 04:50:59 +08:00
|
|
|
if (I == D.begin()) {
|
2011-08-30 06:21:46 +08:00
|
|
|
// 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.
|
2011-08-28 04:50:59 +08:00
|
|
|
typedefString += "// @class ";
|
|
|
|
typedefString += ForwardDecl->getNameAsString();
|
2010-01-12 06:48:40 +08:00
|
|
|
typedefString += ";\n";
|
2011-08-28 04:50:59 +08:00
|
|
|
}
|
2011-08-30 06:21:46 +08:00
|
|
|
RewriteOneForwardClassDecl(ForwardDecl, typedefString);
|
2007-10-25 06:48:43 +08:00
|
|
|
}
|
2011-08-30 06:21:46 +08:00
|
|
|
DeclGroupRef::iterator I = D.begin();
|
2011-12-28 06:43:10 +08:00
|
|
|
RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
|
2011-08-30 06:21:46 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-08-30 06:21:46 +08:00
|
|
|
void RewriteObjC::RewriteForwardClassDecl(
|
|
|
|
const llvm::SmallVector<Decl*, 8> &D) {
|
|
|
|
std::string typedefString;
|
|
|
|
for (unsigned i = 0; i < D.size(); i++) {
|
2011-12-28 06:43:10 +08:00
|
|
|
ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
|
2011-08-30 06:21:46 +08:00
|
|
|
if (i == 0) {
|
|
|
|
typedefString += "// @class ";
|
|
|
|
typedefString += ForwardDecl->getNameAsString();
|
|
|
|
typedefString += ";\n";
|
|
|
|
}
|
|
|
|
RewriteOneForwardClassDecl(ForwardDecl, typedefString);
|
|
|
|
}
|
2011-12-28 06:43:10 +08:00
|
|
|
RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
|
2007-10-25 01:06:59 +08:00
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
|
2010-01-22 01:36:00 +08:00
|
|
|
// When method is a synthesized one, such as a getter/setter there is
|
|
|
|
// nothing to rewrite.
|
2011-09-10 04:35:22 +08:00
|
|
|
if (Method->isImplicit())
|
2010-01-22 01:36:00 +08:00
|
|
|
return;
|
2007-12-15 07:37:57 +08:00
|
|
|
SourceLocation LocStart = Method->getLocStart();
|
|
|
|
SourceLocation LocEnd = Method->getLocEnd();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-26 05:09:52 +08:00
|
|
|
if (SM->getExpansionLineNumber(LocEnd) >
|
|
|
|
SM->getExpansionLineNumber(LocStart)) {
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(LocStart, "#if 0\n");
|
|
|
|
ReplaceText(LocEnd, 1, ";\n#endif\n");
|
2007-12-15 07:37:57 +08:00
|
|
|
} else {
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(LocStart, "// ");
|
2007-10-30 21:30:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
|
2010-01-22 01:36:00 +08:00
|
|
|
SourceLocation Loc = prop->getAtLoc();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(Loc, 0, "// ");
|
2009-01-11 09:06:09 +08:00
|
|
|
// FIXME: handle properties that are declared across multiple lines.
|
2007-11-07 08:09:37 +08:00
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
|
2007-10-30 21:30:57 +08:00
|
|
|
SourceLocation LocStart = CatDecl->getLocStart();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-30 21:30:57 +08:00
|
|
|
// FIXME: handle category headers that are declared across multiple lines.
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, 0, "// ");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-10 09:15:09 +08:00
|
|
|
for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(),
|
|
|
|
E = CatDecl->prop_end(); I != E; ++I)
|
|
|
|
RewriteProperty(*I);
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
for (ObjCCategoryDecl::instmeth_iterator
|
|
|
|
I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
I != E; ++I)
|
2007-12-15 07:37:57 +08:00
|
|
|
RewriteMethodDeclaration(*I);
|
2009-09-09 23:08:12 +08:00
|
|
|
for (ObjCCategoryDecl::classmeth_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
I != E; ++I)
|
2007-12-15 07:37:57 +08:00
|
|
|
RewriteMethodDeclaration(*I);
|
|
|
|
|
2007-10-30 21:30:57 +08:00
|
|
|
// Lastly, comment out the @end.
|
2010-05-25 01:22:38 +08:00
|
|
|
ReplaceText(CatDecl->getAtEndRange().getBegin(),
|
|
|
|
strlen("@end"), "/* @end */");
|
2007-10-30 21:30:57 +08:00
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
|
2007-10-31 00:42:30 +08:00
|
|
|
SourceLocation LocStart = PDecl->getLocStart();
|
2012-01-02 10:00:30 +08:00
|
|
|
assert(PDecl->isThisDeclarationADefinition());
|
|
|
|
|
2007-10-31 00:42:30 +08:00
|
|
|
// FIXME: handle protocol headers that are declared across multiple lines.
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, 0, "// ");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
for (ObjCProtocolDecl::instmeth_iterator
|
|
|
|
I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
I != E; ++I)
|
2007-12-15 07:37:57 +08:00
|
|
|
RewriteMethodDeclaration(*I);
|
2009-04-10 05:40:53 +08:00
|
|
|
for (ObjCProtocolDecl::classmeth_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
I != E; ++I)
|
2007-12-15 07:37:57 +08:00
|
|
|
RewriteMethodDeclaration(*I);
|
|
|
|
|
2010-09-25 02:36:58 +08:00
|
|
|
for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(),
|
|
|
|
E = PDecl->prop_end(); I != E; ++I)
|
|
|
|
RewriteProperty(*I);
|
|
|
|
|
2007-10-31 00:42:30 +08:00
|
|
|
// Lastly, comment out the @end.
|
2010-01-07 09:20:12 +08:00
|
|
|
SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
|
2010-05-25 01:22:38 +08:00
|
|
|
ReplaceText(LocEnd, strlen("@end"), "/* @end */");
|
2007-11-14 23:03:57 +08:00
|
|
|
|
2007-11-14 09:37:46 +08:00
|
|
|
// 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"))) {
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-14 09:37:46 +08:00
|
|
|
}
|
|
|
|
else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-14 09:37:46 +08:00
|
|
|
}
|
|
|
|
}
|
2007-10-31 00:42:30 +08:00
|
|
|
}
|
|
|
|
|
2012-01-02 05:23:57 +08:00
|
|
|
void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
|
|
|
|
SourceLocation LocStart = (*D.begin())->getLocStart();
|
|
|
|
if (LocStart.isInvalid())
|
|
|
|
llvm_unreachable("Invalid SourceLocation");
|
|
|
|
// FIXME: handle forward protocol that are declared across multiple lines.
|
|
|
|
ReplaceText(LocStart, 0, "// ");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RewriteObjC::RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG) {
|
|
|
|
SourceLocation LocStart = DG[0]->getLocStart();
|
2007-11-14 11:37:28 +08:00
|
|
|
if (LocStart.isInvalid())
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Invalid SourceLocation");
|
2007-11-14 08:42:16 +08:00
|
|
|
// FIXME: handle forward protocol that are declared across multiple lines.
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, 0, "// ");
|
2007-11-14 08:42:16 +08:00
|
|
|
}
|
|
|
|
|
2010-02-26 09:42:20 +08:00
|
|
|
void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
|
|
|
|
const FunctionType *&FPRetType) {
|
|
|
|
if (T->isObjCQualifiedIdType())
|
2007-12-18 05:03:50 +08:00
|
|
|
ResultStr += "id";
|
2010-02-26 09:42:20 +08:00
|
|
|
else if (T->isFunctionPointerType() ||
|
|
|
|
T->isBlockPointerType()) {
|
2008-07-16 22:40:40 +08:00
|
|
|
// needs special handling, since pointer-to-functions have special
|
|
|
|
// syntax (where a decaration models use).
|
2010-02-26 09:42:20 +08:00
|
|
|
QualType retType = T;
|
2008-12-12 03:29:16 +08:00
|
|
|
QualType PointeeTy;
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const PointerType* PT = retType->getAs<PointerType>())
|
2008-12-12 03:29:16 +08:00
|
|
|
PointeeTy = PT->getPointeeType();
|
2009-07-30 05:53:49 +08:00
|
|
|
else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
|
2008-12-12 03:29:16 +08:00
|
|
|
PointeeTy = BPT->getPointeeType();
|
2009-09-22 07:43:11 +08:00
|
|
|
if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
|
2010-07-01 03:16:53 +08:00
|
|
|
ResultStr += FPRetType->getResultType().getAsString(
|
2011-09-28 06:38:19 +08:00
|
|
|
Context->getPrintingPolicy());
|
2008-12-12 03:29:16 +08:00
|
|
|
ResultStr += "(*";
|
2008-07-16 22:40:40 +08:00
|
|
|
}
|
|
|
|
} else
|
2011-09-28 06:38:19 +08:00
|
|
|
ResultStr += T.getAsString(Context->getPrintingPolicy());
|
2010-02-26 09:42:20 +08:00
|
|
|
}
|
|
|
|
|
2010-10-16 08:29:27 +08:00
|
|
|
void RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
|
|
|
|
ObjCMethodDecl *OMD,
|
2010-02-26 09:42:20 +08:00
|
|
|
std::string &ResultStr) {
|
|
|
|
//fprintf(stderr,"In RewriteObjCMethodDecl\n");
|
|
|
|
const FunctionType *FPRetType = 0;
|
|
|
|
ResultStr += "\nstatic ";
|
|
|
|
RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType);
|
2008-01-10 09:39:52 +08:00
|
|
|
ResultStr += " ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-14 02:44:14 +08:00
|
|
|
// Unique method name
|
2007-11-14 05:02:00 +08:00
|
|
|
std::string NameStr;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-10 01:18:27 +08:00
|
|
|
if (OMD->isInstanceMethod())
|
2007-11-14 05:02:00 +08:00
|
|
|
NameStr += "_I_";
|
2007-11-14 02:44:14 +08:00
|
|
|
else
|
2007-11-14 05:02:00 +08:00
|
|
|
NameStr += "_C_";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-10-16 08:29:27 +08:00
|
|
|
NameStr += IDecl->getNameAsString();
|
2007-11-14 05:02:00 +08:00
|
|
|
NameStr += "_";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
if (ObjCCategoryImplDecl *CID =
|
2009-01-09 03:41:02 +08:00
|
|
|
dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
|
2008-11-24 13:29:24 +08:00
|
|
|
NameStr += CID->getNameAsString();
|
2007-11-14 05:02:00 +08:00
|
|
|
NameStr += "_";
|
2007-11-14 02:44:14 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
// Append selector names, replacing ':' with '_'
|
2008-11-24 11:33:13 +08:00
|
|
|
{
|
|
|
|
std::string selString = OMD->getSelector().getAsString();
|
2007-11-14 02:44:14 +08:00
|
|
|
int len = selString.size();
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
if (selString[i] == ':')
|
|
|
|
selString[i] = '_';
|
2007-11-14 05:02:00 +08:00
|
|
|
NameStr += selString;
|
2007-11-14 02:44:14 +08:00
|
|
|
}
|
2007-11-14 05:02:00 +08:00
|
|
|
// Remember this name for metadata emission
|
|
|
|
MethodInternalNames[OMD] = NameStr;
|
|
|
|
ResultStr += NameStr;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-14 02:44:14 +08:00
|
|
|
// Rewrite arguments
|
|
|
|
ResultStr += "(";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-14 02:44:14 +08:00
|
|
|
// invisible arguments
|
2009-01-10 01:18:27 +08:00
|
|
|
if (OMD->isInstanceMethod()) {
|
2010-10-16 08:29:27 +08:00
|
|
|
QualType selfTy = Context->getObjCInterfaceType(IDecl);
|
2007-11-14 02:44:14 +08:00
|
|
|
selfTy = Context->getPointerType(selfTy);
|
2011-09-18 01:15:52 +08:00
|
|
|
if (!LangOpts.MicrosoftExt) {
|
2010-10-16 08:29:27 +08:00
|
|
|
if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
|
2008-03-12 08:25:36 +08:00
|
|
|
ResultStr += "struct ";
|
|
|
|
}
|
|
|
|
// When rewriting for Microsoft, explicitly omit the structure name.
|
2010-10-16 08:29:27 +08:00
|
|
|
ResultStr += IDecl->getNameAsString();
|
2008-03-11 07:16:54 +08:00
|
|
|
ResultStr += " *";
|
2007-11-14 02:44:14 +08:00
|
|
|
}
|
|
|
|
else
|
2010-07-01 03:16:53 +08:00
|
|
|
ResultStr += Context->getObjCClassType().getAsString(
|
2011-09-28 06:38:19 +08:00
|
|
|
Context->getPrintingPolicy());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-14 02:44:14 +08:00
|
|
|
ResultStr += " self, ";
|
2011-09-28 06:38:19 +08:00
|
|
|
ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
|
2007-11-14 02:44:14 +08:00
|
|
|
ResultStr += " _cmd";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-14 02:44:14 +08:00
|
|
|
// Method arguments.
|
2009-02-21 02:43:26 +08:00
|
|
|
for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
|
|
|
|
E = OMD->param_end(); PI != E; ++PI) {
|
|
|
|
ParmVarDecl *PDecl = *PI;
|
2007-11-14 02:44:14 +08:00
|
|
|
ResultStr += ", ";
|
2008-04-19 05:13:19 +08:00
|
|
|
if (PDecl->getType()->isObjCQualifiedIdType()) {
|
|
|
|
ResultStr += "id ";
|
2008-11-24 13:29:24 +08:00
|
|
|
ResultStr += PDecl->getNameAsString();
|
2008-04-19 05:13:19 +08:00
|
|
|
} else {
|
2008-11-24 13:29:24 +08:00
|
|
|
std::string Name = PDecl->getNameAsString();
|
2010-05-26 01:12:52 +08:00
|
|
|
QualType QT = PDecl->getType();
|
|
|
|
// Make sure we convert "t (^)(...)" to "t (*)(...)".
|
|
|
|
if (convertBlockPointerToFunctionPointer(QT))
|
2011-09-28 06:38:19 +08:00
|
|
|
QT.getAsStringInternal(Name, Context->getPrintingPolicy());
|
2010-05-26 01:12:52 +08:00
|
|
|
else
|
2011-09-28 06:38:19 +08:00
|
|
|
PDecl->getType().getAsStringInternal(Name, Context->getPrintingPolicy());
|
2008-04-19 05:13:19 +08:00
|
|
|
ResultStr += Name;
|
|
|
|
}
|
2007-11-14 02:44:14 +08:00
|
|
|
}
|
2008-01-22 04:14:23 +08:00
|
|
|
if (OMD->isVariadic())
|
|
|
|
ResultStr += ", ...";
|
2008-01-10 09:39:52 +08:00
|
|
|
ResultStr += ") ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-07-16 22:40:40 +08:00
|
|
|
if (FPRetType) {
|
|
|
|
ResultStr += ")"; // close the precedence "scope" for "*".
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-07-16 22:40:40 +08:00
|
|
|
// Now, emit the argument types (if any).
|
2009-02-27 07:50:07 +08:00
|
|
|
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
|
2008-07-16 22:40:40 +08:00
|
|
|
ResultStr += "(";
|
|
|
|
for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
|
|
|
|
if (i) ResultStr += ", ";
|
2010-07-01 03:16:53 +08:00
|
|
|
std::string ParamStr = FT->getArgType(i).getAsString(
|
2011-09-28 06:38:19 +08:00
|
|
|
Context->getPrintingPolicy());
|
2008-07-16 22:40:40 +08:00
|
|
|
ResultStr += ParamStr;
|
|
|
|
}
|
|
|
|
if (FT->isVariadic()) {
|
|
|
|
if (FT->getNumArgs()) ResultStr += ", ";
|
|
|
|
ResultStr += "...";
|
|
|
|
}
|
|
|
|
ResultStr += ")";
|
|
|
|
} else {
|
|
|
|
ResultStr += "()";
|
|
|
|
}
|
|
|
|
}
|
2007-11-14 02:44:14 +08:00
|
|
|
}
|
2009-01-20 09:17:11 +08:00
|
|
|
void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
|
2008-01-08 03:49:32 +08:00
|
|
|
ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
|
|
|
|
ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-16 05:11:41 +08:00
|
|
|
InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// ");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
for (ObjCCategoryImplDecl::instmeth_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(),
|
|
|
|
E = IMD ? IMD->instmeth_end() : CID->instmeth_end();
|
2009-04-23 09:02:12 +08:00
|
|
|
I != E; ++I) {
|
2007-11-14 02:44:14 +08:00
|
|
|
std::string ResultStr;
|
2008-01-08 03:49:32 +08:00
|
|
|
ObjCMethodDecl *OMD = *I;
|
2010-10-16 08:29:27 +08:00
|
|
|
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
2007-11-14 02:44:14 +08:00
|
|
|
SourceLocation LocStart = OMD->getLocStart();
|
2009-06-30 10:35:26 +08:00
|
|
|
SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
|
2009-04-27 04:35:05 +08:00
|
|
|
|
2007-11-14 02:44:14 +08:00
|
|
|
const char *startBuf = SM->getCharacterData(LocStart);
|
|
|
|
const char *endBuf = SM->getCharacterData(LocEnd);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, endBuf-startBuf, ResultStr);
|
2007-11-14 02:44:14 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-08 03:49:32 +08:00
|
|
|
for (ObjCCategoryImplDecl::classmeth_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(),
|
|
|
|
E = IMD ? IMD->classmeth_end() : CID->classmeth_end();
|
2009-04-23 09:02:12 +08:00
|
|
|
I != E; ++I) {
|
2007-11-14 02:44:14 +08:00
|
|
|
std::string ResultStr;
|
2008-01-08 03:49:32 +08:00
|
|
|
ObjCMethodDecl *OMD = *I;
|
2010-10-16 08:29:27 +08:00
|
|
|
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
2007-11-14 02:44:14 +08:00
|
|
|
SourceLocation LocStart = OMD->getLocStart();
|
2009-06-30 10:35:26 +08:00
|
|
|
SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-14 02:44:14 +08:00
|
|
|
const char *startBuf = SM->getCharacterData(LocStart);
|
|
|
|
const char *endBuf = SM->getCharacterData(LocEnd);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, endBuf-startBuf, ResultStr);
|
2007-11-14 02:44:14 +08:00
|
|
|
}
|
2008-12-02 04:33:01 +08:00
|
|
|
for (ObjCCategoryImplDecl::propimpl_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(),
|
2009-09-09 23:08:12 +08:00
|
|
|
E = IMD ? IMD->propimpl_end() : CID->propimpl_end();
|
2009-04-23 09:02:12 +08:00
|
|
|
I != E; ++I) {
|
2008-12-03 01:36:43 +08:00
|
|
|
RewritePropertyImplDecl(*I, IMD, CID);
|
2008-12-02 04:33:01 +08:00
|
|
|
}
|
|
|
|
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// ");
|
2007-11-14 02:44:14 +08:00
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
|
2007-10-30 10:23:23 +08:00
|
|
|
std::string ResultStr;
|
2011-12-16 04:29:51 +08:00
|
|
|
if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) {
|
2007-11-01 11:35:41 +08:00
|
|
|
// we haven't seen a forward decl - generate a typedef.
|
2007-11-15 07:02:56 +08:00
|
|
|
ResultStr = "#ifndef _REWRITER_typedef_";
|
2008-11-24 13:29:24 +08:00
|
|
|
ResultStr += ClassDecl->getNameAsString();
|
2007-11-09 20:50:28 +08:00
|
|
|
ResultStr += "\n";
|
|
|
|
ResultStr += "#define _REWRITER_typedef_";
|
2008-11-24 13:29:24 +08:00
|
|
|
ResultStr += ClassDecl->getNameAsString();
|
2007-11-09 20:50:28 +08:00
|
|
|
ResultStr += "\n";
|
2008-03-11 07:16:54 +08:00
|
|
|
ResultStr += "typedef struct objc_object ";
|
2008-11-24 13:29:24 +08:00
|
|
|
ResultStr += ClassDecl->getNameAsString();
|
2007-11-09 20:50:28 +08:00
|
|
|
ResultStr += ";\n#endif\n";
|
2007-11-01 11:35:41 +08:00
|
|
|
// Mark this typedef as having been generated.
|
2011-12-16 04:29:51 +08:00
|
|
|
ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl());
|
2007-11-01 11:35:41 +08:00
|
|
|
}
|
2011-12-06 02:43:13 +08:00
|
|
|
RewriteObjCInternalStruct(ClassDecl, ResultStr);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(),
|
2009-06-30 10:36:12 +08:00
|
|
|
E = ClassDecl->prop_end(); I != E; ++I)
|
2009-01-11 09:06:09 +08:00
|
|
|
RewriteProperty(*I);
|
2009-09-09 23:08:12 +08:00
|
|
|
for (ObjCInterfaceDecl::instmeth_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
I != E; ++I)
|
2007-12-15 07:37:57 +08:00
|
|
|
RewriteMethodDeclaration(*I);
|
2009-09-09 23:08:12 +08:00
|
|
|
for (ObjCInterfaceDecl::classmeth_iterator
|
|
|
|
I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end();
|
2009-04-10 05:40:53 +08:00
|
|
|
I != E; ++I)
|
2007-12-15 07:37:57 +08:00
|
|
|
RewriteMethodDeclaration(*I);
|
|
|
|
|
2007-10-30 11:43:13 +08:00
|
|
|
// Lastly, comment out the @end.
|
2010-05-25 01:22:38 +08:00
|
|
|
ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
|
|
|
|
"/* @end */");
|
2007-10-27 04:53:56 +08:00
|
|
|
}
|
|
|
|
|
2011-11-06 17:01:30 +08:00
|
|
|
Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {
|
|
|
|
SourceRange OldRange = PseudoOp->getSourceRange();
|
|
|
|
|
|
|
|
// We just magically know some things about the structure of this
|
|
|
|
// expression.
|
|
|
|
ObjCMessageExpr *OldMsg =
|
|
|
|
cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(
|
|
|
|
PseudoOp->getNumSemanticExprs() - 1));
|
|
|
|
|
|
|
|
// Because the rewriter doesn't allow us to rewrite rewritten code,
|
|
|
|
// we need to suppress rewriting the sub-statements.
|
|
|
|
Expr *Base, *RHS;
|
|
|
|
{
|
|
|
|
DisableReplaceStmtScope S(*this);
|
|
|
|
|
|
|
|
// Rebuild the base expression if we have one.
|
|
|
|
Base = 0;
|
|
|
|
if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
|
|
|
|
Base = OldMsg->getInstanceReceiver();
|
|
|
|
Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
|
|
|
|
Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
|
2010-10-15 00:04:05 +08:00
|
|
|
}
|
2011-11-06 17:01:30 +08:00
|
|
|
|
|
|
|
// Rebuild the RHS.
|
|
|
|
RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS();
|
|
|
|
RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
|
|
|
|
RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: avoid this copy.
|
|
|
|
SmallVector<SourceLocation, 1> SelLocs;
|
|
|
|
OldMsg->getSelectorLocs(SelLocs);
|
|
|
|
|
2012-01-07 04:05:14 +08:00
|
|
|
ObjCMessageExpr *NewMsg = 0;
|
2011-11-06 17:01:30 +08:00
|
|
|
switch (OldMsg->getReceiverKind()) {
|
|
|
|
case ObjCMessageExpr::Class:
|
|
|
|
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
|
|
|
|
OldMsg->getValueKind(),
|
|
|
|
OldMsg->getLeftLoc(),
|
|
|
|
OldMsg->getClassReceiverTypeInfo(),
|
|
|
|
OldMsg->getSelector(),
|
|
|
|
SelLocs,
|
|
|
|
OldMsg->getMethodDecl(),
|
|
|
|
RHS,
|
2012-01-12 10:34:39 +08:00
|
|
|
OldMsg->getRightLoc(),
|
|
|
|
OldMsg->isImplicit());
|
2011-11-06 17:01:30 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::Instance:
|
|
|
|
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
|
|
|
|
OldMsg->getValueKind(),
|
|
|
|
OldMsg->getLeftLoc(),
|
|
|
|
Base,
|
|
|
|
OldMsg->getSelector(),
|
|
|
|
SelLocs,
|
|
|
|
OldMsg->getMethodDecl(),
|
|
|
|
RHS,
|
2012-01-12 10:34:39 +08:00
|
|
|
OldMsg->getRightLoc(),
|
|
|
|
OldMsg->isImplicit());
|
2011-11-06 17:01:30 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::SuperClass:
|
|
|
|
case ObjCMessageExpr::SuperInstance:
|
|
|
|
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
|
|
|
|
OldMsg->getValueKind(),
|
|
|
|
OldMsg->getLeftLoc(),
|
|
|
|
OldMsg->getSuperLoc(),
|
|
|
|
OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
|
|
|
|
OldMsg->getSuperType(),
|
|
|
|
OldMsg->getSelector(),
|
|
|
|
SelLocs,
|
|
|
|
OldMsg->getMethodDecl(),
|
|
|
|
RHS,
|
2012-01-12 10:34:39 +08:00
|
|
|
OldMsg->getRightLoc(),
|
|
|
|
OldMsg->isImplicit());
|
2011-11-06 17:01:30 +08:00
|
|
|
break;
|
2010-10-12 05:29:12 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-11-06 17:01:30 +08:00
|
|
|
Stmt *Replacement = SynthMessageExpr(NewMsg);
|
|
|
|
ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
|
|
|
|
return Replacement;
|
2008-12-03 08:56:33 +08:00
|
|
|
}
|
|
|
|
|
2011-11-06 17:01:30 +08:00
|
|
|
Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {
|
|
|
|
SourceRange OldRange = PseudoOp->getSourceRange();
|
|
|
|
|
|
|
|
// We just magically know some things about the structure of this
|
|
|
|
// expression.
|
|
|
|
ObjCMessageExpr *OldMsg =
|
|
|
|
cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());
|
|
|
|
|
|
|
|
// Because the rewriter doesn't allow us to rewrite rewritten code,
|
|
|
|
// we need to suppress rewriting the sub-statements.
|
|
|
|
Expr *Base = 0;
|
|
|
|
{
|
|
|
|
DisableReplaceStmtScope S(*this);
|
|
|
|
|
|
|
|
// Rebuild the base expression if we have one.
|
|
|
|
if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
|
|
|
|
Base = OldMsg->getInstanceReceiver();
|
|
|
|
Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
|
|
|
|
Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
|
2010-10-15 00:04:05 +08:00
|
|
|
}
|
2008-12-09 00:43:47 +08:00
|
|
|
}
|
2011-11-06 17:01:30 +08:00
|
|
|
|
|
|
|
// Intentionally empty.
|
|
|
|
SmallVector<SourceLocation, 1> SelLocs;
|
|
|
|
SmallVector<Expr*, 1> Args;
|
|
|
|
|
2012-01-07 04:05:14 +08:00
|
|
|
ObjCMessageExpr *NewMsg = 0;
|
2011-11-06 17:01:30 +08:00
|
|
|
switch (OldMsg->getReceiverKind()) {
|
|
|
|
case ObjCMessageExpr::Class:
|
|
|
|
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
|
|
|
|
OldMsg->getValueKind(),
|
|
|
|
OldMsg->getLeftLoc(),
|
|
|
|
OldMsg->getClassReceiverTypeInfo(),
|
|
|
|
OldMsg->getSelector(),
|
|
|
|
SelLocs,
|
|
|
|
OldMsg->getMethodDecl(),
|
|
|
|
Args,
|
2012-01-12 10:34:39 +08:00
|
|
|
OldMsg->getRightLoc(),
|
|
|
|
OldMsg->isImplicit());
|
2011-11-06 17:01:30 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::Instance:
|
|
|
|
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
|
|
|
|
OldMsg->getValueKind(),
|
|
|
|
OldMsg->getLeftLoc(),
|
|
|
|
Base,
|
|
|
|
OldMsg->getSelector(),
|
|
|
|
SelLocs,
|
|
|
|
OldMsg->getMethodDecl(),
|
|
|
|
Args,
|
2012-01-12 10:34:39 +08:00
|
|
|
OldMsg->getRightLoc(),
|
|
|
|
OldMsg->isImplicit());
|
2011-11-06 17:01:30 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::SuperClass:
|
|
|
|
case ObjCMessageExpr::SuperInstance:
|
|
|
|
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
|
|
|
|
OldMsg->getValueKind(),
|
|
|
|
OldMsg->getLeftLoc(),
|
|
|
|
OldMsg->getSuperLoc(),
|
|
|
|
OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
|
|
|
|
OldMsg->getSuperType(),
|
|
|
|
OldMsg->getSelector(),
|
|
|
|
SelLocs,
|
|
|
|
OldMsg->getMethodDecl(),
|
|
|
|
Args,
|
2012-01-12 10:34:39 +08:00
|
|
|
OldMsg->getRightLoc(),
|
|
|
|
OldMsg->isImplicit());
|
2011-11-06 17:01:30 +08:00
|
|
|
break;
|
2008-12-09 00:43:47 +08:00
|
|
|
}
|
2011-11-06 17:01:30 +08:00
|
|
|
|
|
|
|
Stmt *Replacement = SynthMessageExpr(NewMsg);
|
|
|
|
ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
|
|
|
|
return Replacement;
|
2008-12-03 08:56:33 +08:00
|
|
|
}
|
|
|
|
|
2008-10-29 04:29:00 +08:00
|
|
|
/// SynthCountByEnumWithState - To print:
|
|
|
|
/// ((unsigned int (*)
|
|
|
|
/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
|
2009-09-09 23:08:12 +08:00
|
|
|
/// (void *)objc_msgSend)((id)l_collection,
|
2008-10-29 04:29:00 +08:00
|
|
|
/// sel_registerName(
|
2009-09-09 23:08:12 +08:00
|
|
|
/// "countByEnumeratingWithState:objects:count:"),
|
|
|
|
/// &enumState,
|
2011-11-10 01:41:43 +08:00
|
|
|
/// (id *)__rw_items, (unsigned int)16)
|
2008-10-29 04:29:00 +08:00
|
|
|
///
|
|
|
|
void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
|
|
|
|
buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
|
|
|
|
"id *, unsigned int))(void *)objc_msgSend)";
|
|
|
|
buf += "\n\t\t";
|
|
|
|
buf += "((id)l_collection,\n\t\t";
|
|
|
|
buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
|
|
|
|
buf += "\n\t\t";
|
|
|
|
buf += "&enumState, "
|
2011-11-10 01:41:43 +08:00
|
|
|
"(id *)__rw_items, (unsigned int)16)";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2007-11-05 22:50:49 +08:00
|
|
|
|
2008-10-29 04:29:00 +08:00
|
|
|
/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
|
|
|
|
/// statement to exit to its outer synthesized loop.
|
|
|
|
///
|
|
|
|
Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {
|
|
|
|
if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
|
|
|
|
return S;
|
|
|
|
// replace break with goto __break_label
|
|
|
|
std::string buf;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-10-29 04:29:00 +08:00
|
|
|
SourceLocation startLoc = S->getLocStart();
|
|
|
|
buf = "goto __break_label_";
|
|
|
|
buf += utostr(ObjCBcLabelNo.back());
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, strlen("break"), buf);
|
2007-11-07 23:32:26 +08:00
|
|
|
|
2008-10-29 04:29:00 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2008-01-30 06:59:37 +08:00
|
|
|
|
2008-10-29 04:29:00 +08:00
|
|
|
/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
|
|
|
|
/// statement to continue with its inner synthesized loop.
|
|
|
|
///
|
|
|
|
Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {
|
|
|
|
if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
|
|
|
|
return S;
|
|
|
|
// replace continue with goto __continue_label
|
|
|
|
std::string buf;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-10-29 04:29:00 +08:00
|
|
|
SourceLocation startLoc = S->getLocStart();
|
|
|
|
buf = "goto __continue_label_";
|
|
|
|
buf += utostr(ObjCBcLabelNo.back());
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, strlen("continue"), buf);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-16 07:58:23 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-01-30 06:59:37 +08:00
|
|
|
/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
|
2008-01-08 05:40:22 +08:00
|
|
|
/// It rewrites:
|
|
|
|
/// for ( type elem in collection) { stmts; }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-08 05:40:22 +08:00
|
|
|
/// Into:
|
|
|
|
/// {
|
2009-09-09 23:08:12 +08:00
|
|
|
/// type elem;
|
2008-01-09 06:06:28 +08:00
|
|
|
/// struct __objcFastEnumerationState enumState = { 0 };
|
2011-11-10 01:41:43 +08:00
|
|
|
/// id __rw_items[16];
|
2008-01-09 06:06:28 +08:00
|
|
|
/// id l_collection = (id)collection;
|
2009-09-09 23:08:12 +08:00
|
|
|
/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
|
2011-11-10 01:41:43 +08:00
|
|
|
/// objects:__rw_items count:16];
|
2008-01-08 05:40:22 +08:00
|
|
|
/// if (limit) {
|
|
|
|
/// unsigned long startMutations = *enumState.mutationsPtr;
|
|
|
|
/// do {
|
|
|
|
/// unsigned long counter = 0;
|
|
|
|
/// do {
|
2009-09-09 23:08:12 +08:00
|
|
|
/// if (startMutations != *enumState.mutationsPtr)
|
2008-01-09 06:06:28 +08:00
|
|
|
/// objc_enumerationMutation(l_collection);
|
2008-01-10 02:15:42 +08:00
|
|
|
/// elem = (type)enumState.itemsPtr[counter++];
|
2008-01-08 05:40:22 +08:00
|
|
|
/// stmts;
|
2008-01-16 07:58:23 +08:00
|
|
|
/// __continue_label: ;
|
2008-01-08 05:40:22 +08:00
|
|
|
/// } while (counter < limit);
|
2009-09-09 23:08:12 +08:00
|
|
|
/// } while (limit = [l_collection countByEnumeratingWithState:&enumState
|
2011-11-10 01:41:43 +08:00
|
|
|
/// objects:__rw_items count:16]);
|
2008-01-09 06:06:28 +08:00
|
|
|
/// elem = nil;
|
2008-01-16 07:58:23 +08:00
|
|
|
/// __break_label: ;
|
2008-01-08 05:40:22 +08:00
|
|
|
/// }
|
|
|
|
/// else
|
|
|
|
/// elem = nil;
|
|
|
|
/// }
|
|
|
|
///
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
|
2008-01-31 13:10:40 +08:00
|
|
|
SourceLocation OrigEnd) {
|
2008-01-16 07:58:23 +08:00
|
|
|
assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
|
2008-01-16 07:58:23 +08:00
|
|
|
"ObjCForCollectionStmt Statement stack mismatch");
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(!ObjCBcLabelNo.empty() &&
|
2008-01-16 07:58:23 +08:00
|
|
|
"ObjCForCollectionStmt - Label No stack empty");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-09 06:06:28 +08:00
|
|
|
SourceLocation startLoc = S->getLocStart();
|
|
|
|
const char *startBuf = SM->getCharacterData(startLoc);
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef elementName;
|
2008-01-10 02:15:42 +08:00
|
|
|
std::string elementTypeAsString;
|
2008-01-09 06:06:28 +08:00
|
|
|
std::string buf;
|
|
|
|
buf = "\n{\n\t";
|
|
|
|
if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
|
|
|
|
// type elem;
|
2009-03-28 14:33:19 +08:00
|
|
|
NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
|
2008-10-07 06:16:13 +08:00
|
|
|
QualType ElementType = cast<ValueDecl>(D)->getType();
|
2009-12-05 05:18:19 +08:00
|
|
|
if (ElementType->isObjCQualifiedIdType() ||
|
|
|
|
ElementType->isObjCQualifiedInterfaceType())
|
|
|
|
// Simply use 'id' for all qualified types.
|
|
|
|
elementTypeAsString = "id";
|
|
|
|
else
|
2011-09-28 06:38:19 +08:00
|
|
|
elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());
|
2008-01-10 02:15:42 +08:00
|
|
|
buf += elementTypeAsString;
|
2008-01-09 06:06:28 +08:00
|
|
|
buf += " ";
|
2010-08-18 06:39:59 +08:00
|
|
|
elementName = D->getName();
|
2008-01-09 06:06:28 +08:00
|
|
|
buf += elementName;
|
|
|
|
buf += ";\n\t";
|
|
|
|
}
|
2008-04-08 13:52:18 +08:00
|
|
|
else {
|
|
|
|
DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
|
2010-08-18 06:39:59 +08:00
|
|
|
elementName = DR->getDecl()->getName();
|
2009-12-05 05:18:19 +08:00
|
|
|
ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
|
|
|
|
if (VD->getType()->isObjCQualifiedIdType() ||
|
|
|
|
VD->getType()->isObjCQualifiedInterfaceType())
|
|
|
|
// Simply use 'id' for all qualified types.
|
|
|
|
elementTypeAsString = "id";
|
|
|
|
else
|
2011-09-28 06:38:19 +08:00
|
|
|
elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());
|
2008-01-10 02:15:42 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-09 06:06:28 +08:00
|
|
|
// struct __objcFastEnumerationState enumState = { 0 };
|
|
|
|
buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
|
2011-11-10 01:41:43 +08:00
|
|
|
// id __rw_items[16];
|
|
|
|
buf += "id __rw_items[16];\n\t";
|
2008-01-09 06:06:28 +08:00
|
|
|
// id l_collection = (id)
|
|
|
|
buf += "id l_collection = (id)";
|
2008-01-10 08:24:29 +08:00
|
|
|
// Find start location of 'collection' the hard way!
|
|
|
|
const char *startCollectionBuf = startBuf;
|
|
|
|
startCollectionBuf += 3; // skip 'for'
|
|
|
|
startCollectionBuf = strchr(startCollectionBuf, '(');
|
|
|
|
startCollectionBuf++; // skip '('
|
|
|
|
// find 'in' and skip it.
|
|
|
|
while (*startCollectionBuf != ' ' ||
|
|
|
|
*(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
|
|
|
|
(*(startCollectionBuf+3) != ' ' &&
|
|
|
|
*(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
|
|
|
|
startCollectionBuf++;
|
|
|
|
startCollectionBuf += 3;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// Replace: "for (type element in" with string constructed thus far.
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
|
2008-01-09 06:06:28 +08:00
|
|
|
// Replace ')' in for '(' type elem in collection ')' with ';'
|
2008-01-10 08:24:29 +08:00
|
|
|
SourceLocation rightParenLoc = S->getRParenLoc();
|
|
|
|
const char *rparenBuf = SM->getCharacterData(rightParenLoc);
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);
|
2008-01-09 06:06:28 +08:00
|
|
|
buf = ";\n\t";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-09 06:06:28 +08:00
|
|
|
// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
|
2011-11-10 01:41:43 +08:00
|
|
|
// objects:__rw_items count:16];
|
2008-01-09 06:06:28 +08:00
|
|
|
// which is synthesized into:
|
2009-09-09 23:08:12 +08:00
|
|
|
// unsigned int limit =
|
2008-01-09 06:06:28 +08:00
|
|
|
// ((unsigned int (*)
|
|
|
|
// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
|
2009-09-09 23:08:12 +08:00
|
|
|
// (void *)objc_msgSend)((id)l_collection,
|
2008-01-09 06:06:28 +08:00
|
|
|
// sel_registerName(
|
2009-09-09 23:08:12 +08:00
|
|
|
// "countByEnumeratingWithState:objects:count:"),
|
|
|
|
// (struct __objcFastEnumerationState *)&state,
|
2011-11-10 01:41:43 +08:00
|
|
|
// (id *)__rw_items, (unsigned int)16);
|
2008-01-09 06:06:28 +08:00
|
|
|
buf += "unsigned long limit =\n\t\t";
|
|
|
|
SynthCountByEnumWithState(buf);
|
|
|
|
buf += ";\n\t";
|
|
|
|
/// if (limit) {
|
|
|
|
/// unsigned long startMutations = *enumState.mutationsPtr;
|
|
|
|
/// do {
|
|
|
|
/// unsigned long counter = 0;
|
|
|
|
/// do {
|
2009-09-09 23:08:12 +08:00
|
|
|
/// if (startMutations != *enumState.mutationsPtr)
|
2008-01-09 06:06:28 +08:00
|
|
|
/// objc_enumerationMutation(l_collection);
|
2008-01-10 02:15:42 +08:00
|
|
|
/// elem = (type)enumState.itemsPtr[counter++];
|
2008-01-09 06:06:28 +08:00
|
|
|
buf += "if (limit) {\n\t";
|
|
|
|
buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
|
|
|
|
buf += "do {\n\t\t";
|
|
|
|
buf += "unsigned long counter = 0;\n\t\t";
|
|
|
|
buf += "do {\n\t\t\t";
|
|
|
|
buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
|
|
|
|
buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
|
|
|
|
buf += elementName;
|
2008-01-10 02:15:42 +08:00
|
|
|
buf += " = (";
|
|
|
|
buf += elementTypeAsString;
|
|
|
|
buf += ")enumState.itemsPtr[counter++];";
|
2008-01-09 06:06:28 +08:00
|
|
|
// Replace ')' in for '(' type elem in collection ')' with all of these.
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(lparenLoc, 1, buf);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-16 07:58:23 +08:00
|
|
|
/// __continue_label: ;
|
2008-01-09 06:06:28 +08:00
|
|
|
/// } while (counter < limit);
|
2009-09-09 23:08:12 +08:00
|
|
|
/// } while (limit = [l_collection countByEnumeratingWithState:&enumState
|
2011-11-10 01:41:43 +08:00
|
|
|
/// objects:__rw_items count:16]);
|
2008-01-09 06:06:28 +08:00
|
|
|
/// elem = nil;
|
2008-01-16 07:58:23 +08:00
|
|
|
/// __break_label: ;
|
2008-01-09 06:06:28 +08:00
|
|
|
/// }
|
|
|
|
/// else
|
|
|
|
/// elem = nil;
|
|
|
|
/// }
|
2009-09-09 23:08:12 +08:00
|
|
|
///
|
2008-01-16 07:58:23 +08:00
|
|
|
buf = ";\n\t";
|
|
|
|
buf += "__continue_label_";
|
|
|
|
buf += utostr(ObjCBcLabelNo.back());
|
|
|
|
buf += ": ;";
|
|
|
|
buf += "\n\t\t";
|
2008-01-09 06:06:28 +08:00
|
|
|
buf += "} while (counter < limit);\n\t";
|
|
|
|
buf += "} while (limit = ";
|
|
|
|
SynthCountByEnumWithState(buf);
|
|
|
|
buf += ");\n\t";
|
|
|
|
buf += elementName;
|
2010-01-08 09:29:44 +08:00
|
|
|
buf += " = ((";
|
|
|
|
buf += elementTypeAsString;
|
|
|
|
buf += ")0);\n\t";
|
2008-01-16 07:58:23 +08:00
|
|
|
buf += "__break_label_";
|
|
|
|
buf += utostr(ObjCBcLabelNo.back());
|
|
|
|
buf += ": ;\n\t";
|
2008-01-09 06:06:28 +08:00
|
|
|
buf += "}\n\t";
|
|
|
|
buf += "else\n\t\t";
|
|
|
|
buf += elementName;
|
2010-01-08 09:29:44 +08:00
|
|
|
buf += " = ((";
|
|
|
|
buf += elementTypeAsString;
|
|
|
|
buf += ")0);\n\t";
|
2008-01-09 06:06:28 +08:00
|
|
|
buf += "}\n";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-09 06:06:28 +08:00
|
|
|
// Insert all these *after* the statement body.
|
2009-04-27 04:35:05 +08:00
|
|
|
// FIXME: If this should support Obj-C++, support CXXTryStmt
|
2008-07-22 02:26:02 +08:00
|
|
|
if (isa<CompoundStmt>(S->getBody())) {
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(endBodyLoc, buf);
|
2008-07-22 02:26:02 +08:00
|
|
|
} else {
|
|
|
|
/* Need to treat single statements specially. For example:
|
|
|
|
*
|
|
|
|
* for (A *a in b) if (stuff()) break;
|
|
|
|
* for (A *a in b) xxxyy;
|
|
|
|
*
|
|
|
|
* The following code simply scans ahead to the semi to find the actual end.
|
|
|
|
*/
|
|
|
|
const char *stmtBuf = SM->getCharacterData(OrigEnd);
|
|
|
|
const char *semiBuf = strchr(stmtBuf, ';');
|
|
|
|
assert(semiBuf && "Can't find ';'");
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(endBodyLoc, buf);
|
2008-07-22 02:26:02 +08:00
|
|
|
}
|
2008-01-16 07:58:23 +08:00
|
|
|
Stmts.pop_back();
|
|
|
|
ObjCBcLabelNo.pop_back();
|
2008-01-09 06:06:28 +08:00
|
|
|
return 0;
|
2008-01-08 05:40:22 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// RewriteObjCSynchronizedStmt -
|
2008-01-30 06:59:37 +08:00
|
|
|
/// This routine rewrites @synchronized(expr) stmt;
|
|
|
|
/// into:
|
|
|
|
/// objc_sync_enter(expr);
|
|
|
|
/// @try stmt @finally { objc_sync_exit(expr); }
|
|
|
|
///
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
|
2008-01-30 06:59:37 +08:00
|
|
|
// Get the start location and compute the semi location.
|
|
|
|
SourceLocation startLoc = S->getLocStart();
|
|
|
|
const char *startBuf = SM->getCharacterData(startLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-01-30 06:59:37 +08:00
|
|
|
assert((*startBuf == '@') && "bogus @synchronized location");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
std::string buf;
|
2008-08-21 21:03:03 +08:00
|
|
|
buf = "objc_sync_enter((id)";
|
|
|
|
const char *lparenBuf = startBuf;
|
|
|
|
while (*lparenBuf != '(') lparenBuf++;
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
|
2009-09-09 23:08:12 +08:00
|
|
|
// We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
|
|
|
|
// the sync expression is typically a message expression that's already
|
2008-08-19 21:04:19 +08:00
|
|
|
// been rewritten! (which implies the SourceLocation's are invalid).
|
|
|
|
SourceLocation endLoc = S->getSynchBody()->getLocStart();
|
2008-01-30 06:59:37 +08:00
|
|
|
const char *endBuf = SM->getCharacterData(endLoc);
|
2008-08-19 21:04:19 +08:00
|
|
|
while (*endBuf != ')') endBuf--;
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf);
|
2008-01-30 06:59:37 +08:00
|
|
|
buf = ");\n";
|
|
|
|
// declare a new scope with two variables, _stack and _rethrow.
|
|
|
|
buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";
|
|
|
|
buf += "int buf[18/*32-bit i386*/];\n";
|
|
|
|
buf += "char *pointers[4];} _stack;\n";
|
|
|
|
buf += "id volatile _rethrow = 0;\n";
|
|
|
|
buf += "objc_exception_try_enter(&_stack);\n";
|
|
|
|
buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(rparenLoc, 1, buf);
|
2008-01-30 06:59:37 +08:00
|
|
|
startLoc = S->getSynchBody()->getLocEnd();
|
|
|
|
startBuf = SM->getCharacterData(startLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-08-19 21:04:19 +08:00
|
|
|
assert((*startBuf == '}') && "bogus @synchronized block");
|
2008-01-30 06:59:37 +08:00
|
|
|
SourceLocation lastCurlyLoc = startLoc;
|
|
|
|
buf = "}\nelse {\n";
|
|
|
|
buf += " _rethrow = objc_exception_extract(&_stack);\n";
|
2009-04-30 00:37:50 +08:00
|
|
|
buf += "}\n";
|
|
|
|
buf += "{ /* implicit finally clause */\n";
|
2008-01-30 06:59:37 +08:00
|
|
|
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
|
2009-12-06 05:43:12 +08:00
|
|
|
|
|
|
|
std::string syncBuf;
|
|
|
|
syncBuf += " objc_sync_exit(";
|
2011-09-09 13:25:32 +08:00
|
|
|
|
|
|
|
Expr *syncExpr = S->getSynchExpr();
|
|
|
|
CastKind CK = syncExpr->getType()->isObjCObjectPointerType()
|
|
|
|
? CK_BitCast :
|
|
|
|
syncExpr->getType()->isBlockPointerType()
|
|
|
|
? CK_BlockPointerToObjCPointerCast
|
|
|
|
: CK_CPointerToObjCPointerCast;
|
|
|
|
syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
|
|
|
|
CK, syncExpr);
|
2008-09-13 13:16:45 +08:00
|
|
|
std::string syncExprBufS;
|
|
|
|
llvm::raw_string_ostream syncExprBuf(syncExprBufS);
|
2009-06-30 09:26:17 +08:00
|
|
|
syncExpr->printPretty(syncExprBuf, *Context, 0,
|
|
|
|
PrintingPolicy(LangOpts));
|
2009-12-06 05:43:12 +08:00
|
|
|
syncBuf += syncExprBuf.str();
|
|
|
|
syncBuf += ");";
|
|
|
|
|
|
|
|
buf += syncBuf;
|
|
|
|
buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n";
|
2008-01-30 06:59:37 +08:00
|
|
|
buf += "}\n";
|
|
|
|
buf += "}";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(lastCurlyLoc, 1, buf);
|
2009-12-06 05:43:12 +08:00
|
|
|
|
|
|
|
bool hasReturns = false;
|
|
|
|
HasReturnStmts(S->getSynchBody(), hasReturns);
|
|
|
|
if (hasReturns)
|
|
|
|
RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
|
|
|
|
|
2008-01-30 06:59:37 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-12-06 05:43:12 +08:00
|
|
|
void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
|
|
|
|
{
|
2008-12-06 01:03:39 +08:00
|
|
|
// Perform a bottom up traversal of all children.
|
2011-02-13 12:07:26 +08:00
|
|
|
for (Stmt::child_range CI = S->children(); CI; ++CI)
|
2008-12-06 01:03:39 +08:00
|
|
|
if (*CI)
|
2009-12-06 05:43:12 +08:00
|
|
|
WarnAboutReturnGotoStmts(*CI);
|
2008-12-06 01:03:39 +08:00
|
|
|
|
2009-12-06 05:43:12 +08:00
|
|
|
if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
Diags.Report(Context->getFullLoc(S->getLocStart()),
|
2008-12-06 01:03:39 +08:00
|
|
|
TryFinallyContainsReturnDiag);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-06 05:43:12 +08:00
|
|
|
void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
|
|
|
|
{
|
|
|
|
// Perform a bottom up traversal of all children.
|
2011-02-13 12:07:26 +08:00
|
|
|
for (Stmt::child_range CI = S->children(); CI; ++CI)
|
2009-12-06 05:43:12 +08:00
|
|
|
if (*CI)
|
|
|
|
HasReturnStmts(*CI, hasReturns);
|
|
|
|
|
|
|
|
if (isa<ReturnStmt>(S))
|
|
|
|
hasReturns = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
|
|
|
|
// Perform a bottom up traversal of all children.
|
2011-02-13 12:07:26 +08:00
|
|
|
for (Stmt::child_range CI = S->children(); CI; ++CI)
|
2009-12-06 05:43:12 +08:00
|
|
|
if (*CI) {
|
|
|
|
RewriteTryReturnStmts(*CI);
|
|
|
|
}
|
|
|
|
if (isa<ReturnStmt>(S)) {
|
|
|
|
SourceLocation startLoc = S->getLocStart();
|
|
|
|
const char *startBuf = SM->getCharacterData(startLoc);
|
|
|
|
|
|
|
|
const char *semiBuf = strchr(startBuf, ';');
|
|
|
|
assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
|
2009-12-06 05:43:12 +08:00
|
|
|
|
|
|
|
std::string buf;
|
|
|
|
buf = "{ objc_exception_try_exit(&_stack); return";
|
|
|
|
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, 6, buf);
|
|
|
|
InsertText(onePastSemiLoc, "}");
|
2009-12-06 05:43:12 +08:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
|
|
|
|
// Perform a bottom up traversal of all children.
|
2011-02-13 12:07:26 +08:00
|
|
|
for (Stmt::child_range CI = S->children(); CI; ++CI)
|
2009-12-06 05:43:12 +08:00
|
|
|
if (*CI) {
|
|
|
|
RewriteSyncReturnStmts(*CI, syncExitBuf);
|
|
|
|
}
|
|
|
|
if (isa<ReturnStmt>(S)) {
|
|
|
|
SourceLocation startLoc = S->getLocStart();
|
|
|
|
const char *startBuf = SM->getCharacterData(startLoc);
|
|
|
|
|
|
|
|
const char *semiBuf = strchr(startBuf, ';');
|
|
|
|
assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
|
2009-12-06 05:43:12 +08:00
|
|
|
|
|
|
|
std::string buf;
|
|
|
|
buf = "{ objc_exception_try_exit(&_stack);";
|
|
|
|
buf += syncExitBuf;
|
|
|
|
buf += " return";
|
|
|
|
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, 6, buf);
|
|
|
|
InsertText(onePastSemiLoc, "}");
|
2009-12-06 05:43:12 +08:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
|
2007-11-07 12:08:17 +08:00
|
|
|
// Get the start location and compute the semi location.
|
|
|
|
SourceLocation startLoc = S->getLocStart();
|
|
|
|
const char *startBuf = SM->getCharacterData(startLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 12:08:17 +08:00
|
|
|
assert((*startBuf == '@') && "bogus @try location");
|
|
|
|
|
|
|
|
std::string buf;
|
|
|
|
// declare a new scope with two variables, _stack and _rethrow.
|
|
|
|
buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
|
|
|
|
buf += "int buf[18/*32-bit i386*/];\n";
|
|
|
|
buf += "char *pointers[4];} _stack;\n";
|
|
|
|
buf += "id volatile _rethrow = 0;\n";
|
|
|
|
buf += "objc_exception_try_enter(&_stack);\n";
|
2007-11-08 02:43:40 +08:00
|
|
|
buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
|
2007-11-07 12:08:17 +08:00
|
|
|
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, 4, buf);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 12:08:17 +08:00
|
|
|
startLoc = S->getTryBody()->getLocEnd();
|
|
|
|
startBuf = SM->getCharacterData(startLoc);
|
|
|
|
|
|
|
|
assert((*startBuf == '}') && "bogus @try block");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-07-16 23:31:30 +08:00
|
|
|
SourceLocation lastCurlyLoc = startLoc;
|
2010-04-24 06:50:49 +08:00
|
|
|
if (S->getNumCatchStmts()) {
|
2011-09-20 04:40:19 +08:00
|
|
|
startLoc = startLoc.getLocWithOffset(1);
|
2008-07-16 23:31:30 +08:00
|
|
|
buf = " /* @catch begin */ else {\n";
|
|
|
|
buf += " id _caught = objc_exception_extract(&_stack);\n";
|
|
|
|
buf += " objc_exception_try_enter (&_stack);\n";
|
|
|
|
buf += " if (_setjmp(_stack.buf))\n";
|
|
|
|
buf += " _rethrow = objc_exception_extract(&_stack);\n";
|
|
|
|
buf += " else { /* @catch continue */";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(startLoc, buf);
|
2008-09-10 03:59:12 +08:00
|
|
|
} else { /* no catch list */
|
|
|
|
buf = "}\nelse {\n";
|
|
|
|
buf += " _rethrow = objc_exception_extract(&_stack);\n";
|
|
|
|
buf += "}";
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(lastCurlyLoc, 1, buf);
|
2008-07-16 23:31:30 +08:00
|
|
|
}
|
2007-11-07 12:08:17 +08:00
|
|
|
Stmt *lastCatchBody = 0;
|
2010-04-24 06:50:49 +08:00
|
|
|
for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
|
|
|
|
ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
|
2010-04-27 00:46:50 +08:00
|
|
|
VarDecl *catchDecl = Catch->getCatchParamDecl();
|
2007-11-07 12:08:17 +08:00
|
|
|
|
2010-04-24 06:50:49 +08:00
|
|
|
if (I == 0)
|
2007-11-07 12:08:17 +08:00
|
|
|
buf = "if ("; // we are generating code for the first catch clause
|
|
|
|
else
|
|
|
|
buf = "else if (";
|
2010-04-24 06:50:49 +08:00
|
|
|
startLoc = Catch->getLocStart();
|
2007-11-07 12:08:17 +08:00
|
|
|
startBuf = SM->getCharacterData(startLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 12:08:17 +08:00
|
|
|
assert((*startBuf == '@') && "bogus @catch location");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 12:08:17 +08:00
|
|
|
const char *lParenLoc = strchr(startBuf, '(');
|
|
|
|
|
2010-04-24 06:50:49 +08:00
|
|
|
if (Catch->hasEllipsis()) {
|
2008-02-02 04:02:07 +08:00
|
|
|
// Now rewrite the body...
|
2010-04-24 06:50:49 +08:00
|
|
|
lastCatchBody = Catch->getCatchBody();
|
2008-02-02 04:02:07 +08:00
|
|
|
SourceLocation bodyLoc = lastCatchBody->getLocStart();
|
|
|
|
const char *bodyBuf = SM->getCharacterData(bodyLoc);
|
2010-04-24 06:50:49 +08:00
|
|
|
assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' &&
|
2008-04-08 13:52:18 +08:00
|
|
|
"bogus @catch paren location");
|
2008-02-02 04:02:07 +08:00
|
|
|
assert((*bodyBuf == '{') && "bogus @catch body location");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-02-02 04:02:07 +08:00
|
|
|
buf += "1) { id _tmp = _caught;";
|
2009-08-20 03:10:30 +08:00
|
|
|
Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
|
2009-03-04 03:52:17 +08:00
|
|
|
} else if (catchDecl) {
|
|
|
|
QualType t = catchDecl->getType();
|
2008-01-08 03:49:32 +08:00
|
|
|
if (t == Context->getObjCIdType()) {
|
2007-11-07 12:08:17 +08:00
|
|
|
buf += "1) { ";
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
|
2010-05-18 05:00:27 +08:00
|
|
|
} else if (const ObjCObjectPointerType *Ptr =
|
|
|
|
t->getAs<ObjCObjectPointerType>()) {
|
|
|
|
// Should be a pointer to a class.
|
|
|
|
ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
|
|
|
|
if (IDecl) {
|
2007-11-08 02:43:40 +08:00
|
|
|
buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
|
2010-05-18 05:00:27 +08:00
|
|
|
buf += IDecl->getNameAsString();
|
2007-11-08 02:43:40 +08:00
|
|
|
buf += "\"), (struct objc_object *)_caught)) { ";
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
|
2007-11-07 12:08:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Now rewrite the body...
|
2010-04-24 06:50:49 +08:00
|
|
|
lastCatchBody = Catch->getCatchBody();
|
|
|
|
SourceLocation rParenLoc = Catch->getRParenLoc();
|
2007-11-07 12:08:17 +08:00
|
|
|
SourceLocation bodyLoc = lastCatchBody->getLocStart();
|
|
|
|
const char *bodyBuf = SM->getCharacterData(bodyLoc);
|
|
|
|
const char *rParenBuf = SM->getCharacterData(rParenLoc);
|
|
|
|
assert((*rParenBuf == ')') && "bogus @catch paren location");
|
|
|
|
assert((*bodyBuf == '{') && "bogus @catch body location");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// Here we replace ") {" with "= _caught;" (which initializes and
|
2007-11-07 12:08:17 +08:00
|
|
|
// declares the @catch parameter).
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;");
|
2009-03-04 03:52:17 +08:00
|
|
|
} else {
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("@catch rewrite bug");
|
2007-11-07 23:32:26 +08:00
|
|
|
}
|
2007-11-07 12:08:17 +08:00
|
|
|
}
|
|
|
|
// Complete the catch list...
|
|
|
|
if (lastCatchBody) {
|
|
|
|
SourceLocation bodyLoc = lastCatchBody->getLocEnd();
|
2008-04-08 13:52:18 +08:00
|
|
|
assert(*SM->getCharacterData(bodyLoc) == '}' &&
|
|
|
|
"bogus @catch body location");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-09-11 23:29:03 +08:00
|
|
|
// Insert the last (implicit) else clause *before* the right curly brace.
|
2011-09-20 04:40:19 +08:00
|
|
|
bodyLoc = bodyLoc.getLocWithOffset(-1);
|
2008-09-11 23:29:03 +08:00
|
|
|
buf = "} /* last catch end */\n";
|
|
|
|
buf += "else {\n";
|
|
|
|
buf += " _rethrow = _caught;\n";
|
|
|
|
buf += " objc_exception_try_exit(&_stack);\n";
|
|
|
|
buf += "} } /* @catch end */\n";
|
|
|
|
if (!S->getFinallyStmt())
|
|
|
|
buf += "}\n";
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(bodyLoc, buf);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 12:08:17 +08:00
|
|
|
// Set lastCurlyLoc
|
|
|
|
lastCurlyLoc = lastCatchBody->getLocEnd();
|
|
|
|
}
|
2008-01-08 03:49:32 +08:00
|
|
|
if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
|
2007-11-07 12:08:17 +08:00
|
|
|
startLoc = finalStmt->getLocStart();
|
|
|
|
startBuf = SM->getCharacterData(startLoc);
|
|
|
|
assert((*startBuf == '@') && "bogus @finally start");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, 8, "/* @finally */");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 12:08:17 +08:00
|
|
|
Stmt *body = finalStmt->getFinallyBody();
|
|
|
|
SourceLocation startLoc = body->getLocStart();
|
|
|
|
SourceLocation endLoc = body->getLocEnd();
|
2008-04-08 13:52:18 +08:00
|
|
|
assert(*SM->getCharacterData(startLoc) == '{' &&
|
|
|
|
"bogus @finally body location");
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(*SM->getCharacterData(endLoc) == '}' &&
|
2008-04-08 13:52:18 +08:00
|
|
|
"bogus @finally body location");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-09-20 04:40:19 +08:00
|
|
|
startLoc = startLoc.getLocWithOffset(1);
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n");
|
2011-09-20 04:40:19 +08:00
|
|
|
endLoc = endLoc.getLocWithOffset(-1);
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 12:08:17 +08:00
|
|
|
// Set lastCurlyLoc
|
|
|
|
lastCurlyLoc = body->getLocEnd();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-12-06 01:03:39 +08:00
|
|
|
// Now check for any return/continue/go statements within the @try.
|
2009-12-06 05:43:12 +08:00
|
|
|
WarnAboutReturnGotoStmts(S->getTryBody());
|
2008-09-11 23:29:03 +08:00
|
|
|
} else { /* no finally clause - make sure we synthesize an implicit one */
|
|
|
|
buf = "{ /* implicit finally clause */\n";
|
|
|
|
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
|
|
|
|
buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
|
|
|
|
buf += "}";
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(lastCurlyLoc, 1, buf);
|
2009-12-06 05:43:12 +08:00
|
|
|
|
|
|
|
// Now check for any return/continue/go statements within the @try.
|
|
|
|
// The implicit finally clause won't called if the @try contains any
|
|
|
|
// jump statements.
|
|
|
|
bool hasReturns = false;
|
|
|
|
HasReturnStmts(S->getTryBody(), hasReturns);
|
|
|
|
if (hasReturns)
|
|
|
|
RewriteTryReturnStmts(S->getTryBody());
|
2007-11-07 12:08:17 +08:00
|
|
|
}
|
|
|
|
// Now emit the final closing curly brace...
|
2011-09-20 04:40:19 +08:00
|
|
|
lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1);
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(lastCurlyLoc, " } /* @try scope end */\n");
|
2007-11-06 01:47:33 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// This can't be done with ReplaceStmt(S, ThrowExpr), since
|
|
|
|
// the throw expression is typically a message expression that's already
|
2007-11-07 23:32:26 +08:00
|
|
|
// been rewritten! (which implies the SourceLocation's are invalid).
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
|
2007-11-07 23:32:26 +08:00
|
|
|
// Get the start location and compute the semi location.
|
|
|
|
SourceLocation startLoc = S->getLocStart();
|
|
|
|
const char *startBuf = SM->getCharacterData(startLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 23:32:26 +08:00
|
|
|
assert((*startBuf == '@') && "bogus @throw location");
|
|
|
|
|
|
|
|
std::string buf;
|
|
|
|
/* void objc_exception_throw(id) __attribute__((noreturn)); */
|
2008-01-19 08:42:38 +08:00
|
|
|
if (S->getThrowExpr())
|
|
|
|
buf = "objc_exception_throw(";
|
|
|
|
else // add an implicit argument
|
|
|
|
buf = "objc_exception_throw(_caught";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-07-25 23:41:30 +08:00
|
|
|
// handle "@ throw" correctly.
|
|
|
|
const char *wBuf = strchr(startBuf, 'w');
|
|
|
|
assert((*wBuf == 'w') && "@throw: can't find 'w'");
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(startLoc, wBuf-startBuf+1, buf);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-07 23:32:26 +08:00
|
|
|
const char *semiBuf = strchr(startBuf, ';');
|
|
|
|
assert((*semiBuf == ';') && "@throw: can't find ';'");
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(semiLoc, 1, ");");
|
2007-11-07 23:32:26 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2007-11-06 01:47:33 +08:00
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
|
2007-10-18 06:35:30 +08:00
|
|
|
// Create a new string expression.
|
|
|
|
QualType StrType = Context->getPointerType(Context->CharTy);
|
2007-10-29 13:01:08 +08:00
|
|
|
std::string StrEncoding;
|
2008-10-18 04:21:44 +08:00
|
|
|
Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
|
2011-06-21 23:13:30 +08:00
|
|
|
Expr *Replacement = StringLiteral::Create(*Context, StrEncoding,
|
2011-07-27 13:40:30 +08:00
|
|
|
StringLiteral::Ascii, false,
|
|
|
|
StrType, SourceLocation());
|
2008-02-01 03:37:57 +08:00
|
|
|
ReplaceStmt(Exp, Replacement);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-01 06:53:43 +08:00
|
|
|
// Replace this subexpr in the parent.
|
2010-10-12 05:29:12 +08:00
|
|
|
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
|
2007-10-25 00:57:36 +08:00
|
|
|
return Replacement;
|
2007-10-17 06:36:42 +08:00
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
|
2008-12-23 06:16:07 +08:00
|
|
|
if (!SelGetUidFunctionDecl)
|
|
|
|
SynthSelGetUidFunctionDecl();
|
2007-11-05 22:50:49 +08:00
|
|
|
assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
|
|
|
|
// Create a call to sel_registerName("selName").
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Expr*, 8> SelExprs;
|
2007-11-05 22:50:49 +08:00
|
|
|
QualType argType = Context->getPointerType(Context->CharTy);
|
2009-09-09 23:08:12 +08:00
|
|
|
SelExprs.push_back(StringLiteral::Create(*Context,
|
2011-06-21 23:13:30 +08:00
|
|
|
Exp->getSelector().getAsString(),
|
2011-07-27 13:40:30 +08:00
|
|
|
StringLiteral::Ascii, false,
|
|
|
|
argType, SourceLocation()));
|
2007-11-05 22:50:49 +08:00
|
|
|
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
|
|
|
|
&SelExprs[0], SelExprs.size());
|
2008-02-01 03:37:57 +08:00
|
|
|
ReplaceStmt(Exp, SelExp);
|
2010-10-12 05:29:12 +08:00
|
|
|
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
|
2007-11-05 22:50:49 +08:00
|
|
|
return SelExp;
|
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
|
2010-02-23 04:48:10 +08:00
|
|
|
FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc,
|
|
|
|
SourceLocation EndLoc) {
|
2007-10-24 07:50:29 +08:00
|
|
|
// Get the type, we will need to reference it in a couple spots.
|
2007-10-25 06:48:43 +08:00
|
|
|
QualType msgSendType = FD->getType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-24 07:50:29 +08:00
|
|
|
// Create a reference to the objc_msgSend() declaration.
|
2010-11-18 14:31:45 +08:00
|
|
|
DeclRefExpr *DRE =
|
|
|
|
new (Context) DeclRefExpr(FD, msgSendType, VK_LValue, SourceLocation());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-24 07:50:29 +08:00
|
|
|
// Now, we cast the reference to a pointer to the objc_msgSend type.
|
2007-10-25 01:06:59 +08:00
|
|
|
QualType pToFunc = Context->getPointerType(msgSendType);
|
2010-04-24 06:18:37 +08:00
|
|
|
ImplicitCastExpr *ICE =
|
2010-11-15 17:46:46 +08:00
|
|
|
ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
|
2010-08-25 18:28:54 +08:00
|
|
|
DRE, 0, VK_RValue);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-22 07:43:11 +08:00
|
|
|
const FunctionType *FT = msgSendType->getAs<FunctionType>();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-23 04:48:10 +08:00
|
|
|
CallExpr *Exp =
|
2010-07-13 16:18:22 +08:00
|
|
|
new (Context) CallExpr(*Context, ICE, args, nargs,
|
2010-11-18 14:31:45 +08:00
|
|
|
FT->getCallResultType(*Context),
|
|
|
|
VK_RValue, EndLoc);
|
2010-02-23 04:48:10 +08:00
|
|
|
return Exp;
|
2007-10-25 06:48:43 +08:00
|
|
|
}
|
|
|
|
|
2007-11-01 21:24:47 +08:00
|
|
|
static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
|
|
|
|
const char *&startRef, const char *&endRef) {
|
|
|
|
while (startBuf < endBuf) {
|
|
|
|
if (*startBuf == '<')
|
|
|
|
startRef = startBuf; // mark the start.
|
|
|
|
if (*startBuf == '>') {
|
2007-11-09 20:50:28 +08:00
|
|
|
if (startRef && *startRef == '<') {
|
|
|
|
endRef = startBuf; // mark the end.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2007-11-01 21:24:47 +08:00
|
|
|
}
|
|
|
|
startBuf++;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-12-12 06:50:14 +08:00
|
|
|
static void scanToNextArgument(const char *&argRef) {
|
|
|
|
int angle = 0;
|
|
|
|
while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
|
|
|
|
if (*argRef == '<')
|
|
|
|
angle++;
|
|
|
|
else if (*argRef == '>')
|
|
|
|
angle--;
|
|
|
|
argRef++;
|
|
|
|
}
|
|
|
|
assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
|
|
|
|
}
|
2007-12-12 07:04:08 +08:00
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
bool RewriteObjC::needToScanForQualifiers(QualType T) {
|
2010-02-04 05:29:28 +08:00
|
|
|
if (T->isObjCQualifiedIdType())
|
|
|
|
return true;
|
2010-02-03 02:35:07 +08:00
|
|
|
if (const PointerType *PT = T->getAs<PointerType>()) {
|
|
|
|
if (PT->getPointeeType()->isObjCQualifiedIdType())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (T->isObjCObjectPointerType()) {
|
|
|
|
T = T->getPointeeType();
|
|
|
|
return T->isObjCQualifiedInterfaceType();
|
|
|
|
}
|
2010-10-01 04:41:32 +08:00
|
|
|
if (T->isArrayType()) {
|
|
|
|
QualType ElemTy = Context->getBaseElementType(T);
|
|
|
|
return needToScanForQualifiers(ElemTy);
|
|
|
|
}
|
2010-02-03 02:35:07 +08:00
|
|
|
return false;
|
2007-11-01 21:24:47 +08:00
|
|
|
}
|
|
|
|
|
2008-07-30 02:15:38 +08:00
|
|
|
void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
|
|
|
|
QualType Type = E->getType();
|
|
|
|
if (needToScanForQualifiers(Type)) {
|
2008-11-20 05:15:47 +08:00
|
|
|
SourceLocation Loc, EndLoc;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-11-20 05:15:47 +08:00
|
|
|
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
|
|
|
|
Loc = ECE->getLParenLoc();
|
|
|
|
EndLoc = ECE->getRParenLoc();
|
|
|
|
} else {
|
|
|
|
Loc = E->getLocStart();
|
|
|
|
EndLoc = E->getLocEnd();
|
|
|
|
}
|
|
|
|
// This will defend against trying to rewrite synthesized expressions.
|
|
|
|
if (Loc.isInvalid() || EndLoc.isInvalid())
|
|
|
|
return;
|
|
|
|
|
2008-07-30 02:15:38 +08:00
|
|
|
const char *startBuf = SM->getCharacterData(Loc);
|
2008-11-20 05:15:47 +08:00
|
|
|
const char *endBuf = SM->getCharacterData(EndLoc);
|
2008-07-30 02:15:38 +08:00
|
|
|
const char *startRef = 0, *endRef = 0;
|
|
|
|
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
|
|
|
|
// Get the locations of the startRef, endRef.
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
|
|
|
|
SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);
|
2008-07-30 02:15:38 +08:00
|
|
|
// Comment out the protocol references.
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(LessLoc, "/*");
|
|
|
|
InsertText(GreaterLoc, "*/");
|
2008-07-30 02:15:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
|
2007-12-12 06:50:14 +08:00
|
|
|
SourceLocation Loc;
|
|
|
|
QualType Type;
|
2009-02-27 07:50:07 +08:00
|
|
|
const FunctionProtoType *proto = 0;
|
2007-12-12 06:50:14 +08:00
|
|
|
if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
|
|
|
|
Loc = VD->getLocation();
|
|
|
|
Type = VD->getType();
|
|
|
|
}
|
|
|
|
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
|
|
|
|
Loc = FD->getLocation();
|
|
|
|
// Check for ObjC 'id' and class types that have been adorned with protocol
|
|
|
|
// information (id<p>, C<p>*). The protocol references need to be rewritten!
|
2009-09-22 07:43:11 +08:00
|
|
|
const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
|
2007-12-12 06:50:14 +08:00
|
|
|
assert(funcType && "missing function type");
|
2009-02-27 07:50:07 +08:00
|
|
|
proto = dyn_cast<FunctionProtoType>(funcType);
|
2007-12-12 06:50:14 +08:00
|
|
|
if (!proto)
|
|
|
|
return;
|
|
|
|
Type = proto->getResultType();
|
|
|
|
}
|
2009-12-05 23:55:59 +08:00
|
|
|
else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
|
|
|
|
Loc = FD->getLocation();
|
|
|
|
Type = FD->getType();
|
|
|
|
}
|
2007-12-12 06:50:14 +08:00
|
|
|
else
|
2007-12-12 03:56:36 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-12 06:50:14 +08:00
|
|
|
if (needToScanForQualifiers(Type)) {
|
2007-11-01 21:24:47 +08:00
|
|
|
// Since types are unique, we need to scan the buffer.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-01 21:24:47 +08:00
|
|
|
const char *endBuf = SM->getCharacterData(Loc);
|
|
|
|
const char *startBuf = endBuf;
|
2008-05-31 13:02:17 +08:00
|
|
|
while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
|
2007-11-01 21:24:47 +08:00
|
|
|
startBuf--; // scan backward (from the decl location) for return type.
|
|
|
|
const char *startRef = 0, *endRef = 0;
|
|
|
|
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
|
|
|
|
// Get the locations of the startRef, endRef.
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
|
|
|
|
SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);
|
2007-11-01 21:24:47 +08:00
|
|
|
// Comment out the protocol references.
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(LessLoc, "/*");
|
|
|
|
InsertText(GreaterLoc, "*/");
|
2007-11-01 21:24:47 +08:00
|
|
|
}
|
|
|
|
}
|
2007-12-12 06:50:14 +08:00
|
|
|
if (!proto)
|
|
|
|
return; // most likely, was a variable
|
2007-10-31 12:38:33 +08:00
|
|
|
// Now check arguments.
|
2007-12-12 06:50:14 +08:00
|
|
|
const char *startBuf = SM->getCharacterData(Loc);
|
|
|
|
const char *startFuncBuf = startBuf;
|
2007-10-31 12:38:33 +08:00
|
|
|
for (unsigned i = 0; i < proto->getNumArgs(); i++) {
|
2007-11-01 21:24:47 +08:00
|
|
|
if (needToScanForQualifiers(proto->getArgType(i))) {
|
|
|
|
// Since types are unique, we need to scan the buffer.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-01 21:24:47 +08:00
|
|
|
const char *endBuf = startBuf;
|
2007-12-12 06:50:14 +08:00
|
|
|
// scan forward (from the decl location) for argument types.
|
|
|
|
scanToNextArgument(endBuf);
|
2007-11-01 21:24:47 +08:00
|
|
|
const char *startRef = 0, *endRef = 0;
|
|
|
|
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
|
|
|
|
// Get the locations of the startRef, endRef.
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation LessLoc =
|
2011-09-20 04:40:19 +08:00
|
|
|
Loc.getLocWithOffset(startRef-startFuncBuf);
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation GreaterLoc =
|
2011-09-20 04:40:19 +08:00
|
|
|
Loc.getLocWithOffset(endRef-startFuncBuf+1);
|
2007-11-01 21:24:47 +08:00
|
|
|
// Comment out the protocol references.
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(LessLoc, "/*");
|
|
|
|
InsertText(GreaterLoc, "*/");
|
2007-11-01 21:24:47 +08:00
|
|
|
}
|
2007-12-12 06:50:14 +08:00
|
|
|
startBuf = ++endBuf;
|
|
|
|
}
|
|
|
|
else {
|
2008-08-06 23:58:23 +08:00
|
|
|
// If the function name is derived from a macro expansion, then the
|
|
|
|
// argument buffer will not follow the name. Need to speak with Chris.
|
|
|
|
while (*startBuf && *startBuf != ')' && *startBuf != ',')
|
2007-12-12 06:50:14 +08:00
|
|
|
startBuf++; // scan forward (from the decl location) for argument types.
|
|
|
|
startBuf++;
|
|
|
|
}
|
2007-10-31 12:38:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-11 02:54:22 +08:00
|
|
|
void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) {
|
|
|
|
QualType QT = ND->getType();
|
|
|
|
const Type* TypePtr = QT->getAs<Type>();
|
|
|
|
if (!isa<TypeOfExprType>(TypePtr))
|
|
|
|
return;
|
|
|
|
while (isa<TypeOfExprType>(TypePtr)) {
|
|
|
|
const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
|
|
|
|
QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
|
|
|
|
TypePtr = QT->getAs<Type>();
|
|
|
|
}
|
|
|
|
// FIXME. This will not work for multiple declarators; as in:
|
|
|
|
// __typeof__(a) b,c,d;
|
2011-09-28 06:38:19 +08:00
|
|
|
std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));
|
2010-02-11 02:54:22 +08:00
|
|
|
SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
|
|
|
|
const char *startBuf = SM->getCharacterData(DeclLoc);
|
|
|
|
if (ND->getInit()) {
|
|
|
|
std::string Name(ND->getNameAsString());
|
|
|
|
TypeAsString += " " + Name + " = ";
|
|
|
|
Expr *E = ND->getInit();
|
|
|
|
SourceLocation startLoc;
|
|
|
|
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
|
|
|
|
startLoc = ECE->getLParenLoc();
|
|
|
|
else
|
|
|
|
startLoc = E->getLocStart();
|
2011-07-26 00:49:02 +08:00
|
|
|
startLoc = SM->getExpansionLoc(startLoc);
|
2010-02-11 02:54:22 +08:00
|
|
|
const char *endBuf = SM->getCharacterData(startLoc);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
|
2010-02-11 02:54:22 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
SourceLocation X = ND->getLocEnd();
|
2011-07-26 00:49:02 +08:00
|
|
|
X = SM->getExpansionLoc(X);
|
2010-02-11 02:54:22 +08:00
|
|
|
const char *endBuf = SM->getCharacterData(X);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
|
2010-02-11 02:54:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-05 05:47:40 +08:00
|
|
|
// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthSelGetUidFunctionDecl() {
|
2007-12-05 05:47:40 +08:00
|
|
|
IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2009-09-25 03:53:00 +08:00
|
|
|
ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType getFuncType =
|
|
|
|
getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size());
|
2008-04-17 22:40:12 +08:00
|
|
|
SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
SelGetUidIdent, getFuncType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2007-12-05 05:47:40 +08:00
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
|
2007-10-31 07:14:51 +08:00
|
|
|
// declared in <objc/objc.h>
|
2009-01-09 09:47:02 +08:00
|
|
|
if (FD->getIdentifier() &&
|
2010-08-18 06:39:59 +08:00
|
|
|
FD->getName() == "sel_registerName") {
|
2007-10-31 07:14:51 +08:00
|
|
|
SelGetUidFunctionDecl = FD;
|
2007-10-31 12:38:33 +08:00
|
|
|
return;
|
|
|
|
}
|
2008-01-08 03:49:32 +08:00
|
|
|
RewriteObjCQualifiedInterfaceTypes(FD);
|
2007-10-31 07:14:51 +08:00
|
|
|
}
|
|
|
|
|
2010-07-01 03:16:53 +08:00
|
|
|
void RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {
|
2011-09-28 06:38:19 +08:00
|
|
|
std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
|
2010-02-13 01:52:31 +08:00
|
|
|
const char *argPtr = TypeString.c_str();
|
|
|
|
if (!strchr(argPtr, '^')) {
|
|
|
|
Str += TypeString;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
while (*argPtr) {
|
|
|
|
Str += (*argPtr == '^' ? '*' : *argPtr);
|
|
|
|
argPtr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-17 00:21:26 +08:00
|
|
|
// FIXME. Consolidate this routine with RewriteBlockPointerType.
|
2010-07-01 03:16:53 +08:00
|
|
|
void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
|
|
|
|
ValueDecl *VD) {
|
2010-02-17 00:21:26 +08:00
|
|
|
QualType Type = VD->getType();
|
2011-09-28 06:38:19 +08:00
|
|
|
std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
|
2010-02-17 00:21:26 +08:00
|
|
|
const char *argPtr = TypeString.c_str();
|
|
|
|
int paren = 0;
|
|
|
|
while (*argPtr) {
|
|
|
|
switch (*argPtr) {
|
|
|
|
case '(':
|
|
|
|
Str += *argPtr;
|
|
|
|
paren++;
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
Str += *argPtr;
|
|
|
|
paren--;
|
|
|
|
break;
|
|
|
|
case '^':
|
|
|
|
Str += '*';
|
|
|
|
if (paren == 1)
|
|
|
|
Str += VD->getNameAsString();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Str += *argPtr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
argPtr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-14 08:35:56 +08:00
|
|
|
void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
|
|
|
|
SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
|
|
|
|
const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
|
|
|
|
const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
|
|
|
|
if (!proto)
|
|
|
|
return;
|
|
|
|
QualType Type = proto->getResultType();
|
2011-09-28 06:38:19 +08:00
|
|
|
std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
|
2010-01-14 08:35:56 +08:00
|
|
|
FdStr += " ";
|
2010-08-18 06:39:59 +08:00
|
|
|
FdStr += FD->getName();
|
2010-01-14 08:35:56 +08:00
|
|
|
FdStr += "(";
|
|
|
|
unsigned numArgs = proto->getNumArgs();
|
|
|
|
for (unsigned i = 0; i < numArgs; i++) {
|
|
|
|
QualType ArgType = proto->getArgType(i);
|
2010-02-13 01:52:31 +08:00
|
|
|
RewriteBlockPointerType(FdStr, ArgType);
|
2010-01-14 08:35:56 +08:00
|
|
|
if (i+1 < numArgs)
|
|
|
|
FdStr += ", ";
|
|
|
|
}
|
|
|
|
FdStr += ");\n";
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(FunLocStart, FdStr);
|
2010-01-14 08:35:56 +08:00
|
|
|
CurFunctionDeclToDeclareForBlock = 0;
|
|
|
|
}
|
|
|
|
|
2008-03-12 01:37:02 +08:00
|
|
|
// SynthSuperContructorFunctionDecl - id objc_super(id obj, id super);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthSuperContructorFunctionDecl() {
|
2008-03-12 01:37:02 +08:00
|
|
|
if (SuperContructorFunctionDecl)
|
|
|
|
return;
|
2008-12-24 04:11:22 +08:00
|
|
|
IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2008-03-12 01:37:02 +08:00
|
|
|
QualType argT = Context->getObjCIdType();
|
|
|
|
assert(!argT.isNull() && "Can't find 'id' type");
|
|
|
|
ArgTys.push_back(argT);
|
|
|
|
ArgTys.push_back(argT);
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
|
|
|
|
&ArgTys[0], ArgTys.size());
|
2008-04-17 22:40:12 +08:00
|
|
|
SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
msgSendIdent, msgSendType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2008-03-12 01:37:02 +08:00
|
|
|
}
|
|
|
|
|
2007-10-31 07:14:51 +08:00
|
|
|
// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthMsgSendFunctionDecl() {
|
2007-10-31 07:14:51 +08:00
|
|
|
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2008-01-08 03:49:32 +08:00
|
|
|
QualType argT = Context->getObjCIdType();
|
2007-10-31 07:14:51 +08:00
|
|
|
assert(!argT.isNull() && "Can't find 'id' type");
|
|
|
|
ArgTys.push_back(argT);
|
2008-01-08 03:49:32 +08:00
|
|
|
argT = Context->getObjCSelType();
|
2007-10-31 07:14:51 +08:00
|
|
|
assert(!argT.isNull() && "Can't find 'SEL' type");
|
|
|
|
ArgTys.push_back(argT);
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
|
|
|
|
&ArgTys[0], ArgTys.size(),
|
|
|
|
true /*isVariadic*/);
|
2008-04-17 22:40:12 +08:00
|
|
|
MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2008-04-04 14:12:32 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
msgSendIdent, msgSendType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2007-10-31 07:14:51 +08:00
|
|
|
}
|
|
|
|
|
2007-11-15 18:28:18 +08:00
|
|
|
// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
|
2007-11-15 18:28:18 +08:00
|
|
|
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2010-05-12 05:36:43 +08:00
|
|
|
RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
|
2011-03-09 22:09:51 +08:00
|
|
|
SourceLocation(), SourceLocation(),
|
2008-09-05 09:34:33 +08:00
|
|
|
&Context->Idents.get("objc_super"));
|
2007-11-15 18:28:18 +08:00
|
|
|
QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
|
|
|
|
assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
|
|
|
|
ArgTys.push_back(argT);
|
2008-01-08 03:49:32 +08:00
|
|
|
argT = Context->getObjCSelType();
|
2007-11-15 18:28:18 +08:00
|
|
|
assert(!argT.isNull() && "Can't find 'SEL' type");
|
|
|
|
ArgTys.push_back(argT);
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
|
|
|
|
&ArgTys[0], ArgTys.size(),
|
|
|
|
true /*isVariadic*/);
|
2008-04-17 22:40:12 +08:00
|
|
|
MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
msgSendIdent, msgSendType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2007-11-15 18:28:18 +08:00
|
|
|
}
|
|
|
|
|
2011-10-12 07:02:37 +08:00
|
|
|
// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthMsgSendStretFunctionDecl() {
|
2007-12-04 03:17:29 +08:00
|
|
|
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2008-01-08 03:49:32 +08:00
|
|
|
QualType argT = Context->getObjCIdType();
|
2007-12-04 03:17:29 +08:00
|
|
|
assert(!argT.isNull() && "Can't find 'id' type");
|
|
|
|
ArgTys.push_back(argT);
|
2008-01-08 03:49:32 +08:00
|
|
|
argT = Context->getObjCSelType();
|
2007-12-04 03:17:29 +08:00
|
|
|
assert(!argT.isNull() && "Can't find 'SEL' type");
|
|
|
|
ArgTys.push_back(argT);
|
2011-10-12 07:02:37 +08:00
|
|
|
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
|
2010-12-14 16:05:40 +08:00
|
|
|
&ArgTys[0], ArgTys.size(),
|
|
|
|
true /*isVariadic*/);
|
2008-04-17 22:40:12 +08:00
|
|
|
MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
msgSendIdent, msgSendType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2007-12-04 03:17:29 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// SynthMsgSendSuperStretFunctionDecl -
|
2011-10-12 07:02:37 +08:00
|
|
|
// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
|
2009-09-09 23:08:12 +08:00
|
|
|
IdentifierInfo *msgSendIdent =
|
2007-12-04 03:17:29 +08:00
|
|
|
&Context->Idents.get("objc_msgSendSuper_stret");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2010-05-12 05:36:43 +08:00
|
|
|
RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
|
2011-03-09 22:09:51 +08:00
|
|
|
SourceLocation(), SourceLocation(),
|
2008-09-05 09:34:33 +08:00
|
|
|
&Context->Idents.get("objc_super"));
|
2007-12-04 03:17:29 +08:00
|
|
|
QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
|
|
|
|
assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
|
|
|
|
ArgTys.push_back(argT);
|
2008-01-08 03:49:32 +08:00
|
|
|
argT = Context->getObjCSelType();
|
2007-12-04 03:17:29 +08:00
|
|
|
assert(!argT.isNull() && "Can't find 'SEL' type");
|
|
|
|
ArgTys.push_back(argT);
|
2011-10-12 07:02:37 +08:00
|
|
|
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
|
2010-12-14 16:05:40 +08:00
|
|
|
&ArgTys[0], ArgTys.size(),
|
|
|
|
true /*isVariadic*/);
|
2008-04-17 22:40:12 +08:00
|
|
|
MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(),
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
msgSendIdent, msgSendType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2007-12-04 03:17:29 +08:00
|
|
|
}
|
|
|
|
|
2008-05-09 06:02:18 +08:00
|
|
|
// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
|
2007-12-04 05:26:48 +08:00
|
|
|
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2008-01-08 03:49:32 +08:00
|
|
|
QualType argT = Context->getObjCIdType();
|
2007-12-04 05:26:48 +08:00
|
|
|
assert(!argT.isNull() && "Can't find 'id' type");
|
|
|
|
ArgTys.push_back(argT);
|
2008-01-08 03:49:32 +08:00
|
|
|
argT = Context->getObjCSelType();
|
2007-12-04 05:26:48 +08:00
|
|
|
assert(!argT.isNull() && "Can't find 'SEL' type");
|
|
|
|
ArgTys.push_back(argT);
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
|
|
|
|
&ArgTys[0], ArgTys.size(),
|
|
|
|
true /*isVariadic*/);
|
2008-04-17 22:40:12 +08:00
|
|
|
MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
msgSendIdent, msgSendType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2007-12-04 05:26:48 +08:00
|
|
|
}
|
|
|
|
|
2007-10-31 07:14:51 +08:00
|
|
|
// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthGetClassFunctionDecl() {
|
2007-10-31 07:14:51 +08:00
|
|
|
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2009-09-25 03:53:00 +08:00
|
|
|
ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
|
|
|
|
&ArgTys[0], ArgTys.size());
|
2008-04-17 22:40:12 +08:00
|
|
|
GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
getClassIdent, getClassType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2007-10-31 07:14:51 +08:00
|
|
|
}
|
|
|
|
|
2010-03-11 05:17:41 +08:00
|
|
|
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
|
|
|
|
void RewriteObjC::SynthGetSuperClassFunctionDecl() {
|
|
|
|
IdentifierInfo *getSuperClassIdent =
|
|
|
|
&Context->Idents.get("class_getSuperclass");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2010-03-11 05:17:41 +08:00
|
|
|
ArgTys.push_back(Context->getObjCClassType());
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
|
|
|
|
&ArgTys[0], ArgTys.size());
|
2010-03-11 05:17:41 +08:00
|
|
|
GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2010-04-20 06:54:31 +08:00
|
|
|
SourceLocation(),
|
|
|
|
getSuperClassIdent,
|
|
|
|
getClassType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None,
|
2010-04-20 06:54:31 +08:00
|
|
|
false);
|
2010-03-11 05:17:41 +08:00
|
|
|
}
|
|
|
|
|
2011-12-22 03:48:07 +08:00
|
|
|
// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name);
|
2008-04-15 06:03:09 +08:00
|
|
|
void RewriteObjC::SynthGetMetaClassFunctionDecl() {
|
2007-12-07 11:50:46 +08:00
|
|
|
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 16> ArgTys;
|
2009-09-25 03:53:00 +08:00
|
|
|
ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
|
|
|
|
&ArgTys[0], ArgTys.size());
|
2008-04-17 22:40:12 +08:00
|
|
|
GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(),
|
2009-08-19 09:27:57 +08:00
|
|
|
getClassIdent, getClassType, 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern,
|
|
|
|
SC_None, false);
|
2007-12-07 11:50:46 +08:00
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
|
2008-03-15 08:55:56 +08:00
|
|
|
QualType strType = getConstantStringStructType();
|
|
|
|
|
|
|
|
std::string S = "__NSConstantStringImpl_";
|
2008-05-31 11:35:42 +08:00
|
|
|
|
|
|
|
std::string tmpName = InFileName;
|
|
|
|
unsigned i;
|
|
|
|
for (i=0; i < tmpName.length(); i++) {
|
|
|
|
char c = tmpName.at(i);
|
|
|
|
// replace any non alphanumeric characters with '_'.
|
|
|
|
if (!isalpha(c) && (c < '0' || c > '9'))
|
|
|
|
tmpName[i] = '_';
|
|
|
|
}
|
|
|
|
S += tmpName;
|
|
|
|
S += "_";
|
2008-03-15 08:55:56 +08:00
|
|
|
S += utostr(NumObjCStringLiterals++);
|
|
|
|
|
2008-03-28 06:29:16 +08:00
|
|
|
Preamble += "static __NSConstantStringImpl " + S;
|
|
|
|
Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
|
|
|
|
Preamble += "0x000007c8,"; // utf8_str
|
2008-03-15 08:55:56 +08:00
|
|
|
// The pretty printer for StringLiteral handles escape characters properly.
|
2008-09-13 13:16:45 +08:00
|
|
|
std::string prettyBufS;
|
|
|
|
llvm::raw_string_ostream prettyBuf(prettyBufS);
|
2009-06-30 09:26:17 +08:00
|
|
|
Exp->getString()->printPretty(prettyBuf, *Context, 0,
|
|
|
|
PrintingPolicy(LangOpts));
|
2008-03-28 06:29:16 +08:00
|
|
|
Preamble += prettyBuf.str();
|
|
|
|
Preamble += ",";
|
2009-12-06 09:48:44 +08:00
|
|
|
Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(), &Context->Idents.get(S),
|
|
|
|
strType, 0, SC_Static, SC_None);
|
2010-11-18 14:31:45 +08:00
|
|
|
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, VK_LValue,
|
|
|
|
SourceLocation());
|
2010-08-25 19:45:40 +08:00
|
|
|
Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
|
2009-09-09 23:08:12 +08:00
|
|
|
Context->getPointerType(DRE->getType()),
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_RValue, OK_Ordinary,
|
|
|
|
SourceLocation());
|
2007-11-08 22:30:50 +08:00
|
|
|
// cast to NSConstantString *
|
2010-01-16 02:39:57 +08:00
|
|
|
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
|
2011-09-09 13:25:32 +08:00
|
|
|
CK_CPointerToObjCPointerCast, Unop);
|
2008-02-01 03:37:57 +08:00
|
|
|
ReplaceStmt(Exp, cast);
|
2010-10-12 05:29:12 +08:00
|
|
|
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
|
2007-11-08 22:30:50 +08:00
|
|
|
return cast;
|
2007-11-03 19:27:19 +08:00
|
|
|
}
|
|
|
|
|
2007-11-15 18:28:18 +08:00
|
|
|
// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
|
2008-04-15 06:03:09 +08:00
|
|
|
QualType RewriteObjC::getSuperStructType() {
|
2007-11-15 18:28:18 +08:00
|
|
|
if (!SuperStructDecl) {
|
2010-05-12 05:36:43 +08:00
|
|
|
SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
|
2011-03-09 22:09:51 +08:00
|
|
|
SourceLocation(), SourceLocation(),
|
2008-09-05 09:34:33 +08:00
|
|
|
&Context->Idents.get("objc_super"));
|
2007-11-15 18:28:18 +08:00
|
|
|
QualType FieldTypes[2];
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-15 18:28:18 +08:00
|
|
|
// struct objc_object *receiver;
|
2009-09-09 23:08:12 +08:00
|
|
|
FieldTypes[0] = Context->getObjCIdType();
|
2007-11-15 18:28:18 +08:00
|
|
|
// struct objc_class *super;
|
2009-09-09 23:08:12 +08:00
|
|
|
FieldTypes[1] = Context->getObjCClassType();
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2007-11-15 18:28:18 +08:00
|
|
|
// Create fields
|
2008-12-12 00:49:14 +08:00
|
|
|
for (unsigned i = 0; i < 2; ++i) {
|
2009-09-09 23:08:12 +08:00
|
|
|
SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation(), 0,
|
2009-08-19 09:27:57 +08:00
|
|
|
FieldTypes[i], 0,
|
|
|
|
/*BitWidth=*/0,
|
2011-06-12 01:19:42 +08:00
|
|
|
/*Mutable=*/false,
|
|
|
|
/*HasInit=*/false));
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-02-11 09:19:42 +08:00
|
|
|
SuperStructDecl->completeDefinition();
|
2007-11-15 18:28:18 +08:00
|
|
|
}
|
|
|
|
return Context->getTagDeclType(SuperStructDecl);
|
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
QualType RewriteObjC::getConstantStringStructType() {
|
2008-03-15 08:55:56 +08:00
|
|
|
if (!ConstantStringDecl) {
|
2010-05-12 05:36:43 +08:00
|
|
|
ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
|
2011-03-09 22:09:51 +08:00
|
|
|
SourceLocation(), SourceLocation(),
|
2008-09-05 09:34:33 +08:00
|
|
|
&Context->Idents.get("__NSConstantStringImpl"));
|
2008-03-15 08:55:56 +08:00
|
|
|
QualType FieldTypes[4];
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-03-15 08:55:56 +08:00
|
|
|
// struct objc_object *receiver;
|
2009-09-09 23:08:12 +08:00
|
|
|
FieldTypes[0] = Context->getObjCIdType();
|
2008-03-15 08:55:56 +08:00
|
|
|
// int flags;
|
2009-09-09 23:08:12 +08:00
|
|
|
FieldTypes[1] = Context->IntTy;
|
2008-03-15 08:55:56 +08:00
|
|
|
// char *str;
|
2009-09-09 23:08:12 +08:00
|
|
|
FieldTypes[2] = Context->getPointerType(Context->CharTy);
|
2008-03-15 08:55:56 +08:00
|
|
|
// long length;
|
2009-09-09 23:08:12 +08:00
|
|
|
FieldTypes[3] = Context->LongTy;
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2008-03-15 08:55:56 +08:00
|
|
|
// Create fields
|
2008-12-12 00:49:14 +08:00
|
|
|
for (unsigned i = 0; i < 4; ++i) {
|
2009-09-09 23:08:12 +08:00
|
|
|
ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
|
|
|
|
ConstantStringDecl,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(),
|
2008-12-12 00:49:14 +08:00
|
|
|
SourceLocation(), 0,
|
2009-08-19 09:27:57 +08:00
|
|
|
FieldTypes[i], 0,
|
2008-12-12 00:49:14 +08:00
|
|
|
/*BitWidth=*/0,
|
2011-06-12 01:19:42 +08:00
|
|
|
/*Mutable=*/true,
|
|
|
|
/*HasInit=*/false));
|
2008-12-12 00:49:14 +08:00
|
|
|
}
|
|
|
|
|
2010-02-11 09:19:42 +08:00
|
|
|
ConstantStringDecl->completeDefinition();
|
2008-03-15 08:55:56 +08:00
|
|
|
}
|
|
|
|
return Context->getTagDeclType(ConstantStringDecl);
|
|
|
|
}
|
|
|
|
|
2010-02-23 04:48:10 +08:00
|
|
|
Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation EndLoc) {
|
2007-12-05 05:47:40 +08:00
|
|
|
if (!SelGetUidFunctionDecl)
|
|
|
|
SynthSelGetUidFunctionDecl();
|
2007-10-31 07:14:51 +08:00
|
|
|
if (!MsgSendFunctionDecl)
|
|
|
|
SynthMsgSendFunctionDecl();
|
2007-11-15 18:28:18 +08:00
|
|
|
if (!MsgSendSuperFunctionDecl)
|
|
|
|
SynthMsgSendSuperFunctionDecl();
|
2007-12-04 03:17:29 +08:00
|
|
|
if (!MsgSendStretFunctionDecl)
|
|
|
|
SynthMsgSendStretFunctionDecl();
|
|
|
|
if (!MsgSendSuperStretFunctionDecl)
|
|
|
|
SynthMsgSendSuperStretFunctionDecl();
|
2007-12-04 05:26:48 +08:00
|
|
|
if (!MsgSendFpretFunctionDecl)
|
|
|
|
SynthMsgSendFpretFunctionDecl();
|
2007-10-31 07:14:51 +08:00
|
|
|
if (!GetClassFunctionDecl)
|
|
|
|
SynthGetClassFunctionDecl();
|
2010-03-11 05:17:41 +08:00
|
|
|
if (!GetSuperClassFunctionDecl)
|
|
|
|
SynthGetSuperClassFunctionDecl();
|
2007-12-07 11:50:46 +08:00
|
|
|
if (!GetMetaClassFunctionDecl)
|
|
|
|
SynthGetMetaClassFunctionDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-15 18:28:18 +08:00
|
|
|
// default to objc_msgSend().
|
2007-12-04 03:17:29 +08:00
|
|
|
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
|
|
|
|
// May need to use objc_msgSend_stret() as well.
|
|
|
|
FunctionDecl *MsgSendStretFlavor = 0;
|
2009-04-30 00:37:50 +08:00
|
|
|
if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
|
|
|
|
QualType resultType = mDecl->getResultType();
|
2010-04-27 05:31:17 +08:00
|
|
|
if (resultType->isRecordType())
|
2007-12-04 03:17:29 +08:00
|
|
|
MsgSendStretFlavor = MsgSendStretFunctionDecl;
|
2008-07-27 06:36:27 +08:00
|
|
|
else if (resultType->isRealFloatingType())
|
2007-12-04 05:26:48 +08:00
|
|
|
MsgSendFlavor = MsgSendFpretFunctionDecl;
|
2007-12-04 03:17:29 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-25 06:48:43 +08:00
|
|
|
// Synthesize a call to objc_msgSend().
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Expr*, 8> MsgExprs;
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
switch (Exp->getReceiverKind()) {
|
|
|
|
case ObjCMessageExpr::SuperClass: {
|
|
|
|
MsgSendFlavor = MsgSendSuperFunctionDecl;
|
|
|
|
if (MsgSendStretFlavor)
|
|
|
|
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
|
|
|
|
assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Expr*, 4> InitExprs;
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
|
|
|
|
// set the receiver to self, the first argument to all methods.
|
|
|
|
InitExprs.push_back(
|
|
|
|
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast,
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
|
2010-11-18 14:31:45 +08:00
|
|
|
Context->getObjCIdType(),
|
|
|
|
VK_RValue,
|
|
|
|
SourceLocation()))
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
); // set the 'receiver'.
|
|
|
|
|
|
|
|
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Expr*, 8> ClsExprs;
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
QualType argType = Context->getPointerType(Context->CharTy);
|
|
|
|
ClsExprs.push_back(StringLiteral::Create(*Context,
|
2011-06-21 23:13:30 +08:00
|
|
|
ClassDecl->getIdentifier()->getName(),
|
2011-07-27 13:40:30 +08:00
|
|
|
StringLiteral::Ascii, false,
|
|
|
|
argType, SourceLocation()));
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
|
|
|
|
&ClsExprs[0],
|
|
|
|
ClsExprs.size(),
|
|
|
|
StartLoc,
|
|
|
|
EndLoc);
|
|
|
|
// (Class)objc_getClass("CurrentClass")
|
|
|
|
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
|
|
|
|
Context->getObjCClassType(),
|
2011-12-22 03:48:07 +08:00
|
|
|
CK_BitCast, Cls);
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
ClsExprs.clear();
|
|
|
|
ClsExprs.push_back(ArgExpr);
|
|
|
|
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
|
|
|
|
&ClsExprs[0], ClsExprs.size(),
|
|
|
|
StartLoc, EndLoc);
|
|
|
|
|
|
|
|
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
|
|
|
|
// To turn off a warning, type-cast to 'id'
|
|
|
|
InitExprs.push_back( // set 'super class', using class_getSuperclass().
|
|
|
|
NoTypeInfoCStyleCastExpr(Context,
|
|
|
|
Context->getObjCIdType(),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast, Cls));
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
// struct objc_super
|
|
|
|
QualType superType = getSuperStructType();
|
|
|
|
Expr *SuperRep;
|
|
|
|
|
2011-09-18 01:15:52 +08:00
|
|
|
if (LangOpts.MicrosoftExt) {
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
SynthSuperContructorFunctionDecl();
|
|
|
|
// Simulate a contructor call...
|
|
|
|
DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
|
2010-11-18 14:31:45 +08:00
|
|
|
superType, VK_LValue,
|
|
|
|
SourceLocation());
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
|
|
|
|
InitExprs.size(),
|
2010-11-18 14:31:45 +08:00
|
|
|
superType, VK_LValue,
|
|
|
|
SourceLocation());
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
// The code for super is a little tricky to prevent collision with
|
|
|
|
// the structure definition in the header. The rewriter has it's own
|
|
|
|
// internal definition (__rw_objc_super) that is uses. This is why
|
|
|
|
// we need the cast below. For example:
|
|
|
|
// (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
|
|
|
|
//
|
2010-08-25 19:45:40 +08:00
|
|
|
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
Context->getPointerType(SuperRep->getType()),
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_RValue, OK_Ordinary,
|
|
|
|
SourceLocation());
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
SuperRep = NoTypeInfoCStyleCastExpr(Context,
|
|
|
|
Context->getPointerType(superType),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast, SuperRep);
|
2007-12-07 11:50:46 +08:00
|
|
|
} else {
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
// (struct objc_super) { <exprs from above> }
|
|
|
|
InitListExpr *ILE =
|
|
|
|
new (Context) InitListExpr(*Context, SourceLocation(),
|
|
|
|
&InitExprs[0], InitExprs.size(),
|
|
|
|
SourceLocation());
|
|
|
|
TypeSourceInfo *superTInfo
|
|
|
|
= Context->getTrivialTypeSourceInfo(superType);
|
|
|
|
SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
|
2010-11-18 14:31:45 +08:00
|
|
|
superType, VK_LValue,
|
|
|
|
ILE, false);
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
// struct objc_super *
|
2010-08-25 19:45:40 +08:00
|
|
|
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
Context->getPointerType(SuperRep->getType()),
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_RValue, OK_Ordinary,
|
|
|
|
SourceLocation());
|
2007-12-07 11:50:46 +08:00
|
|
|
}
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
MsgExprs.push_back(SuperRep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ObjCMessageExpr::Class: {
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Expr*, 8> ClsExprs;
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
QualType argType = Context->getPointerType(Context->CharTy);
|
|
|
|
ObjCInterfaceDecl *Class
|
2010-05-18 05:00:27 +08:00
|
|
|
= Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
IdentifierInfo *clsName = Class->getIdentifier();
|
|
|
|
ClsExprs.push_back(StringLiteral::Create(*Context,
|
2011-06-21 23:13:30 +08:00
|
|
|
clsName->getName(),
|
2011-07-27 13:40:30 +08:00
|
|
|
StringLiteral::Ascii, false,
|
2011-04-14 08:40:03 +08:00
|
|
|
argType, SourceLocation()));
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
|
|
|
|
&ClsExprs[0],
|
|
|
|
ClsExprs.size(),
|
|
|
|
StartLoc, EndLoc);
|
|
|
|
MsgExprs.push_back(Cls);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ObjCMessageExpr::SuperInstance:{
|
|
|
|
MsgSendFlavor = MsgSendSuperFunctionDecl;
|
|
|
|
if (MsgSendStretFlavor)
|
|
|
|
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
|
|
|
|
assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
|
|
|
|
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Expr*, 4> InitExprs;
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
|
|
|
|
InitExprs.push_back(
|
|
|
|
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast,
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
|
2010-11-18 14:31:45 +08:00
|
|
|
Context->getObjCIdType(),
|
|
|
|
VK_RValue, SourceLocation()))
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
); // set the 'receiver'.
|
|
|
|
|
|
|
|
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Expr*, 8> ClsExprs;
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
QualType argType = Context->getPointerType(Context->CharTy);
|
|
|
|
ClsExprs.push_back(StringLiteral::Create(*Context,
|
2011-06-21 23:13:30 +08:00
|
|
|
ClassDecl->getIdentifier()->getName(),
|
2011-07-27 13:40:30 +08:00
|
|
|
StringLiteral::Ascii, false, argType,
|
|
|
|
SourceLocation()));
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
|
|
|
|
&ClsExprs[0],
|
|
|
|
ClsExprs.size(),
|
|
|
|
StartLoc, EndLoc);
|
|
|
|
// (Class)objc_getClass("CurrentClass")
|
|
|
|
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
|
|
|
|
Context->getObjCClassType(),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast, Cls);
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
ClsExprs.clear();
|
|
|
|
ClsExprs.push_back(ArgExpr);
|
|
|
|
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
|
|
|
|
&ClsExprs[0], ClsExprs.size(),
|
|
|
|
StartLoc, EndLoc);
|
|
|
|
|
|
|
|
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
|
|
|
|
// To turn off a warning, type-cast to 'id'
|
|
|
|
InitExprs.push_back(
|
|
|
|
// set 'super class', using class_getSuperclass().
|
|
|
|
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast, Cls));
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
// struct objc_super
|
|
|
|
QualType superType = getSuperStructType();
|
|
|
|
Expr *SuperRep;
|
|
|
|
|
2011-09-18 01:15:52 +08:00
|
|
|
if (LangOpts.MicrosoftExt) {
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
SynthSuperContructorFunctionDecl();
|
|
|
|
// Simulate a contructor call...
|
|
|
|
DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
|
2010-11-18 14:31:45 +08:00
|
|
|
superType, VK_LValue,
|
|
|
|
SourceLocation());
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
|
|
|
|
InitExprs.size(),
|
2010-11-18 14:31:45 +08:00
|
|
|
superType, VK_LValue, SourceLocation());
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
// The code for super is a little tricky to prevent collision with
|
|
|
|
// the structure definition in the header. The rewriter has it's own
|
|
|
|
// internal definition (__rw_objc_super) that is uses. This is why
|
|
|
|
// we need the cast below. For example:
|
|
|
|
// (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
|
|
|
|
//
|
2010-08-25 19:45:40 +08:00
|
|
|
SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
Context->getPointerType(SuperRep->getType()),
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_RValue, OK_Ordinary,
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
SourceLocation());
|
|
|
|
SuperRep = NoTypeInfoCStyleCastExpr(Context,
|
|
|
|
Context->getPointerType(superType),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast, SuperRep);
|
2007-11-15 18:28:18 +08:00
|
|
|
} else {
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
// (struct objc_super) { <exprs from above> }
|
|
|
|
InitListExpr *ILE =
|
|
|
|
new (Context) InitListExpr(*Context, SourceLocation(),
|
|
|
|
&InitExprs[0], InitExprs.size(),
|
|
|
|
SourceLocation());
|
|
|
|
TypeSourceInfo *superTInfo
|
|
|
|
= Context->getTrivialTypeSourceInfo(superType);
|
|
|
|
SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
|
2010-11-18 14:31:45 +08:00
|
|
|
superType, VK_RValue, ILE,
|
|
|
|
false);
|
2007-11-15 18:28:18 +08:00
|
|
|
}
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
MsgExprs.push_back(SuperRep);
|
|
|
|
break;
|
2007-11-15 07:54:14 +08:00
|
|
|
}
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
|
|
|
|
case ObjCMessageExpr::Instance: {
|
|
|
|
// Remove all type-casts because it may contain objc-style types; e.g.
|
|
|
|
// Foo<Proto> *.
|
|
|
|
Expr *recExpr = Exp->getInstanceReceiver();
|
|
|
|
while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
|
|
|
|
recExpr = CE->getSubExpr();
|
2011-10-08 01:17:45 +08:00
|
|
|
CastKind CK = recExpr->getType()->isObjCObjectPointerType()
|
|
|
|
? CK_BitCast : recExpr->getType()->isBlockPointerType()
|
|
|
|
? CK_BlockPointerToObjCPointerCast
|
|
|
|
: CK_CPointerToObjCPointerCast;
|
|
|
|
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
|
2011-10-08 01:17:45 +08:00
|
|
|
CK, recExpr);
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
MsgExprs.push_back(recExpr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-03 19:27:19 +08:00
|
|
|
// Create a call to sel_registerName("selName"), it will be the 2nd argument.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Expr*, 8> SelExprs;
|
2007-10-25 06:48:43 +08:00
|
|
|
QualType argType = Context->getPointerType(Context->CharTy);
|
2009-09-09 23:08:12 +08:00
|
|
|
SelExprs.push_back(StringLiteral::Create(*Context,
|
2011-06-21 23:13:30 +08:00
|
|
|
Exp->getSelector().getAsString(),
|
2011-07-27 13:40:30 +08:00
|
|
|
StringLiteral::Ascii, false,
|
|
|
|
argType, SourceLocation()));
|
2007-10-25 06:48:43 +08:00
|
|
|
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
|
2010-02-23 04:48:10 +08:00
|
|
|
&SelExprs[0], SelExprs.size(),
|
|
|
|
StartLoc,
|
|
|
|
EndLoc);
|
2007-10-25 06:48:43 +08:00
|
|
|
MsgExprs.push_back(SelExp);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-25 06:48:43 +08:00
|
|
|
// Now push any user supplied arguments.
|
|
|
|
for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
|
2007-11-15 07:54:14 +08:00
|
|
|
Expr *userExpr = Exp->getArg(i);
|
2007-11-15 10:58:25 +08:00
|
|
|
// Make all implicit casts explicit...ICE comes in handy:-)
|
|
|
|
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
|
|
|
|
// Reuse the ICE type, it is exactly what the doctor ordered.
|
2011-02-26 09:31:36 +08:00
|
|
|
QualType type = ICE->getType();
|
|
|
|
if (needToScanForQualifiers(type))
|
|
|
|
type = Context->getObjCIdType();
|
2010-05-25 23:56:08 +08:00
|
|
|
// Make sure we convert "type (^)(...)" to "type (*)(...)".
|
2010-05-26 01:12:52 +08:00
|
|
|
(void)convertBlockPointerToFunctionPointer(type);
|
2011-08-05 07:58:03 +08:00
|
|
|
const Expr *SubExpr = ICE->IgnoreParenImpCasts();
|
2011-09-09 13:25:32 +08:00
|
|
|
CastKind CK;
|
|
|
|
if (SubExpr->getType()->isIntegralType(*Context) &&
|
|
|
|
type->isBooleanType()) {
|
|
|
|
CK = CK_IntegralToBoolean;
|
|
|
|
} else if (type->isObjCObjectPointerType()) {
|
|
|
|
if (SubExpr->getType()->isBlockPointerType()) {
|
|
|
|
CK = CK_BlockPointerToObjCPointerCast;
|
|
|
|
} else if (SubExpr->getType()->isPointerType()) {
|
|
|
|
CK = CK_CPointerToObjCPointerCast;
|
|
|
|
} else {
|
|
|
|
CK = CK_BitCast;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
CK = CK_BitCast;
|
|
|
|
}
|
|
|
|
|
|
|
|
userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
|
2007-12-19 05:33:44 +08:00
|
|
|
}
|
|
|
|
// Make id<P...> cast into an 'id' cast.
|
2008-10-28 23:36:24 +08:00
|
|
|
else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
|
2008-01-08 03:49:32 +08:00
|
|
|
if (CE->getType()->isObjCQualifiedIdType()) {
|
2008-10-28 23:36:24 +08:00
|
|
|
while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
|
2007-12-19 05:33:44 +08:00
|
|
|
userExpr = CE->getSubExpr();
|
2011-09-09 13:25:32 +08:00
|
|
|
CastKind CK;
|
|
|
|
if (userExpr->getType()->isIntegralType(*Context)) {
|
|
|
|
CK = CK_IntegralToPointer;
|
|
|
|
} else if (userExpr->getType()->isBlockPointerType()) {
|
|
|
|
CK = CK_BlockPointerToObjCPointerCast;
|
|
|
|
} else if (userExpr->getType()->isPointerType()) {
|
|
|
|
CK = CK_CPointerToObjCPointerCast;
|
|
|
|
} else {
|
|
|
|
CK = CK_BitCast;
|
|
|
|
}
|
2010-01-16 02:39:57 +08:00
|
|
|
userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
|
2011-09-09 13:25:32 +08:00
|
|
|
CK, userExpr);
|
2007-12-19 05:33:44 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2007-11-15 07:54:14 +08:00
|
|
|
MsgExprs.push_back(userExpr);
|
2009-04-30 00:37:50 +08:00
|
|
|
// We've transferred the ownership to MsgExprs. For now, we *don't* null
|
|
|
|
// out the argument in the original expression (since we aren't deleting
|
2010-10-12 05:29:12 +08:00
|
|
|
// the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
|
2009-04-30 00:37:50 +08:00
|
|
|
//Exp->setArg(i, 0);
|
2007-10-25 06:48:43 +08:00
|
|
|
}
|
2007-11-05 06:37:50 +08:00
|
|
|
// Generate the funky cast.
|
|
|
|
CastExpr *cast;
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 8> ArgTypes;
|
2007-11-05 06:37:50 +08:00
|
|
|
QualType returnType;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-05 06:37:50 +08:00
|
|
|
// Push 'id' and 'SEL', the 2 implicit arguments.
|
2007-11-15 18:43:57 +08:00
|
|
|
if (MsgSendFlavor == MsgSendSuperFunctionDecl)
|
|
|
|
ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
|
|
|
|
else
|
2008-01-08 03:49:32 +08:00
|
|
|
ArgTypes.push_back(Context->getObjCIdType());
|
|
|
|
ArgTypes.push_back(Context->getObjCSelType());
|
2009-02-21 02:43:26 +08:00
|
|
|
if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
|
2007-11-05 06:37:50 +08:00
|
|
|
// Push any user argument types.
|
2009-02-21 02:43:26 +08:00
|
|
|
for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
|
|
|
|
E = OMD->param_end(); PI != E; ++PI) {
|
|
|
|
QualType t = (*PI)->getType()->isObjCQualifiedIdType()
|
2009-09-09 23:08:12 +08:00
|
|
|
? Context->getObjCIdType()
|
2009-02-21 02:43:26 +08:00
|
|
|
: (*PI)->getType();
|
2008-10-29 22:49:46 +08:00
|
|
|
// Make sure we convert "t (^)(...)" to "t (*)(...)".
|
2010-05-26 01:12:52 +08:00
|
|
|
(void)convertBlockPointerToFunctionPointer(t);
|
2007-11-05 22:36:37 +08:00
|
|
|
ArgTypes.push_back(t);
|
|
|
|
}
|
2011-09-11 01:01:56 +08:00
|
|
|
returnType = Exp->getType();
|
|
|
|
convertToUnqualifiedObjCType(returnType);
|
2010-05-26 01:12:52 +08:00
|
|
|
(void)convertBlockPointerToFunctionPointer(returnType);
|
2007-11-05 06:37:50 +08:00
|
|
|
} else {
|
2008-01-08 03:49:32 +08:00
|
|
|
returnType = Context->getObjCIdType();
|
2007-11-05 06:37:50 +08:00
|
|
|
}
|
|
|
|
// Get the type, we will need to reference it in a couple spots.
|
2007-11-15 18:28:18 +08:00
|
|
|
QualType msgSendType = MsgSendFlavor->getType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-05 06:37:50 +08:00
|
|
|
// Create a reference to the objc_msgSend() declaration.
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType,
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_LValue, SourceLocation());
|
2007-11-05 06:37:50 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
|
2007-11-05 06:37:50 +08:00
|
|
|
// If we don't do this cast, we get the following bizarre warning/note:
|
|
|
|
// xx.m:13: warning: function called through a non-compatible type
|
|
|
|
// xx.m:13: note: if this code is reached, the program will abort
|
2010-01-16 02:39:57 +08:00
|
|
|
cast = NoTypeInfoCStyleCastExpr(Context,
|
|
|
|
Context->getPointerType(Context->VoidTy),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast, DRE);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-05 06:37:50 +08:00
|
|
|
// Now do the "normal" pointer to function cast.
|
2010-12-14 16:05:40 +08:00
|
|
|
QualType castType =
|
|
|
|
getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
|
|
|
|
// If we don't have a method decl, force a variadic cast.
|
|
|
|
Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true);
|
2007-11-05 06:37:50 +08:00
|
|
|
castType = Context->getPointerType(castType);
|
2010-11-15 17:46:46 +08:00
|
|
|
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
|
2010-01-16 02:39:57 +08:00
|
|
|
cast);
|
2007-11-05 06:37:50 +08:00
|
|
|
|
|
|
|
// Don't forget the parens to enforce the proper binding.
|
2010-02-23 04:48:10 +08:00
|
|
|
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-22 07:43:11 +08:00
|
|
|
const FunctionType *FT = msgSendType->getAs<FunctionType>();
|
2009-02-10 04:51:47 +08:00
|
|
|
CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
|
2009-09-09 23:08:12 +08:00
|
|
|
MsgExprs.size(),
|
2010-11-18 14:31:45 +08:00
|
|
|
FT->getResultType(), VK_RValue,
|
|
|
|
EndLoc);
|
2008-01-09 06:06:28 +08:00
|
|
|
Stmt *ReplacingStmt = CE;
|
2007-12-04 03:17:29 +08:00
|
|
|
if (MsgSendStretFlavor) {
|
|
|
|
// We have the method which returns a struct/union. Must also generate
|
|
|
|
// call to objc_msgSend_stret and hang both varieties on a conditional
|
|
|
|
// expression which dictate which one to envoke depending on size of
|
|
|
|
// method's return type.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-04 03:17:29 +08:00
|
|
|
// Create a reference to the objc_msgSend_stret() declaration.
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType,
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_LValue, SourceLocation());
|
2007-12-04 03:17:29 +08:00
|
|
|
// Need to cast objc_msgSend_stret to "void *" (see above comment).
|
2010-01-16 02:39:57 +08:00
|
|
|
cast = NoTypeInfoCStyleCastExpr(Context,
|
|
|
|
Context->getPointerType(Context->VoidTy),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast, STDRE);
|
2007-12-04 03:17:29 +08:00
|
|
|
// Now do the "normal" pointer to function cast.
|
2010-12-14 16:05:40 +08:00
|
|
|
castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
|
|
|
|
Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false);
|
2007-12-04 03:17:29 +08:00
|
|
|
castType = Context->getPointerType(castType);
|
2010-11-15 17:46:46 +08:00
|
|
|
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
|
2010-01-16 02:39:57 +08:00
|
|
|
cast);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-04 03:17:29 +08:00
|
|
|
// Don't forget the parens to enforce the proper binding.
|
2009-02-07 09:47:29 +08:00
|
|
|
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-22 07:43:11 +08:00
|
|
|
FT = msgSendType->getAs<FunctionType>();
|
2009-02-10 04:51:47 +08:00
|
|
|
CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
|
2009-09-09 23:08:12 +08:00
|
|
|
MsgExprs.size(),
|
2010-11-18 14:31:45 +08:00
|
|
|
FT->getResultType(), VK_RValue,
|
|
|
|
SourceLocation());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-04 03:17:29 +08:00
|
|
|
// Build sizeof(returnType)
|
2011-03-12 03:24:49 +08:00
|
|
|
UnaryExprOrTypeTraitExpr *sizeofExpr =
|
|
|
|
new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf,
|
|
|
|
Context->getTrivialTypeSourceInfo(returnType),
|
|
|
|
Context->getSizeType(), SourceLocation(),
|
|
|
|
SourceLocation());
|
2007-12-04 03:17:29 +08:00
|
|
|
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
|
|
|
|
// FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
|
|
|
|
// For X86 it is more complicated and some kind of target specific routine
|
|
|
|
// is needed to decide what to do.
|
2009-09-09 23:08:12 +08:00
|
|
|
unsigned IntSize =
|
2008-03-06 02:54:05 +08:00
|
|
|
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
|
2010-08-28 17:06:06 +08:00
|
|
|
IntegerLiteral *limit = IntegerLiteral::Create(*Context,
|
|
|
|
llvm::APInt(IntSize, 8),
|
|
|
|
Context->IntTy,
|
|
|
|
SourceLocation());
|
2010-11-18 14:31:45 +08:00
|
|
|
BinaryOperator *lessThanExpr =
|
|
|
|
new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy,
|
|
|
|
VK_RValue, OK_Ordinary, SourceLocation());
|
2007-12-04 03:17:29 +08:00
|
|
|
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
|
2009-09-09 23:08:12 +08:00
|
|
|
ConditionalOperator *CondExpr =
|
2009-08-26 22:37:04 +08:00
|
|
|
new (Context) ConditionalOperator(lessThanExpr,
|
|
|
|
SourceLocation(), CE,
|
2011-02-17 18:25:35 +08:00
|
|
|
SourceLocation(), STCE,
|
2010-11-19 03:01:18 +08:00
|
|
|
returnType, VK_RValue, OK_Ordinary);
|
2010-09-01 02:02:20 +08:00
|
|
|
ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
|
|
|
|
CondExpr);
|
2007-12-04 03:17:29 +08:00
|
|
|
}
|
2010-10-12 05:29:12 +08:00
|
|
|
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
|
2008-01-09 06:06:28 +08:00
|
|
|
return ReplacingStmt;
|
|
|
|
}
|
|
|
|
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
|
2010-02-23 04:48:10 +08:00
|
|
|
Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(),
|
|
|
|
Exp->getLocEnd());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-25 06:48:43 +08:00
|
|
|
// Now do the actual rewrite.
|
2008-02-01 03:37:57 +08:00
|
|
|
ReplaceStmt(Exp, ReplacingStmt);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-10-12 05:29:12 +08:00
|
|
|
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
|
2008-01-09 06:06:28 +08:00
|
|
|
return ReplacingStmt;
|
2007-10-24 07:50:29 +08:00
|
|
|
}
|
|
|
|
|
2009-04-30 00:37:50 +08:00
|
|
|
// typedef struct objc_object Protocol;
|
|
|
|
QualType RewriteObjC::getProtocolType() {
|
|
|
|
if (!ProtocolTypeDecl) {
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *TInfo
|
|
|
|
= Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
|
2009-04-30 00:37:50 +08:00
|
|
|
ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
|
2011-03-06 23:48:19 +08:00
|
|
|
SourceLocation(), SourceLocation(),
|
2009-04-30 00:37:50 +08:00
|
|
|
&Context->Idents.get("Protocol"),
|
2009-12-07 10:54:59 +08:00
|
|
|
TInfo);
|
2009-04-30 00:37:50 +08:00
|
|
|
}
|
|
|
|
return Context->getTypeDeclType(ProtocolTypeDecl);
|
|
|
|
}
|
|
|
|
|
2007-12-08 02:47:10 +08:00
|
|
|
/// RewriteObjCProtocolExpr - Rewrite a protocol expression into
|
2009-04-30 00:37:50 +08:00
|
|
|
/// a synthesized/forward data reference (to the protocol's metadata).
|
|
|
|
/// The forward references (and metadata) are generated in
|
|
|
|
/// RewriteObjC::HandleTranslationUnit().
|
2008-04-15 06:03:09 +08:00
|
|
|
Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
|
2009-04-30 00:37:50 +08:00
|
|
|
std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();
|
|
|
|
IdentifierInfo *ID = &Context->Idents.get(Name);
|
2009-09-09 23:08:12 +08:00
|
|
|
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation(), ID, getProtocolType(), 0,
|
2010-08-26 11:08:43 +08:00
|
|
|
SC_Extern, SC_None);
|
2010-11-18 14:31:45 +08:00
|
|
|
DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), VK_LValue,
|
|
|
|
SourceLocation());
|
2010-08-25 19:45:40 +08:00
|
|
|
Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
|
2009-04-30 00:37:50 +08:00
|
|
|
Context->getPointerType(DRE->getType()),
|
2010-11-18 14:31:45 +08:00
|
|
|
VK_RValue, OK_Ordinary, SourceLocation());
|
2010-01-16 02:39:57 +08:00
|
|
|
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
|
2010-11-15 17:46:46 +08:00
|
|
|
CK_BitCast,
|
2010-01-16 02:39:57 +08:00
|
|
|
DerefExpr);
|
2009-04-30 00:37:50 +08:00
|
|
|
ReplaceStmt(Exp, castExpr);
|
2012-01-02 02:09:12 +08:00
|
|
|
ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
|
2010-10-12 05:29:12 +08:00
|
|
|
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
|
2009-04-30 00:37:50 +08:00
|
|
|
return castExpr;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-12-08 02:47:10 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
|
2008-05-31 22:15:04 +08:00
|
|
|
const char *endBuf) {
|
|
|
|
while (startBuf < endBuf) {
|
|
|
|
if (*startBuf == '#') {
|
|
|
|
// Skip whitespace.
|
|
|
|
for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
|
|
|
|
;
|
|
|
|
if (!strncmp(startBuf, "if", strlen("if")) ||
|
|
|
|
!strncmp(startBuf, "ifdef", strlen("ifdef")) ||
|
|
|
|
!strncmp(startBuf, "ifndef", strlen("ifndef")) ||
|
|
|
|
!strncmp(startBuf, "define", strlen("define")) ||
|
|
|
|
!strncmp(startBuf, "undef", strlen("undef")) ||
|
|
|
|
!strncmp(startBuf, "else", strlen("else")) ||
|
|
|
|
!strncmp(startBuf, "elif", strlen("elif")) ||
|
|
|
|
!strncmp(startBuf, "endif", strlen("endif")) ||
|
|
|
|
!strncmp(startBuf, "pragma", strlen("pragma")) ||
|
|
|
|
!strncmp(startBuf, "include", strlen("include")) ||
|
|
|
|
!strncmp(startBuf, "import", strlen("import")) ||
|
|
|
|
!strncmp(startBuf, "include_next", strlen("include_next")))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
startBuf++;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-12-06 02:43:13 +08:00
|
|
|
/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
|
2007-10-27 03:46:17 +08:00
|
|
|
/// an objective-c class with ivars.
|
2011-12-06 02:43:13 +08:00
|
|
|
void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
|
2007-10-27 03:46:17 +08:00
|
|
|
std::string &Result) {
|
2008-01-08 03:49:32 +08:00
|
|
|
assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
|
2010-08-18 06:39:59 +08:00
|
|
|
assert(CDecl->getName() != "" &&
|
2008-11-17 22:58:09 +08:00
|
|
|
"Name missing in SynthesizeObjCInternalStruct");
|
2007-11-01 07:08:24 +08:00
|
|
|
// Do not synthesize more than once.
|
2008-01-08 03:49:32 +08:00
|
|
|
if (ObjCSynthesizedStructs.count(CDecl))
|
2007-11-01 07:08:24 +08:00
|
|
|
return;
|
2008-01-08 03:49:32 +08:00
|
|
|
ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
|
2008-03-17 05:08:55 +08:00
|
|
|
int NumIvars = CDecl->ivar_size();
|
2007-11-27 03:52:57 +08:00
|
|
|
SourceLocation LocStart = CDecl->getLocStart();
|
2011-12-16 06:34:59 +08:00
|
|
|
SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-27 03:52:57 +08:00
|
|
|
const char *startBuf = SM->getCharacterData(LocStart);
|
|
|
|
const char *endBuf = SM->getCharacterData(LocEnd);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-01 06:57:04 +08:00
|
|
|
// If no ivars and no root or if its root, directly or indirectly,
|
2007-11-01 07:53:01 +08:00
|
|
|
// have no ivars (thus not synthesized) then no need to synthesize this class.
|
2011-12-16 04:29:51 +08:00
|
|
|
if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) &&
|
2008-03-17 05:08:55 +08:00
|
|
|
(!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
|
2009-04-15 07:22:57 +08:00
|
|
|
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, endBuf-startBuf, Result);
|
2007-10-27 03:46:17 +08:00
|
|
|
return;
|
2007-11-27 03:52:57 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// FIXME: This has potential of causing problem. If
|
2008-01-08 03:49:32 +08:00
|
|
|
// SynthesizeObjCInternalStruct is ever called recursively.
|
2007-11-15 03:25:57 +08:00
|
|
|
Result += "\nstruct ";
|
2008-11-24 13:29:24 +08:00
|
|
|
Result += CDecl->getNameAsString();
|
2011-09-18 01:15:52 +08:00
|
|
|
if (LangOpts.MicrosoftExt)
|
2008-03-11 07:16:54 +08:00
|
|
|
Result += "_IMPL";
|
2008-03-12 08:25:36 +08:00
|
|
|
|
2007-11-01 01:29:28 +08:00
|
|
|
if (NumIvars > 0) {
|
2007-11-15 03:25:57 +08:00
|
|
|
const char *cursor = strchr(startBuf, '{');
|
2009-09-09 23:08:12 +08:00
|
|
|
assert((cursor && endBuf)
|
2008-01-08 03:49:32 +08:00
|
|
|
&& "SynthesizeObjCInternalStruct - malformed @interface");
|
2008-05-31 22:15:04 +08:00
|
|
|
// If the buffer contains preprocessor directives, we do more fine-grained
|
|
|
|
// rewrites. This is intended to fix code that looks like (which occurs in
|
|
|
|
// NSURL.h, for example):
|
|
|
|
//
|
|
|
|
// #ifdef XYZ
|
|
|
|
// @interface Foo : NSObject
|
|
|
|
// #else
|
|
|
|
// @interface FooBar : NSObject
|
|
|
|
// #endif
|
|
|
|
// {
|
|
|
|
// int i;
|
|
|
|
// }
|
|
|
|
// @end
|
|
|
|
//
|
|
|
|
// This clause is segregated to avoid breaking the common case.
|
|
|
|
if (BufferContainsPPDirectives(startBuf, cursor)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :
|
2011-10-04 12:48:02 +08:00
|
|
|
CDecl->getAtStartLoc();
|
2008-05-31 22:15:04 +08:00
|
|
|
const char *endHeader = SM->getCharacterData(L);
|
2009-04-15 07:22:57 +08:00
|
|
|
endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);
|
2008-05-31 22:15:04 +08:00
|
|
|
|
2009-02-21 02:18:36 +08:00
|
|
|
if (CDecl->protocol_begin() != CDecl->protocol_end()) {
|
2008-05-31 22:15:04 +08:00
|
|
|
// advance to the end of the referenced protocols.
|
|
|
|
while (endHeader < cursor && *endHeader != '>') endHeader++;
|
|
|
|
endHeader++;
|
|
|
|
}
|
|
|
|
// rewrite the original header
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, endHeader-startBuf, Result);
|
2008-05-31 22:15:04 +08:00
|
|
|
} else {
|
|
|
|
// rewrite the original header *without* disturbing the '{'
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, cursor-startBuf, Result);
|
2008-05-31 22:15:04 +08:00
|
|
|
}
|
2008-01-08 03:49:32 +08:00
|
|
|
if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
|
2007-11-15 03:25:57 +08:00
|
|
|
Result = "\n struct ";
|
2008-11-24 13:29:24 +08:00
|
|
|
Result += RCDecl->getNameAsString();
|
2008-03-13 05:09:20 +08:00
|
|
|
Result += "_IMPL ";
|
2008-11-24 13:29:24 +08:00
|
|
|
Result += RCDecl->getNameAsString();
|
2008-03-13 05:22:52 +08:00
|
|
|
Result += "_IVARS;\n";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-15 03:25:57 +08:00
|
|
|
// insert the super class structure definition.
|
2008-02-01 03:42:41 +08:00
|
|
|
SourceLocation OnePastCurly =
|
2011-09-20 04:40:19 +08:00
|
|
|
LocStart.getLocWithOffset(cursor-startBuf+1);
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(OnePastCurly, Result);
|
2007-11-15 03:25:57 +08:00
|
|
|
}
|
|
|
|
cursor++; // past '{'
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-11-15 03:25:57 +08:00
|
|
|
// Now comment out any visibility specifiers.
|
|
|
|
while (cursor < endBuf) {
|
|
|
|
if (*cursor == '@') {
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
|
2007-11-15 06:57:51 +08:00
|
|
|
// Skip whitespace.
|
|
|
|
for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
|
|
|
|
/*scan*/;
|
|
|
|
|
2007-11-01 01:29:28 +08:00
|
|
|
// FIXME: presence of @public, etc. inside comment results in
|
|
|
|
// this transformation as well, which is still correct c-code.
|
2007-11-15 03:25:57 +08:00
|
|
|
if (!strncmp(cursor, "public", strlen("public")) ||
|
|
|
|
!strncmp(cursor, "private", strlen("private")) ||
|
2008-04-05 06:34:24 +08:00
|
|
|
!strncmp(cursor, "package", strlen("package")) ||
|
2007-11-15 06:26:25 +08:00
|
|
|
!strncmp(cursor, "protected", strlen("protected")))
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(atLoc, "// ");
|
2007-11-01 01:29:28 +08:00
|
|
|
}
|
2007-11-15 06:26:25 +08:00
|
|
|
// FIXME: If there are cases where '<' is used in ivar declaration part
|
|
|
|
// of user code, then scan the ivar list and use needToScanForQualifiers
|
|
|
|
// for type checking.
|
|
|
|
else if (*cursor == '<') {
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(atLoc, "/* ");
|
2007-11-15 06:26:25 +08:00
|
|
|
cursor = strchr(cursor, '>');
|
|
|
|
cursor++;
|
2011-09-20 04:40:19 +08:00
|
|
|
atLoc = LocStart.getLocWithOffset(cursor-startBuf);
|
2010-02-14 22:14:16 +08:00
|
|
|
InsertText(atLoc, " */");
|
2008-10-30 20:09:33 +08:00
|
|
|
} else if (*cursor == '^') { // rewrite block specifier.
|
2011-09-20 04:40:19 +08:00
|
|
|
SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf);
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(caretLoc, 1, "*");
|
2007-11-15 06:26:25 +08:00
|
|
|
}
|
2007-11-15 03:25:57 +08:00
|
|
|
cursor++;
|
2007-11-01 01:29:28 +08:00
|
|
|
}
|
2007-11-15 03:25:57 +08:00
|
|
|
// Don't forget to add a ';'!!
|
2011-09-20 04:40:19 +08:00
|
|
|
InsertText(LocEnd.getLocWithOffset(1), ";");
|
2007-11-15 03:25:57 +08:00
|
|
|
} else { // we don't have any instance variables - insert super struct.
|
2009-04-15 07:22:57 +08:00
|
|
|
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
|
2007-11-15 03:25:57 +08:00
|
|
|
Result += " {\n struct ";
|
2008-11-24 13:29:24 +08:00
|
|
|
Result += RCDecl->getNameAsString();
|
2008-03-13 05:09:20 +08:00
|
|
|
Result += "_IMPL ";
|
2008-11-24 13:29:24 +08:00
|
|
|
Result += RCDecl->getNameAsString();
|
2008-03-13 05:22:52 +08:00
|
|
|
Result += "_IVARS;\n};\n";
|
2010-02-14 22:14:16 +08:00
|
|
|
ReplaceText(LocStart, endBuf-startBuf, Result);
|
2007-10-27 03:46:17 +08:00
|
|
|
}
|
|
|
|
// Mark this struct as having been generated.
|
2008-01-08 03:49:32 +08:00
|
|
|
if (!ObjCSynthesizedStructs.insert(CDecl))
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct");
|
2007-10-27 03:46:17 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Meta Data Emission
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
/// RewriteImplementations - This routine rewrites all method implementations
|
|
|
|
/// and emits meta-data.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::RewriteImplementations() {
|
|
|
|
int ClsDefCount = ClassImplementation.size();
|
|
|
|
int CatDefCount = CategoryImplementation.size();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Rewrite implemented methods
|
|
|
|
for (int i = 0; i < ClsDefCount; i++)
|
|
|
|
RewriteImplementationDecl(ClassImplementation[i]);
|
2007-12-12 15:46:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
for (int i = 0; i < CatDefCount; i++)
|
|
|
|
RewriteImplementationDecl(CategoryImplementation[i]);
|
2007-10-25 03:23:36 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::RewriteByRefString(std::string &ResultStr,
|
|
|
|
const std::string &Name,
|
|
|
|
ValueDecl *VD, bool def) {
|
|
|
|
assert(BlockByRefDeclNo.count(VD) &&
|
|
|
|
"RewriteByRefString: ByRef decl missing");
|
|
|
|
if (def)
|
|
|
|
ResultStr += "struct ";
|
|
|
|
ResultStr += "__Block_byref_" + Name +
|
|
|
|
"_" + utostr(BlockByRefDeclNo[VD]) ;
|
|
|
|
}
|
2009-04-30 00:37:50 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
|
|
|
|
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
|
|
|
|
return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
|
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
|
|
|
|
StringRef funcName,
|
|
|
|
std::string Tag) {
|
|
|
|
const FunctionType *AFT = CE->getFunctionType();
|
|
|
|
QualType RT = AFT->getResultType();
|
|
|
|
std::string StructRef = "struct " + Tag;
|
|
|
|
std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
|
|
|
|
funcName.str() + "_" + "block_func_" + utostr(i);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
BlockDecl *BD = CE->getBlockDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (isa<FunctionNoProtoType>(AFT)) {
|
|
|
|
// No user-supplied arguments. Still need to pass in a pointer to the
|
|
|
|
// block (to reference imported block decl refs).
|
|
|
|
S += "(" + StructRef + " *__cself)";
|
|
|
|
} else if (BD->param_empty()) {
|
|
|
|
S += "(" + StructRef + " *__cself)";
|
|
|
|
} else {
|
|
|
|
const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
|
|
|
|
assert(FT && "SynthesizeBlockFunc: No function proto");
|
|
|
|
S += '(';
|
|
|
|
// first add the implicit argument.
|
|
|
|
S += StructRef + " *__cself, ";
|
|
|
|
std::string ParamStr;
|
|
|
|
for (BlockDecl::param_iterator AI = BD->param_begin(),
|
|
|
|
E = BD->param_end(); AI != E; ++AI) {
|
|
|
|
if (AI != BD->param_begin()) S += ", ";
|
|
|
|
ParamStr = (*AI)->getNameAsString();
|
|
|
|
QualType QT = (*AI)->getType();
|
|
|
|
if (convertBlockPointerToFunctionPointer(QT))
|
|
|
|
QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
|
2009-04-30 00:37:50 +08:00
|
|
|
else
|
2011-12-09 02:25:15 +08:00
|
|
|
QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
|
|
|
|
S += ParamStr;
|
2008-07-22 05:33:21 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
if (FT->isVariadic()) {
|
|
|
|
if (!BD->param_empty()) S += ", ";
|
|
|
|
S += "...";
|
|
|
|
}
|
|
|
|
S += ')';
|
2009-04-30 00:37:50 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
S += " {\n";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Create local declarations to avoid rewriting all closure decl ref exprs.
|
|
|
|
// First, emit a declaration for all "by ref" decls.
|
|
|
|
for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
|
|
|
|
E = BlockByRefDecls.end(); I != E; ++I) {
|
|
|
|
S += " ";
|
|
|
|
std::string Name = (*I)->getNameAsString();
|
|
|
|
std::string TypeString;
|
|
|
|
RewriteByRefString(TypeString, Name, (*I));
|
|
|
|
TypeString += " *";
|
|
|
|
Name = TypeString + Name;
|
|
|
|
S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
|
|
|
|
}
|
|
|
|
// Next, emit a declaration for all "by copy" declarations.
|
|
|
|
for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
|
|
|
|
E = BlockByCopyDecls.end(); I != E; ++I) {
|
|
|
|
S += " ";
|
|
|
|
// Handle nested closure invocation. For example:
|
|
|
|
//
|
|
|
|
// void (^myImportedClosure)(void);
|
|
|
|
// myImportedClosure = ^(void) { setGlobalInt(x + y); };
|
|
|
|
//
|
|
|
|
// void (^anotherClosure)(void);
|
|
|
|
// anotherClosure = ^(void) {
|
|
|
|
// myImportedClosure(); // import and invoke the closure
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
if (isTopLevelBlockPointerType((*I)->getType())) {
|
|
|
|
RewriteBlockPointerTypeVariable(S, (*I));
|
|
|
|
S += " = (";
|
|
|
|
RewriteBlockPointerType(S, (*I)->getType());
|
|
|
|
S += ")";
|
|
|
|
S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
std::string Name = (*I)->getNameAsString();
|
|
|
|
QualType QT = (*I)->getType();
|
|
|
|
if (HasLocalVariableExternalStorage(*I))
|
|
|
|
QT = Context->getPointerType(QT);
|
|
|
|
QT.getAsStringInternal(Name, Context->getPrintingPolicy());
|
|
|
|
S += Name + " = __cself->" +
|
|
|
|
(*I)->getNameAsString() + "; // bound by copy\n";
|
2007-10-23 05:41:37 +08:00
|
|
|
}
|
2009-04-30 00:37:50 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string RewrittenStr = RewrittenBlockExprs[CE];
|
|
|
|
const char *cstr = RewrittenStr.c_str();
|
|
|
|
while (*cstr++ != '{') ;
|
|
|
|
S += cstr;
|
|
|
|
S += "\n";
|
|
|
|
return S;
|
|
|
|
}
|
2009-04-30 00:37:50 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
|
|
|
|
StringRef funcName,
|
|
|
|
std::string Tag) {
|
|
|
|
std::string StructRef = "struct " + Tag;
|
|
|
|
std::string S = "static void __";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
S += funcName;
|
|
|
|
S += "_block_copy_" + utostr(i);
|
|
|
|
S += "(" + StructRef;
|
|
|
|
S += "*dst, " + StructRef;
|
|
|
|
S += "*src) {";
|
|
|
|
for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
|
|
|
|
E = ImportedBlockDecls.end(); I != E; ++I) {
|
|
|
|
ValueDecl *VD = (*I);
|
|
|
|
S += "_Block_object_assign((void*)&dst->";
|
|
|
|
S += (*I)->getNameAsString();
|
|
|
|
S += ", (void*)src->";
|
|
|
|
S += (*I)->getNameAsString();
|
|
|
|
if (BlockByRefDeclsPtrSet.count((*I)))
|
|
|
|
S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
|
|
|
|
else if (VD->getType()->isBlockPointerType())
|
|
|
|
S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
|
|
|
|
else
|
|
|
|
S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
|
2008-07-22 05:33:21 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
S += "}\n";
|
|
|
|
|
|
|
|
S += "\nstatic void __";
|
|
|
|
S += funcName;
|
|
|
|
S += "_block_dispose_" + utostr(i);
|
|
|
|
S += "(" + StructRef;
|
|
|
|
S += "*src) {";
|
|
|
|
for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
|
|
|
|
E = ImportedBlockDecls.end(); I != E; ++I) {
|
|
|
|
ValueDecl *VD = (*I);
|
|
|
|
S += "_Block_object_dispose((void*)src->";
|
|
|
|
S += (*I)->getNameAsString();
|
|
|
|
if (BlockByRefDeclsPtrSet.count((*I)))
|
|
|
|
S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
|
|
|
|
else if (VD->getType()->isBlockPointerType())
|
|
|
|
S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
|
|
|
|
else
|
|
|
|
S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
|
2009-04-30 00:37:50 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
S += "}\n";
|
|
|
|
return S;
|
2009-04-30 00:37:50 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
|
|
|
|
std::string Desc) {
|
|
|
|
std::string S = "\nstruct " + Tag;
|
|
|
|
std::string Constructor = " " + Tag;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
S += " {\n struct __block_impl impl;\n";
|
|
|
|
S += " struct " + Desc;
|
|
|
|
S += "* Desc;\n";
|
2009-04-30 00:37:50 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
Constructor += "(void *fp, "; // Invoke function pointer.
|
|
|
|
Constructor += "struct " + Desc; // Descriptor pointer.
|
|
|
|
Constructor += " *desc";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (BlockDeclRefs.size()) {
|
|
|
|
// Output all "by copy" declarations.
|
|
|
|
for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
|
|
|
|
E = BlockByCopyDecls.end(); I != E; ++I) {
|
|
|
|
S += " ";
|
|
|
|
std::string FieldName = (*I)->getNameAsString();
|
|
|
|
std::string ArgName = "_" + FieldName;
|
|
|
|
// Handle nested closure invocation. For example:
|
|
|
|
//
|
|
|
|
// void (^myImportedBlock)(void);
|
|
|
|
// myImportedBlock = ^(void) { setGlobalInt(x + y); };
|
|
|
|
//
|
|
|
|
// void (^anotherBlock)(void);
|
|
|
|
// anotherBlock = ^(void) {
|
|
|
|
// myImportedBlock(); // import and invoke the closure
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
if (isTopLevelBlockPointerType((*I)->getType())) {
|
|
|
|
S += "struct __block_impl *";
|
|
|
|
Constructor += ", void *" + ArgName;
|
|
|
|
} else {
|
|
|
|
QualType QT = (*I)->getType();
|
|
|
|
if (HasLocalVariableExternalStorage(*I))
|
|
|
|
QT = Context->getPointerType(QT);
|
|
|
|
QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
|
|
|
|
QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
|
|
|
|
Constructor += ", " + ArgName;
|
|
|
|
}
|
|
|
|
S += FieldName + ";\n";
|
|
|
|
}
|
|
|
|
// Output all "by ref" declarations.
|
|
|
|
for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
|
|
|
|
E = BlockByRefDecls.end(); I != E; ++I) {
|
|
|
|
S += " ";
|
|
|
|
std::string FieldName = (*I)->getNameAsString();
|
|
|
|
std::string ArgName = "_" + FieldName;
|
|
|
|
{
|
|
|
|
std::string TypeString;
|
|
|
|
RewriteByRefString(TypeString, FieldName, (*I));
|
|
|
|
TypeString += " *";
|
|
|
|
FieldName = TypeString + FieldName;
|
|
|
|
ArgName = TypeString + ArgName;
|
|
|
|
Constructor += ", " + ArgName;
|
|
|
|
}
|
|
|
|
S += FieldName + "; // by ref\n";
|
|
|
|
}
|
|
|
|
// Finish writing the constructor.
|
|
|
|
Constructor += ", int flags=0)";
|
|
|
|
// Initialize all "by copy" arguments.
|
|
|
|
bool firsTime = true;
|
|
|
|
for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
|
|
|
|
E = BlockByCopyDecls.end(); I != E; ++I) {
|
|
|
|
std::string Name = (*I)->getNameAsString();
|
|
|
|
if (firsTime) {
|
|
|
|
Constructor += " : ";
|
|
|
|
firsTime = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Constructor += ", ";
|
|
|
|
if (isTopLevelBlockPointerType((*I)->getType()))
|
|
|
|
Constructor += Name + "((struct __block_impl *)_" + Name + ")";
|
|
|
|
else
|
|
|
|
Constructor += Name + "(_" + Name + ")";
|
|
|
|
}
|
|
|
|
// Initialize all "by ref" arguments.
|
|
|
|
for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
|
|
|
|
E = BlockByRefDecls.end(); I != E; ++I) {
|
|
|
|
std::string Name = (*I)->getNameAsString();
|
|
|
|
if (firsTime) {
|
|
|
|
Constructor += " : ";
|
|
|
|
firsTime = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Constructor += ", ";
|
|
|
|
Constructor += Name + "(_" + Name + "->__forwarding)";
|
|
|
|
}
|
|
|
|
|
|
|
|
Constructor += " {\n";
|
|
|
|
if (GlobalVarDecl)
|
|
|
|
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
|
|
|
|
else
|
|
|
|
Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
|
|
|
|
Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
Constructor += " Desc = desc;\n";
|
|
|
|
} else {
|
|
|
|
// Finish writing the constructor.
|
|
|
|
Constructor += ", int flags=0) {\n";
|
|
|
|
if (GlobalVarDecl)
|
|
|
|
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
|
|
|
|
else
|
|
|
|
Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
|
|
|
|
Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
|
|
|
|
Constructor += " Desc = desc;\n";
|
2008-07-22 05:33:21 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
Constructor += " ";
|
|
|
|
Constructor += "}\n";
|
|
|
|
S += Constructor;
|
|
|
|
S += "};\n";
|
|
|
|
return S;
|
2007-10-25 03:23:36 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
|
|
|
|
std::string ImplTag, int i,
|
|
|
|
StringRef FunName,
|
|
|
|
unsigned hasCopy) {
|
|
|
|
std::string S = "\nstatic struct " + DescTag;
|
|
|
|
|
|
|
|
S += " {\n unsigned long reserved;\n";
|
|
|
|
S += " unsigned long Block_size;\n";
|
|
|
|
if (hasCopy) {
|
|
|
|
S += " void (*copy)(struct ";
|
|
|
|
S += ImplTag; S += "*, struct ";
|
|
|
|
S += ImplTag; S += "*);\n";
|
|
|
|
|
|
|
|
S += " void (*dispose)(struct ";
|
|
|
|
S += ImplTag; S += "*);\n";
|
|
|
|
}
|
|
|
|
S += "} ";
|
2009-04-30 00:37:50 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
S += DescTag + "_DATA = { 0, sizeof(struct ";
|
|
|
|
S += ImplTag + ")";
|
|
|
|
if (hasCopy) {
|
|
|
|
S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
|
|
|
|
S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
|
|
|
|
}
|
|
|
|
S += "};\n";
|
|
|
|
return S;
|
|
|
|
}
|
2009-04-23 09:02:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
|
|
|
|
StringRef FunName) {
|
|
|
|
// Insert declaration for the function in which block literal is used.
|
|
|
|
if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
|
|
|
|
RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
|
|
|
|
bool RewriteSC = (GlobalVarDecl &&
|
|
|
|
!Blocks.empty() &&
|
|
|
|
GlobalVarDecl->getStorageClass() == SC_Static &&
|
|
|
|
GlobalVarDecl->getType().getCVRQualifiers());
|
|
|
|
if (RewriteSC) {
|
|
|
|
std::string SC(" void __");
|
|
|
|
SC += GlobalVarDecl->getNameAsString();
|
|
|
|
SC += "() {}";
|
|
|
|
InsertText(FunLocStart, SC);
|
2009-04-23 09:02:12 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
// Insert closures that were part of the function.
|
|
|
|
for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
|
|
|
|
CollectBlockDeclRefInfo(Blocks[i]);
|
|
|
|
// Need to copy-in the inner copied-in variables not actually used in this
|
|
|
|
// block.
|
|
|
|
for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
|
|
|
|
BlockDeclRefExpr *Exp = InnerDeclRefs[count++];
|
|
|
|
ValueDecl *VD = Exp->getDecl();
|
|
|
|
BlockDeclRefs.push_back(Exp);
|
|
|
|
if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) {
|
|
|
|
BlockByCopyDeclsPtrSet.insert(VD);
|
|
|
|
BlockByCopyDecls.push_back(VD);
|
|
|
|
}
|
|
|
|
if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) {
|
|
|
|
BlockByRefDeclsPtrSet.insert(VD);
|
|
|
|
BlockByRefDecls.push_back(VD);
|
|
|
|
}
|
|
|
|
// imported objects in the inner blocks not used in the outer
|
|
|
|
// blocks must be copied/disposed in the outer block as well.
|
|
|
|
if (Exp->isByRef() ||
|
|
|
|
VD->getType()->isObjCObjectPointerType() ||
|
|
|
|
VD->getType()->isBlockPointerType())
|
|
|
|
ImportedBlockDecls.insert(VD);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
|
|
|
|
std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
InsertText(FunLocStart, CI);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
InsertText(FunLocStart, CF);
|
2007-10-25 03:23:36 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ImportedBlockDecls.size()) {
|
|
|
|
std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
|
|
|
|
InsertText(FunLocStart, HF);
|
|
|
|
}
|
|
|
|
std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
|
|
|
|
ImportedBlockDecls.size() > 0);
|
|
|
|
InsertText(FunLocStart, BD);
|
|
|
|
|
|
|
|
BlockDeclRefs.clear();
|
|
|
|
BlockByRefDecls.clear();
|
|
|
|
BlockByRefDeclsPtrSet.clear();
|
|
|
|
BlockByCopyDecls.clear();
|
|
|
|
BlockByCopyDeclsPtrSet.clear();
|
|
|
|
ImportedBlockDecls.clear();
|
|
|
|
}
|
|
|
|
if (RewriteSC) {
|
|
|
|
// Must insert any 'const/volatile/static here. Since it has been
|
|
|
|
// removed as result of rewriting of block literals.
|
|
|
|
std::string SC;
|
|
|
|
if (GlobalVarDecl->getStorageClass() == SC_Static)
|
|
|
|
SC = "static ";
|
|
|
|
if (GlobalVarDecl->getType().isConstQualified())
|
|
|
|
SC += "const ";
|
|
|
|
if (GlobalVarDecl->getType().isVolatileQualified())
|
|
|
|
SC += "volatile ";
|
|
|
|
if (GlobalVarDecl->getType().isRestrictQualified())
|
|
|
|
SC += "restrict ";
|
|
|
|
InsertText(FunLocStart, SC);
|
2008-07-17 02:22:22 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
Blocks.clear();
|
|
|
|
InnerDeclRefsCount.clear();
|
|
|
|
InnerDeclRefs.clear();
|
|
|
|
RewrittenBlockExprs.clear();
|
2007-10-27 03:46:17 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
|
|
|
|
SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
|
|
|
|
StringRef FuncName = FD->getName();
|
2007-10-25 03:23:36 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
SynthesizeBlockLiterals(FunLocStart, FuncName);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
static void BuildUniqueMethodName(std::string &Name,
|
|
|
|
ObjCMethodDecl *MD) {
|
|
|
|
ObjCInterfaceDecl *IFace = MD->getClassInterface();
|
|
|
|
Name = IFace->getName();
|
|
|
|
Name += "__" + MD->getSelector().getAsString();
|
|
|
|
// Convert colons to underscores.
|
|
|
|
std::string::size_type loc = 0;
|
|
|
|
while ((loc = Name.find(":", loc)) != std::string::npos)
|
|
|
|
Name.replace(loc, 1, "_");
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
|
|
|
|
//fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
|
|
|
|
//SourceLocation FunLocStart = MD->getLocStart();
|
|
|
|
SourceLocation FunLocStart = MD->getLocStart();
|
|
|
|
std::string FuncName;
|
|
|
|
BuildUniqueMethodName(FuncName, MD);
|
|
|
|
SynthesizeBlockLiterals(FunLocStart, FuncName);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
|
|
|
|
for (Stmt::child_range CI = S->children(); CI; ++CI)
|
|
|
|
if (*CI) {
|
|
|
|
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
|
|
|
|
GetBlockDeclRefExprs(CBE->getBody());
|
|
|
|
else
|
|
|
|
GetBlockDeclRefExprs(*CI);
|
|
|
|
}
|
|
|
|
// Handle specific things.
|
|
|
|
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
|
|
|
|
// FIXME: Handle enums.
|
|
|
|
if (!isa<FunctionDecl>(CDRE->getDecl()))
|
|
|
|
BlockDeclRefs.push_back(CDRE);
|
|
|
|
}
|
|
|
|
else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
|
|
|
|
if (HasLocalVariableExternalStorage(DRE->getDecl())) {
|
|
|
|
BlockDeclRefExpr *BDRE =
|
|
|
|
new (Context)BlockDeclRefExpr(cast<VarDecl>(DRE->getDecl()),
|
|
|
|
DRE->getType(),
|
|
|
|
VK_LValue, DRE->getLocation(), false);
|
|
|
|
BlockDeclRefs.push_back(BDRE);
|
2007-10-25 03:23:36 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2007-10-25 03:23:36 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
|
|
|
|
SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
|
|
|
|
llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
|
|
|
|
for (Stmt::child_range CI = S->children(); CI; ++CI)
|
|
|
|
if (*CI) {
|
|
|
|
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
|
|
|
|
InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
|
|
|
|
GetInnerBlockDeclRefExprs(CBE->getBody(),
|
|
|
|
InnerBlockDeclRefs,
|
|
|
|
InnerContexts);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
GetInnerBlockDeclRefExprs(*CI,
|
|
|
|
InnerBlockDeclRefs,
|
|
|
|
InnerContexts);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-10-26 04:55:25 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// Handle specific things.
|
|
|
|
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
|
|
|
|
if (!isa<FunctionDecl>(CDRE->getDecl()) &&
|
|
|
|
!InnerContexts.count(CDRE->getDecl()->getDeclContext()))
|
|
|
|
InnerBlockDeclRefs.push_back(CDRE);
|
|
|
|
}
|
|
|
|
else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
|
|
|
|
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
|
|
|
|
if (Var->isFunctionOrMethodVarDecl())
|
|
|
|
ImportedLocalExternalDecls.insert(Var);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
/// convertFunctionTypeOfBlocks - This routine converts a function type
|
|
|
|
/// whose result type may be a block pointer or whose argument type(s)
|
|
|
|
/// might be block pointers to an equivalent function type replacing
|
|
|
|
/// all block pointers to function pointers.
|
|
|
|
QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
|
|
|
|
const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
|
|
|
|
// FTP will be null for closures that don't take arguments.
|
|
|
|
// Generate a funky cast.
|
|
|
|
SmallVector<QualType, 8> ArgTypes;
|
|
|
|
QualType Res = FT->getResultType();
|
|
|
|
bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
|
|
|
|
|
|
|
|
if (FTP) {
|
|
|
|
for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
|
|
|
|
E = FTP->arg_type_end(); I && (I != E); ++I) {
|
|
|
|
QualType t = *I;
|
|
|
|
// Make sure we convert "t (^)(...)" to "t (*)(...)".
|
|
|
|
if (convertBlockPointerToFunctionPointer(t))
|
|
|
|
HasBlockType = true;
|
|
|
|
ArgTypes.push_back(t);
|
|
|
|
}
|
2007-10-25 03:23:36 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
QualType FuncType;
|
|
|
|
// FIXME. Does this work if block takes no argument but has a return type
|
|
|
|
// which is of block type?
|
|
|
|
if (HasBlockType)
|
|
|
|
FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size());
|
|
|
|
else FuncType = QualType(FT, 0);
|
|
|
|
return FuncType;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
|
|
|
|
// Navigate to relevant type information.
|
|
|
|
const BlockPointerType *CPT = 0;
|
2009-04-23 09:02:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
|
|
|
|
CPT = DRE->getType()->getAs<BlockPointerType>();
|
|
|
|
} else if (const BlockDeclRefExpr *CDRE =
|
|
|
|
dyn_cast<BlockDeclRefExpr>(BlockExp)) {
|
|
|
|
CPT = CDRE->getType()->getAs<BlockPointerType>();
|
|
|
|
} else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
|
|
|
|
CPT = MExpr->getType()->getAs<BlockPointerType>();
|
|
|
|
}
|
|
|
|
else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
|
|
|
|
return SynthesizeBlockCall(Exp, PRE->getSubExpr());
|
2009-04-23 09:02:12 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
|
|
|
|
CPT = IEXPR->getType()->getAs<BlockPointerType>();
|
|
|
|
else if (const ConditionalOperator *CEXPR =
|
|
|
|
dyn_cast<ConditionalOperator>(BlockExp)) {
|
|
|
|
Expr *LHSExp = CEXPR->getLHS();
|
|
|
|
Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
|
|
|
|
Expr *RHSExp = CEXPR->getRHS();
|
|
|
|
Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
|
|
|
|
Expr *CONDExp = CEXPR->getCond();
|
|
|
|
ConditionalOperator *CondExpr =
|
|
|
|
new (Context) ConditionalOperator(CONDExp,
|
|
|
|
SourceLocation(), cast<Expr>(LHSStmt),
|
|
|
|
SourceLocation(), cast<Expr>(RHSStmt),
|
|
|
|
Exp->getType(), VK_RValue, OK_Ordinary);
|
|
|
|
return CondExpr;
|
|
|
|
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
|
|
|
|
CPT = IRE->getType()->getAs<BlockPointerType>();
|
|
|
|
} else if (const PseudoObjectExpr *POE
|
|
|
|
= dyn_cast<PseudoObjectExpr>(BlockExp)) {
|
|
|
|
CPT = POE->getType()->castAs<BlockPointerType>();
|
|
|
|
} else {
|
|
|
|
assert(1 && "RewriteBlockClass: Bad type");
|
|
|
|
}
|
|
|
|
assert(CPT && "RewriteBlockClass: Bad type");
|
|
|
|
const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
|
|
|
|
assert(FT && "RewriteBlockClass: Bad type");
|
|
|
|
const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
|
|
|
|
// FTP will be null for closures that don't take arguments.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get("__block_impl"));
|
|
|
|
QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Generate a funky cast.
|
|
|
|
SmallVector<QualType, 8> ArgTypes;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Push the block argument type.
|
|
|
|
ArgTypes.push_back(PtrBlock);
|
|
|
|
if (FTP) {
|
|
|
|
for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
|
|
|
|
E = FTP->arg_type_end(); I && (I != E); ++I) {
|
|
|
|
QualType t = *I;
|
|
|
|
// Make sure we convert "t (^)(...)" to "t (*)(...)".
|
|
|
|
if (!convertBlockPointerToFunctionPointer(t))
|
|
|
|
convertToUnqualifiedObjCType(t);
|
|
|
|
ArgTypes.push_back(t);
|
|
|
|
}
|
2007-10-23 08:02:02 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// Now do the pointer to function cast.
|
|
|
|
QualType PtrToFuncCastType
|
|
|
|
= getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
|
|
|
|
CK_BitCast,
|
|
|
|
const_cast<Expr*>(BlockExp));
|
|
|
|
// Don't forget the parens to enforce the proper binding.
|
|
|
|
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
|
|
|
|
BlkCast);
|
|
|
|
//PE->dump();
|
2007-10-26 04:55:25 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context->Idents.get("FuncPtr"),
|
|
|
|
Context->VoidPtrTy, 0,
|
|
|
|
/*BitWidth=*/0, /*Mutable=*/true,
|
|
|
|
/*HasInit=*/false);
|
|
|
|
MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(),
|
|
|
|
FD->getType(), VK_LValue,
|
|
|
|
OK_Ordinary);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
|
|
|
|
CK_BitCast, ME);
|
|
|
|
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
|
|
|
|
|
|
|
|
SmallVector<Expr*, 8> BlkExprs;
|
|
|
|
// Add the implicit argument.
|
|
|
|
BlkExprs.push_back(BlkCast);
|
|
|
|
// Add the user arguments.
|
|
|
|
for (CallExpr::arg_iterator I = Exp->arg_begin(),
|
|
|
|
E = Exp->arg_end(); I != E; ++I) {
|
|
|
|
BlkExprs.push_back(*I);
|
2007-10-26 04:55:25 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0],
|
|
|
|
BlkExprs.size(),
|
|
|
|
Exp->getType(), VK_RValue,
|
|
|
|
SourceLocation());
|
|
|
|
return CE;
|
2007-10-23 08:02:02 +08:00
|
|
|
}
|
2007-10-19 06:09:03 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// We need to return the rewritten expression to handle cases where the
|
|
|
|
// BlockDeclRefExpr is embedded in another expression being rewritten.
|
|
|
|
// For example:
|
|
|
|
//
|
|
|
|
// int main() {
|
|
|
|
// __block Foo *f;
|
|
|
|
// __block int i;
|
|
|
|
//
|
|
|
|
// void (^myblock)() = ^() {
|
|
|
|
// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).
|
|
|
|
// i = 77;
|
|
|
|
// };
|
|
|
|
//}
|
|
|
|
Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) {
|
|
|
|
// Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
|
|
|
|
// for each DeclRefExp where BYREFVAR is name of the variable.
|
|
|
|
ValueDecl *VD;
|
|
|
|
bool isArrow = true;
|
|
|
|
if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp))
|
|
|
|
VD = BDRE->getDecl();
|
|
|
|
else {
|
|
|
|
VD = cast<DeclRefExpr>(DeclRefExp)->getDecl();
|
|
|
|
isArrow = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
&Context->Idents.get("__forwarding"),
|
|
|
|
Context->VoidPtrTy, 0,
|
|
|
|
/*BitWidth=*/0, /*Mutable=*/true,
|
|
|
|
/*HasInit=*/false);
|
|
|
|
MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow,
|
|
|
|
FD, SourceLocation(),
|
|
|
|
FD->getType(), VK_LValue,
|
|
|
|
OK_Ordinary);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
StringRef Name = VD->getName();
|
|
|
|
FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get(Name),
|
|
|
|
Context->VoidPtrTy, 0,
|
|
|
|
/*BitWidth=*/0, /*Mutable=*/true,
|
|
|
|
/*HasInit=*/false);
|
|
|
|
ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(),
|
|
|
|
DeclRefExp->getType(), VK_LValue, OK_Ordinary);
|
2010-02-26 09:42:20 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
|
|
|
|
// Need parens to enforce precedence.
|
|
|
|
ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
|
|
|
|
DeclRefExp->getExprLoc(),
|
|
|
|
ME);
|
|
|
|
ReplaceStmt(DeclRefExp, PE);
|
|
|
|
return PE;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Rewrites the imported local variable V with external storage
|
|
|
|
// (static, extern, etc.) as *V
|
|
|
|
//
|
|
|
|
Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
|
|
|
|
ValueDecl *VD = DRE->getDecl();
|
|
|
|
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
|
|
|
|
if (!ImportedLocalExternalDecls.count(Var))
|
|
|
|
return DRE;
|
|
|
|
Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(),
|
|
|
|
VK_LValue, OK_Ordinary,
|
|
|
|
DRE->getLocation());
|
|
|
|
// Need parens to enforce precedence.
|
|
|
|
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
|
|
|
|
Exp);
|
|
|
|
ReplaceStmt(DRE, PE);
|
|
|
|
return PE;
|
|
|
|
}
|
2009-04-30 00:37:50 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
|
|
|
|
SourceLocation LocStart = CE->getLParenLoc();
|
|
|
|
SourceLocation LocEnd = CE->getRParenLoc();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Need to avoid trying to rewrite synthesized casts.
|
|
|
|
if (LocStart.isInvalid())
|
|
|
|
return;
|
|
|
|
// Need to avoid trying to rewrite casts contained in macros.
|
|
|
|
if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
const char *startBuf = SM->getCharacterData(LocStart);
|
|
|
|
const char *endBuf = SM->getCharacterData(LocEnd);
|
|
|
|
QualType QT = CE->getType();
|
|
|
|
const Type* TypePtr = QT->getAs<Type>();
|
|
|
|
if (isa<TypeOfExprType>(TypePtr)) {
|
|
|
|
const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
|
|
|
|
QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
|
|
|
|
std::string TypeAsString = "(";
|
|
|
|
RewriteBlockPointerType(TypeAsString, QT);
|
|
|
|
TypeAsString += ")";
|
|
|
|
ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
|
|
|
|
return;
|
2007-10-26 04:55:25 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// advance the location to startArgList.
|
|
|
|
const char *argPtr = startBuf;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
while (*argPtr++ && (argPtr < endBuf)) {
|
|
|
|
switch (*argPtr) {
|
|
|
|
case '^':
|
|
|
|
// Replace the '^' with '*'.
|
|
|
|
LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
|
|
|
|
ReplaceText(LocStart, 1, "*");
|
|
|
|
break;
|
|
|
|
}
|
2007-10-26 04:55:25 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
return;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
|
|
|
|
SourceLocation DeclLoc = FD->getLocation();
|
|
|
|
unsigned parenCount = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// We have 1 or more arguments that have closure pointers.
|
|
|
|
const char *startBuf = SM->getCharacterData(DeclLoc);
|
|
|
|
const char *startArgList = strchr(startBuf, '(');
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
parenCount++;
|
|
|
|
// advance the location to startArgList.
|
|
|
|
DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
|
|
|
|
assert((DeclLoc.isValid()) && "Invalid DeclLoc");
|
2008-03-11 04:43:59 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
const char *argPtr = startArgList;
|
|
|
|
|
|
|
|
while (*argPtr++ && parenCount) {
|
|
|
|
switch (*argPtr) {
|
|
|
|
case '^':
|
|
|
|
// Replace the '^' with '*'.
|
|
|
|
DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
|
|
|
|
ReplaceText(DeclLoc, 1, "*");
|
|
|
|
break;
|
|
|
|
case '(':
|
|
|
|
parenCount++;
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
parenCount--;
|
|
|
|
break;
|
2009-04-30 00:37:50 +08:00
|
|
|
}
|
2008-03-11 04:43:59 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
return;
|
2007-10-19 03:23:00 +08:00
|
|
|
}
|
2007-10-17 06:36:42 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
|
|
|
|
const FunctionProtoType *FTP;
|
|
|
|
const PointerType *PT = QT->getAs<PointerType>();
|
|
|
|
if (PT) {
|
|
|
|
FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
|
|
|
|
} else {
|
|
|
|
const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
|
|
|
|
assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
|
|
|
|
FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
|
|
|
|
}
|
|
|
|
if (FTP) {
|
|
|
|
for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
|
|
|
|
E = FTP->arg_type_end(); I != E; ++I)
|
|
|
|
if (isTopLevelBlockPointerType(*I))
|
|
|
|
return true;
|
|
|
|
}
|
2010-03-12 02:20:03 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
|
|
|
|
const FunctionProtoType *FTP;
|
|
|
|
const PointerType *PT = QT->getAs<PointerType>();
|
|
|
|
if (PT) {
|
|
|
|
FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
|
2008-10-28 01:20:55 +08:00
|
|
|
} else {
|
2011-12-09 02:25:15 +08:00
|
|
|
const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
|
|
|
|
assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
|
|
|
|
FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
if (FTP) {
|
|
|
|
for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
|
|
|
|
E = FTP->arg_type_end(); I != E; ++I) {
|
|
|
|
if ((*I)->isObjCQualifiedIdType())
|
|
|
|
return true;
|
|
|
|
if ((*I)->isObjCObjectPointerType() &&
|
|
|
|
(*I)->getPointeeType()->isObjCQualifiedInterfaceType())
|
|
|
|
return true;
|
2010-02-17 00:21:26 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
return false;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
|
|
|
|
const char *&RParen) {
|
|
|
|
const char *argPtr = strchr(Name, '(');
|
|
|
|
assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
LParen = argPtr; // output the start.
|
|
|
|
argPtr++; // skip past the left paren.
|
|
|
|
unsigned parenCount = 1;
|
|
|
|
|
|
|
|
while (*argPtr && parenCount) {
|
|
|
|
switch (*argPtr) {
|
|
|
|
case '(': parenCount++; break;
|
|
|
|
case ')': parenCount--; break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
if (parenCount) argPtr++;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
|
|
|
|
RParen = argPtr; // output the end
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2008-04-17 22:40:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
|
|
|
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
|
|
|
|
RewriteBlockPointerFunctionArgs(FD);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Handle Variables and Typedefs.
|
|
|
|
SourceLocation DeclLoc = ND->getLocation();
|
|
|
|
QualType DeclT;
|
|
|
|
if (VarDecl *VD = dyn_cast<VarDecl>(ND))
|
|
|
|
DeclT = VD->getType();
|
|
|
|
else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
|
|
|
|
DeclT = TDD->getUnderlyingType();
|
|
|
|
else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
|
|
|
|
DeclT = FD->getType();
|
|
|
|
else
|
|
|
|
llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
|
|
|
|
|
|
|
|
const char *startBuf = SM->getCharacterData(DeclLoc);
|
|
|
|
const char *endBuf = startBuf;
|
|
|
|
// scan backward (from the decl location) for the end of the previous decl.
|
|
|
|
while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
|
|
|
|
startBuf--;
|
|
|
|
SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
|
|
|
|
std::string buf;
|
|
|
|
unsigned OrigLength=0;
|
|
|
|
// *startBuf != '^' if we are dealing with a pointer to function that
|
|
|
|
// may take block argument types (which will be handled below).
|
|
|
|
if (*startBuf == '^') {
|
|
|
|
// Replace the '^' with '*', computing a negative offset.
|
|
|
|
buf = '*';
|
|
|
|
startBuf++;
|
|
|
|
OrigLength++;
|
|
|
|
}
|
|
|
|
while (*startBuf != ')') {
|
|
|
|
buf += *startBuf;
|
|
|
|
startBuf++;
|
|
|
|
OrigLength++;
|
|
|
|
}
|
|
|
|
buf += ')';
|
|
|
|
OrigLength++;
|
|
|
|
|
|
|
|
if (PointerTypeTakesAnyBlockArguments(DeclT) ||
|
|
|
|
PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
|
|
|
|
// Replace the '^' with '*' for arguments.
|
|
|
|
// Replace id<P> with id/*<>*/
|
|
|
|
DeclLoc = ND->getLocation();
|
|
|
|
startBuf = SM->getCharacterData(DeclLoc);
|
|
|
|
const char *argListBegin, *argListEnd;
|
|
|
|
GetExtentOfArgList(startBuf, argListBegin, argListEnd);
|
|
|
|
while (argListBegin < argListEnd) {
|
|
|
|
if (*argListBegin == '^')
|
|
|
|
buf += '*';
|
|
|
|
else if (*argListBegin == '<') {
|
|
|
|
buf += "/*";
|
|
|
|
buf += *argListBegin++;
|
|
|
|
OrigLength++;;
|
|
|
|
while (*argListBegin != '>') {
|
|
|
|
buf += *argListBegin++;
|
|
|
|
OrigLength++;
|
2010-07-29 07:27:30 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
buf += *argListBegin;
|
|
|
|
buf += "*/";
|
2010-07-29 07:27:30 +08:00
|
|
|
}
|
|
|
|
else
|
2011-12-09 02:25:15 +08:00
|
|
|
buf += *argListBegin;
|
|
|
|
argListBegin++;
|
|
|
|
OrigLength++;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
buf += ')';
|
|
|
|
OrigLength++;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
ReplaceText(Start, OrigLength, buf);
|
|
|
|
|
|
|
|
return;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2008-06-10 07:19:58 +08:00
|
|
|
|
2009-12-07 05:14:13 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
|
|
|
|
/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
|
|
|
|
/// struct Block_byref_id_object *src) {
|
|
|
|
/// _Block_object_assign (&_dest->object, _src->object,
|
|
|
|
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
|
|
|
|
/// [|BLOCK_FIELD_IS_WEAK]) // object
|
|
|
|
/// _Block_object_assign(&_dest->object, _src->object,
|
|
|
|
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
|
|
|
|
/// [|BLOCK_FIELD_IS_WEAK]) // block
|
|
|
|
/// }
|
|
|
|
/// And:
|
|
|
|
/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
|
|
|
|
/// _Block_object_dispose(_src->object,
|
|
|
|
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
|
|
|
|
/// [|BLOCK_FIELD_IS_WEAK]) // object
|
|
|
|
/// _Block_object_dispose(_src->object,
|
|
|
|
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
|
|
|
|
/// [|BLOCK_FIELD_IS_WEAK]) // block
|
|
|
|
/// }
|
|
|
|
|
|
|
|
std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
|
|
|
|
int flag) {
|
|
|
|
std::string S;
|
|
|
|
if (CopyDestroyCache.count(flag))
|
|
|
|
return S;
|
|
|
|
CopyDestroyCache.insert(flag);
|
|
|
|
S = "static void __Block_byref_id_object_copy_";
|
|
|
|
S += utostr(flag);
|
|
|
|
S += "(void *dst, void *src) {\n";
|
|
|
|
|
|
|
|
// offset into the object pointer is computed as:
|
|
|
|
// void * + void* + int + int + void* + void *
|
|
|
|
unsigned IntSize =
|
|
|
|
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
|
|
|
|
unsigned VoidPtrSize =
|
|
|
|
static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
|
|
|
|
|
|
|
|
unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
|
|
|
|
S += " _Block_object_assign((char*)dst + ";
|
|
|
|
S += utostr(offset);
|
|
|
|
S += ", *(void * *) ((char*)src + ";
|
|
|
|
S += utostr(offset);
|
|
|
|
S += "), ";
|
|
|
|
S += utostr(flag);
|
|
|
|
S += ");\n}\n";
|
|
|
|
|
|
|
|
S += "static void __Block_byref_id_object_dispose_";
|
|
|
|
S += utostr(flag);
|
|
|
|
S += "(void *src) {\n";
|
|
|
|
S += " _Block_object_dispose(*(void * *) ((char*)src + ";
|
|
|
|
S += utostr(offset);
|
|
|
|
S += "), ";
|
|
|
|
S += utostr(flag);
|
|
|
|
S += ");\n}\n";
|
2009-12-07 05:14:13 +08:00
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
/// RewriteByRefVar - For each __block typex ND variable this routine transforms
|
|
|
|
/// the declaration into:
|
|
|
|
/// struct __Block_byref_ND {
|
|
|
|
/// void *__isa; // NULL for everything except __weak pointers
|
|
|
|
/// struct __Block_byref_ND *__forwarding;
|
|
|
|
/// int32_t __flags;
|
|
|
|
/// int32_t __size;
|
|
|
|
/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
|
|
|
|
/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
|
|
|
|
/// typex ND;
|
|
|
|
/// };
|
|
|
|
///
|
|
|
|
/// It then replaces declaration of ND variable with:
|
|
|
|
/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
|
|
|
|
/// __size=sizeof(struct __Block_byref_ND),
|
|
|
|
/// ND=initializer-if-any};
|
|
|
|
///
|
|
|
|
///
|
|
|
|
void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
|
|
|
|
// Insert declaration for the function in which block literal is
|
|
|
|
// used.
|
|
|
|
if (CurFunctionDeclToDeclareForBlock)
|
|
|
|
RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
|
|
|
|
int flag = 0;
|
|
|
|
int isa = 0;
|
|
|
|
SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
|
|
|
|
if (DeclLoc.isInvalid())
|
|
|
|
// If type location is missing, it is because of missing type (a warning).
|
|
|
|
// Use variable's location which is good for this case.
|
|
|
|
DeclLoc = ND->getLocation();
|
|
|
|
const char *startBuf = SM->getCharacterData(DeclLoc);
|
|
|
|
SourceLocation X = ND->getLocEnd();
|
|
|
|
X = SM->getExpansionLoc(X);
|
|
|
|
const char *endBuf = SM->getCharacterData(X);
|
|
|
|
std::string Name(ND->getNameAsString());
|
|
|
|
std::string ByrefType;
|
|
|
|
RewriteByRefString(ByrefType, Name, ND, true);
|
|
|
|
ByrefType += " {\n";
|
|
|
|
ByrefType += " void *__isa;\n";
|
|
|
|
RewriteByRefString(ByrefType, Name, ND);
|
|
|
|
ByrefType += " *__forwarding;\n";
|
|
|
|
ByrefType += " int __flags;\n";
|
|
|
|
ByrefType += " int __size;\n";
|
|
|
|
// Add void *__Block_byref_id_object_copy;
|
|
|
|
// void *__Block_byref_id_object_dispose; if needed.
|
|
|
|
QualType Ty = ND->getType();
|
|
|
|
bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty);
|
|
|
|
if (HasCopyAndDispose) {
|
|
|
|
ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
|
|
|
|
ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType T = Ty;
|
|
|
|
(void)convertBlockPointerToFunctionPointer(T);
|
|
|
|
T.getAsStringInternal(Name, Context->getPrintingPolicy());
|
|
|
|
|
|
|
|
ByrefType += " " + Name + ";\n";
|
|
|
|
ByrefType += "};\n";
|
|
|
|
// Insert this type in global scope. It is needed by helper function.
|
|
|
|
SourceLocation FunLocStart;
|
|
|
|
if (CurFunctionDef)
|
|
|
|
FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
|
|
|
|
else {
|
|
|
|
assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
|
|
|
|
FunLocStart = CurMethodDef->getLocStart();
|
|
|
|
}
|
|
|
|
InsertText(FunLocStart, ByrefType);
|
|
|
|
if (Ty.isObjCGCWeak()) {
|
|
|
|
flag |= BLOCK_FIELD_IS_WEAK;
|
|
|
|
isa = 1;
|
|
|
|
}
|
2010-03-05 05:35:37 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (HasCopyAndDispose) {
|
|
|
|
flag = BLOCK_BYREF_CALLER;
|
|
|
|
QualType Ty = ND->getType();
|
|
|
|
// FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
|
|
|
|
if (Ty->isBlockPointerType())
|
|
|
|
flag |= BLOCK_FIELD_IS_BLOCK;
|
|
|
|
else
|
|
|
|
flag |= BLOCK_FIELD_IS_OBJECT;
|
|
|
|
std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
|
|
|
|
if (!HF.empty())
|
|
|
|
InsertText(FunLocStart, HF);
|
|
|
|
}
|
|
|
|
|
|
|
|
// struct __Block_byref_ND ND =
|
|
|
|
// {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
|
|
|
|
// initializer-if-any};
|
|
|
|
bool hasInit = (ND->getInit() != 0);
|
|
|
|
unsigned flags = 0;
|
|
|
|
if (HasCopyAndDispose)
|
|
|
|
flags |= BLOCK_HAS_COPY_DISPOSE;
|
|
|
|
Name = ND->getNameAsString();
|
|
|
|
ByrefType.clear();
|
|
|
|
RewriteByRefString(ByrefType, Name, ND);
|
|
|
|
std::string ForwardingCastType("(");
|
|
|
|
ForwardingCastType += ByrefType + " *)";
|
|
|
|
if (!hasInit) {
|
|
|
|
ByrefType += " " + Name + " = {(void*)";
|
|
|
|
ByrefType += utostr(isa);
|
|
|
|
ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
|
|
|
|
ByrefType += utostr(flags);
|
|
|
|
ByrefType += ", ";
|
|
|
|
ByrefType += "sizeof(";
|
|
|
|
RewriteByRefString(ByrefType, Name, ND);
|
|
|
|
ByrefType += ")";
|
|
|
|
if (HasCopyAndDispose) {
|
|
|
|
ByrefType += ", __Block_byref_id_object_copy_";
|
|
|
|
ByrefType += utostr(flag);
|
|
|
|
ByrefType += ", __Block_byref_id_object_dispose_";
|
|
|
|
ByrefType += utostr(flag);
|
|
|
|
}
|
|
|
|
ByrefType += "};\n";
|
|
|
|
unsigned nameSize = Name.size();
|
|
|
|
// for block or function pointer declaration. Name is aleady
|
|
|
|
// part of the declaration.
|
|
|
|
if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
|
|
|
|
nameSize = 1;
|
|
|
|
ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SourceLocation startLoc;
|
|
|
|
Expr *E = ND->getInit();
|
|
|
|
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
|
|
|
|
startLoc = ECE->getLParenLoc();
|
|
|
|
else
|
|
|
|
startLoc = E->getLocStart();
|
|
|
|
startLoc = SM->getExpansionLoc(startLoc);
|
|
|
|
endBuf = SM->getCharacterData(startLoc);
|
|
|
|
ByrefType += " " + Name;
|
|
|
|
ByrefType += " = {(void*)";
|
|
|
|
ByrefType += utostr(isa);
|
|
|
|
ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
|
|
|
|
ByrefType += utostr(flags);
|
|
|
|
ByrefType += ", ";
|
|
|
|
ByrefType += "sizeof(";
|
|
|
|
RewriteByRefString(ByrefType, Name, ND);
|
|
|
|
ByrefType += "), ";
|
|
|
|
if (HasCopyAndDispose) {
|
|
|
|
ByrefType += "__Block_byref_id_object_copy_";
|
|
|
|
ByrefType += utostr(flag);
|
|
|
|
ByrefType += ", __Block_byref_id_object_dispose_";
|
|
|
|
ByrefType += utostr(flag);
|
|
|
|
ByrefType += ", ";
|
|
|
|
}
|
|
|
|
ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
|
|
|
|
|
|
|
|
// Complete the newly synthesized compound expression by inserting a right
|
|
|
|
// curly brace before the end of the declaration.
|
|
|
|
// FIXME: This approach avoids rewriting the initializer expression. It
|
|
|
|
// also assumes there is only one declarator. For example, the following
|
|
|
|
// isn't currently supported by this routine (in general):
|
|
|
|
//
|
|
|
|
// double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
|
|
|
|
//
|
|
|
|
const char *startInitializerBuf = SM->getCharacterData(startLoc);
|
|
|
|
const char *semiBuf = strchr(startInitializerBuf, ';');
|
|
|
|
assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
|
|
|
|
SourceLocation semiLoc =
|
|
|
|
startLoc.getLocWithOffset(semiBuf-startInitializerBuf);
|
|
|
|
|
|
|
|
InsertText(semiLoc, "}");
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
|
|
|
|
// Add initializers for any closure decl refs.
|
|
|
|
GetBlockDeclRefExprs(Exp->getBody());
|
|
|
|
if (BlockDeclRefs.size()) {
|
|
|
|
// Unique all "by copy" declarations.
|
|
|
|
for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
|
|
|
|
if (!BlockDeclRefs[i]->isByRef()) {
|
|
|
|
if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
|
|
|
|
BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
|
|
|
|
BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Unique all "by ref" declarations.
|
|
|
|
for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
|
|
|
|
if (BlockDeclRefs[i]->isByRef()) {
|
|
|
|
if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
|
|
|
|
BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
|
|
|
|
BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Find any imported blocks...they will need special attention.
|
|
|
|
for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
|
|
|
|
if (BlockDeclRefs[i]->isByRef() ||
|
|
|
|
BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
|
|
|
|
BlockDeclRefs[i]->getType()->isBlockPointerType())
|
|
|
|
ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
|
|
|
|
IdentifierInfo *ID = &Context->Idents.get(name);
|
|
|
|
QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
|
|
|
|
return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
|
|
|
|
SourceLocation(), ID, FType, 0, SC_Extern,
|
|
|
|
SC_None, false, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|
|
|
const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) {
|
|
|
|
const BlockDecl *block = Exp->getBlockDecl();
|
|
|
|
Blocks.push_back(Exp);
|
|
|
|
|
|
|
|
CollectBlockDeclRefInfo(Exp);
|
|
|
|
|
|
|
|
// Add inner imported variables now used in current block.
|
|
|
|
int countOfInnerDecls = 0;
|
|
|
|
if (!InnerBlockDeclRefs.empty()) {
|
|
|
|
for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
|
|
|
|
BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i];
|
2010-03-02 07:36:21 +08:00
|
|
|
ValueDecl *VD = Exp->getDecl();
|
|
|
|
if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) {
|
2011-12-09 02:25:15 +08:00
|
|
|
// We need to save the copied-in variables in nested
|
|
|
|
// blocks because it is needed at the end for some of the API generations.
|
|
|
|
// See SynthesizeBlockLiterals routine.
|
|
|
|
InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
|
|
|
|
BlockDeclRefs.push_back(Exp);
|
2010-03-02 07:36:21 +08:00
|
|
|
BlockByCopyDeclsPtrSet.insert(VD);
|
|
|
|
BlockByCopyDecls.push_back(VD);
|
|
|
|
}
|
|
|
|
if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) {
|
2011-12-09 02:25:15 +08:00
|
|
|
InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
|
|
|
|
BlockDeclRefs.push_back(Exp);
|
2010-03-02 07:36:21 +08:00
|
|
|
BlockByRefDeclsPtrSet.insert(VD);
|
|
|
|
BlockByRefDecls.push_back(VD);
|
|
|
|
}
|
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// Find any imported blocks...they will need special attention.
|
|
|
|
for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
|
|
|
|
if (InnerBlockDeclRefs[i]->isByRef() ||
|
|
|
|
InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
|
|
|
|
InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
|
|
|
|
ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
|
|
|
|
}
|
|
|
|
InnerDeclRefsCount.push_back(countOfInnerDecls);
|
|
|
|
|
|
|
|
std::string FuncName;
|
2008-10-28 01:20:55 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (CurFunctionDef)
|
|
|
|
FuncName = CurFunctionDef->getNameAsString();
|
|
|
|
else if (CurMethodDef)
|
|
|
|
BuildUniqueMethodName(FuncName, CurMethodDef);
|
|
|
|
else if (GlobalVarDecl)
|
|
|
|
FuncName = std::string(GlobalVarDecl->getNameAsString());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string BlockNumber = utostr(Blocks.size()-1);
|
2008-10-28 01:20:55 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
|
|
|
|
std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
|
2008-10-28 01:20:55 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Get a pointer to the function type so we can cast appropriately.
|
|
|
|
QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
|
|
|
|
QualType FType = Context->getPointerType(BFT);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
FunctionDecl *FD;
|
|
|
|
Expr *NewRep;
|
2008-10-28 01:20:55 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Simulate a contructor call...
|
|
|
|
FD = SynthBlockInitFunctionDecl(Tag);
|
|
|
|
DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, VK_RValue,
|
|
|
|
SourceLocation());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
SmallVector<Expr*, 4> InitExprs;
|
|
|
|
|
|
|
|
// Initialize the block function.
|
|
|
|
FD = SynthBlockInitFunctionDecl(Func);
|
|
|
|
DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
|
|
|
|
SourceLocation());
|
|
|
|
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
|
|
|
|
CK_BitCast, Arg);
|
|
|
|
InitExprs.push_back(castExpr);
|
|
|
|
|
|
|
|
// Initialize the block descriptor.
|
|
|
|
std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
|
|
|
|
|
|
|
|
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
&Context->Idents.get(DescData.c_str()),
|
|
|
|
Context->VoidPtrTy, 0,
|
|
|
|
SC_Static, SC_None);
|
|
|
|
UnaryOperator *DescRefExpr =
|
|
|
|
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD,
|
|
|
|
Context->VoidPtrTy,
|
|
|
|
VK_LValue,
|
|
|
|
SourceLocation()),
|
|
|
|
UO_AddrOf,
|
|
|
|
Context->getPointerType(Context->VoidPtrTy),
|
|
|
|
VK_RValue, OK_Ordinary,
|
|
|
|
SourceLocation());
|
|
|
|
InitExprs.push_back(DescRefExpr);
|
|
|
|
|
|
|
|
// Add initializers for any closure decl refs.
|
|
|
|
if (BlockDeclRefs.size()) {
|
|
|
|
Expr *Exp;
|
|
|
|
// Output all "by copy" declarations.
|
|
|
|
for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
|
|
|
|
E = BlockByCopyDecls.end(); I != E; ++I) {
|
|
|
|
if (isObjCType((*I)->getType())) {
|
|
|
|
// FIXME: Conform to ABI ([[obj retain] autorelease]).
|
|
|
|
FD = SynthBlockInitFunctionDecl((*I)->getName());
|
|
|
|
Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
|
|
|
|
SourceLocation());
|
|
|
|
if (HasLocalVariableExternalStorage(*I)) {
|
|
|
|
QualType QT = (*I)->getType();
|
|
|
|
QT = Context->getPointerType(QT);
|
|
|
|
Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
|
|
|
|
OK_Ordinary, SourceLocation());
|
|
|
|
}
|
|
|
|
} else if (isTopLevelBlockPointerType((*I)->getType())) {
|
|
|
|
FD = SynthBlockInitFunctionDecl((*I)->getName());
|
|
|
|
Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
|
|
|
|
SourceLocation());
|
|
|
|
Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
|
|
|
|
CK_BitCast, Arg);
|
|
|
|
} else {
|
|
|
|
FD = SynthBlockInitFunctionDecl((*I)->getName());
|
|
|
|
Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
|
|
|
|
SourceLocation());
|
|
|
|
if (HasLocalVariableExternalStorage(*I)) {
|
|
|
|
QualType QT = (*I)->getType();
|
|
|
|
QT = Context->getPointerType(QT);
|
|
|
|
Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue,
|
|
|
|
OK_Ordinary, SourceLocation());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
InitExprs.push_back(Exp);
|
|
|
|
}
|
|
|
|
// Output all "by ref" declarations.
|
|
|
|
for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
|
|
|
|
E = BlockByRefDecls.end(); I != E; ++I) {
|
|
|
|
ValueDecl *ND = (*I);
|
|
|
|
std::string Name(ND->getNameAsString());
|
|
|
|
std::string RecName;
|
|
|
|
RewriteByRefString(RecName, Name, ND, true);
|
|
|
|
IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
|
|
|
|
+ sizeof("struct"));
|
|
|
|
RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
II);
|
|
|
|
assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
|
|
|
|
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
|
|
|
|
|
|
|
|
FD = SynthBlockInitFunctionDecl((*I)->getName());
|
|
|
|
Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue,
|
|
|
|
SourceLocation());
|
|
|
|
bool isNestedCapturedVar = false;
|
|
|
|
if (block)
|
|
|
|
for (BlockDecl::capture_const_iterator ci = block->capture_begin(),
|
|
|
|
ce = block->capture_end(); ci != ce; ++ci) {
|
|
|
|
const VarDecl *variable = ci->getVariable();
|
|
|
|
if (variable == ND && ci->isNested()) {
|
|
|
|
assert (ci->isByRef() &&
|
|
|
|
"SynthBlockInitExpr - captured block variable is not byref");
|
|
|
|
isNestedCapturedVar = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// captured nested byref variable has its address passed. Do not take
|
|
|
|
// its address again.
|
|
|
|
if (!isNestedCapturedVar)
|
|
|
|
Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
|
|
|
|
Context->getPointerType(Exp->getType()),
|
|
|
|
VK_RValue, OK_Ordinary, SourceLocation());
|
|
|
|
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
|
|
|
|
InitExprs.push_back(Exp);
|
|
|
|
}
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ImportedBlockDecls.size()) {
|
|
|
|
// generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
|
|
|
|
int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
|
|
|
|
unsigned IntSize =
|
|
|
|
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
|
|
|
|
Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
|
|
|
|
Context->IntTy, SourceLocation());
|
|
|
|
InitExprs.push_back(FlagExp);
|
2010-03-05 02:54:29 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
|
|
|
|
FType, VK_LValue, SourceLocation());
|
|
|
|
NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
|
|
|
|
Context->getPointerType(NewRep->getType()),
|
|
|
|
VK_RValue, OK_Ordinary, SourceLocation());
|
|
|
|
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
|
|
|
|
NewRep);
|
|
|
|
BlockDeclRefs.clear();
|
|
|
|
BlockByRefDecls.clear();
|
|
|
|
BlockByRefDeclsPtrSet.clear();
|
|
|
|
BlockByCopyDecls.clear();
|
|
|
|
BlockByCopyDeclsPtrSet.clear();
|
|
|
|
ImportedBlockDecls.clear();
|
|
|
|
return NewRep;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
|
|
|
|
if (const ObjCForCollectionStmt * CS =
|
|
|
|
dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
|
|
|
|
return CS->getElement() == DS;
|
|
|
|
return false;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Function Body / Expression rewriting
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-02-11 04:18:25 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
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);
|
|
|
|
}
|
2008-10-28 01:20:55 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Pseudo-object operations and ivar references need special
|
|
|
|
// treatment because we're going to recursively rewrite them.
|
|
|
|
if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
|
|
|
|
if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
|
|
|
|
return RewritePropertyOrImplicitSetter(PseudoOp);
|
|
|
|
} else {
|
|
|
|
return RewritePropertyOrImplicitGetter(PseudoOp);
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
} else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
|
|
|
|
return RewriteObjCIvarRefExpr(IvarRefExpr);
|
2010-03-12 02:20:03 +08:00
|
|
|
}
|
2008-10-28 01:20:55 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
SourceRange OrigStmtRange = S->getSourceRange();
|
|
|
|
|
|
|
|
// Perform a bottom up rewrite of all children.
|
2011-02-13 12:07:26 +08:00
|
|
|
for (Stmt::child_range CI = S->children(); CI; ++CI)
|
2010-02-25 06:48:18 +08:00
|
|
|
if (*CI) {
|
2011-12-09 02:25:15 +08:00
|
|
|
Stmt *childStmt = (*CI);
|
|
|
|
Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
|
|
|
|
if (newStmt) {
|
|
|
|
*CI = newStmt;
|
|
|
|
}
|
2010-02-25 06:48:18 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
|
|
|
|
SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
|
|
|
|
llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
|
|
|
|
InnerContexts.insert(BE->getBlockDecl());
|
|
|
|
ImportedLocalExternalDecls.clear();
|
|
|
|
GetInnerBlockDeclRefExprs(BE->getBody(),
|
|
|
|
InnerBlockDeclRefs, InnerContexts);
|
|
|
|
// Rewrite the block body in place.
|
|
|
|
Stmt *SaveCurrentBody = CurrentBody;
|
|
|
|
CurrentBody = BE->getBody();
|
|
|
|
PropParentMap = 0;
|
|
|
|
// block literal on rhs of a property-dot-sytax assignment
|
|
|
|
// must be replaced by its synthesize ast so getRewrittenText
|
|
|
|
// works as expected. In this case, what actually ends up on RHS
|
|
|
|
// is the blockTranscribed which is the helper function for the
|
|
|
|
// block literal; as in: self.c = ^() {[ace ARR];};
|
|
|
|
bool saveDisableReplaceStmt = DisableReplaceStmt;
|
|
|
|
DisableReplaceStmt = false;
|
|
|
|
RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
|
|
|
|
DisableReplaceStmt = saveDisableReplaceStmt;
|
|
|
|
CurrentBody = SaveCurrentBody;
|
|
|
|
PropParentMap = 0;
|
|
|
|
ImportedLocalExternalDecls.clear();
|
|
|
|
// Now we snarf the rewritten text and stash it away for later use.
|
|
|
|
std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
|
|
|
|
RewrittenBlockExprs[BE] = Str;
|
|
|
|
|
|
|
|
Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
|
|
|
|
|
|
|
|
//blockTranscribed->dump();
|
|
|
|
ReplaceStmt(S, blockTranscribed);
|
|
|
|
return blockTranscribed;
|
2010-05-25 23:56:08 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// Handle specific things.
|
|
|
|
if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
|
|
|
|
return RewriteAtEncode(AtEncode);
|
2010-05-25 23:56:08 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
|
|
|
|
return RewriteAtSelector(AtSelector);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
|
|
|
|
return RewriteObjCStringLiteral(AtString);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
|
|
|
|
#if 0
|
|
|
|
// Before we rewrite it, put the original message expression in a comment.
|
|
|
|
SourceLocation startLoc = MessExpr->getLocStart();
|
|
|
|
SourceLocation endLoc = MessExpr->getLocEnd();
|
2008-10-28 01:20:55 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
const char *startBuf = SM->getCharacterData(startLoc);
|
|
|
|
const char *endBuf = SM->getCharacterData(endLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
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());
|
|
|
|
#endif
|
|
|
|
return RewriteMessageExpr(MessExpr);
|
2008-10-30 18:07:53 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
|
|
|
|
return RewriteObjCTryStmt(StmtTry);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
|
|
|
|
return RewriteObjCSynchronizedStmt(StmtTry);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
|
|
|
|
return RewriteObjCThrowStmt(StmtThrow);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
|
|
|
|
return RewriteObjCProtocolExpr(ProtocolExp);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (ObjCForCollectionStmt *StmtForCollection =
|
|
|
|
dyn_cast<ObjCForCollectionStmt>(S))
|
|
|
|
return RewriteObjCForCollectionStmt(StmtForCollection,
|
|
|
|
OrigStmtRange.getEnd());
|
|
|
|
if (BreakStmt *StmtBreakStmt =
|
|
|
|
dyn_cast<BreakStmt>(S))
|
|
|
|
return RewriteBreakStmt(StmtBreakStmt);
|
|
|
|
if (ContinueStmt *StmtContinueStmt =
|
|
|
|
dyn_cast<ContinueStmt>(S))
|
|
|
|
return RewriteContinueStmt(StmtContinueStmt);
|
2008-10-28 01:20:55 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
|
|
|
|
// and cast exprs.
|
|
|
|
if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
|
|
|
|
// FIXME: What we're doing here is modifying the type-specifier that
|
|
|
|
// precedes the first Decl. In the future the DeclGroup should have
|
|
|
|
// a separate type-specifier that we can rewrite.
|
|
|
|
// NOTE: We need to avoid rewriting the DeclStmt if it is within
|
|
|
|
// the context of an ObjCForCollectionStmt. For example:
|
|
|
|
// NSArray *someArray;
|
|
|
|
// for (id <FooProtocol> index in someArray) ;
|
|
|
|
// This is because RewriteObjCForCollectionStmt() does textual rewriting
|
|
|
|
// and it depends on the original text locations/positions.
|
|
|
|
if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
|
|
|
|
RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Blocks rewrite rules.
|
|
|
|
for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
|
|
|
|
DI != DE; ++DI) {
|
|
|
|
Decl *SD = *DI;
|
|
|
|
if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
|
|
|
|
if (isTopLevelBlockPointerType(ND->getType()))
|
|
|
|
RewriteBlockPointerDecl(ND);
|
|
|
|
else if (ND->getType()->isFunctionPointerType())
|
|
|
|
CheckFunctionPointerDecl(ND->getType(), ND);
|
|
|
|
if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
|
|
|
|
if (VD->hasAttr<BlocksAttr>()) {
|
|
|
|
static unsigned uniqueByrefDeclCount = 0;
|
|
|
|
assert(!BlockByRefDeclNo.count(ND) &&
|
|
|
|
"RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
|
|
|
|
BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
|
|
|
|
RewriteByRefVar(VD);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
RewriteTypeOfDecl(VD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
|
|
|
|
if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
|
|
|
|
RewriteBlockPointerDecl(TD);
|
|
|
|
else if (TD->getUnderlyingType()->isFunctionPointerType())
|
|
|
|
CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
|
|
|
|
}
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
|
|
|
|
RewriteObjCQualifiedInterfaceTypes(CE);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
// Handle blocks rewriting.
|
|
|
|
if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
|
|
|
|
if (BDRE->isByRef())
|
|
|
|
return RewriteBlockDeclRefExpr(BDRE);
|
|
|
|
}
|
|
|
|
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
|
|
|
|
ValueDecl *VD = DRE->getDecl();
|
|
|
|
if (VD->hasAttr<BlocksAttr>())
|
|
|
|
return RewriteBlockDeclRefExpr(DRE);
|
|
|
|
if (HasLocalVariableExternalStorage(VD))
|
|
|
|
return RewriteLocalVariableExternalStorage(DRE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
|
|
|
|
if (CE->getCallee()->getType()->isBlockPointerType()) {
|
|
|
|
Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
|
|
|
|
ReplaceStmt(S, BlockCall);
|
|
|
|
return BlockCall;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
|
|
|
|
RewriteCastExpr(CE);
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
#if 0
|
|
|
|
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
|
|
|
|
CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
|
|
|
|
ICE->getSubExpr(),
|
|
|
|
SourceLocation());
|
|
|
|
// Get the new text.
|
|
|
|
std::string SStr;
|
|
|
|
llvm::raw_string_ostream Buf(SStr);
|
|
|
|
Replacement->printPretty(Buf, *Context);
|
|
|
|
const std::string &Str = Buf.str();
|
|
|
|
|
|
|
|
printf("CAST = %s\n", &Str[0]);
|
|
|
|
InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
|
|
|
|
delete S;
|
|
|
|
return Replacement;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
#endif
|
|
|
|
// Return this stmt unmodified.
|
|
|
|
return S;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
|
|
|
|
for (RecordDecl::field_iterator i = RD->field_begin(),
|
|
|
|
e = RD->field_end(); i != e; ++i) {
|
|
|
|
FieldDecl *FD = *i;
|
|
|
|
if (isTopLevelBlockPointerType(FD->getType()))
|
|
|
|
RewriteBlockPointerDecl(FD);
|
|
|
|
if (FD->getType()->isObjCQualifiedIdType() ||
|
|
|
|
FD->getType()->isObjCQualifiedInterfaceType())
|
|
|
|
RewriteObjCQualifiedInterfaceTypes(FD);
|
2010-11-04 07:29:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
/// HandleDeclInMainFile - This is called for each top-level decl defined in the
|
|
|
|
/// main file of the input.
|
|
|
|
void RewriteObjC::HandleDeclInMainFile(Decl *D) {
|
|
|
|
switch (D->getKind()) {
|
|
|
|
case Decl::Function: {
|
|
|
|
FunctionDecl *FD = cast<FunctionDecl>(D);
|
|
|
|
if (FD->isOverloadedOperator())
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Since function prototypes don't have ParmDecl's, we check the function
|
|
|
|
// prototype. This enables us to rewrite function declarations and
|
|
|
|
// definitions using the same code.
|
|
|
|
RewriteBlocksInFunctionProtoType(FD->getType(), FD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// FIXME: If this should support Obj-C++, support CXXTryStmt
|
|
|
|
if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
|
|
|
|
CurFunctionDef = FD;
|
|
|
|
CurFunctionDeclToDeclareForBlock = FD;
|
|
|
|
CurrentBody = Body;
|
|
|
|
Body =
|
|
|
|
cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
|
|
|
|
FD->setBody(Body);
|
|
|
|
CurrentBody = 0;
|
|
|
|
if (PropParentMap) {
|
|
|
|
delete PropParentMap;
|
|
|
|
PropParentMap = 0;
|
|
|
|
}
|
|
|
|
// This synthesizes and inserts the block "impl" struct, invoke function,
|
|
|
|
// and any copy/dispose helper functions.
|
|
|
|
InsertBlockLiteralsWithinFunction(FD);
|
|
|
|
CurFunctionDef = 0;
|
|
|
|
CurFunctionDeclToDeclareForBlock = 0;
|
|
|
|
}
|
|
|
|
break;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
case Decl::ObjCMethod: {
|
|
|
|
ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
|
|
|
|
if (CompoundStmt *Body = MD->getCompoundBody()) {
|
|
|
|
CurMethodDef = MD;
|
|
|
|
CurrentBody = Body;
|
|
|
|
Body =
|
|
|
|
cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
|
|
|
|
MD->setBody(Body);
|
|
|
|
CurrentBody = 0;
|
|
|
|
if (PropParentMap) {
|
|
|
|
delete PropParentMap;
|
|
|
|
PropParentMap = 0;
|
|
|
|
}
|
|
|
|
InsertBlockLiteralsWithinMethod(MD);
|
|
|
|
CurMethodDef = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Decl::ObjCImplementation: {
|
|
|
|
ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
|
|
|
|
ClassImplementation.push_back(CI);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Decl::ObjCCategoryImpl: {
|
|
|
|
ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
|
|
|
|
CategoryImplementation.push_back(CI);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Decl::Var: {
|
|
|
|
VarDecl *VD = cast<VarDecl>(D);
|
|
|
|
RewriteObjCQualifiedInterfaceTypes(VD);
|
|
|
|
if (isTopLevelBlockPointerType(VD->getType()))
|
|
|
|
RewriteBlockPointerDecl(VD);
|
|
|
|
else if (VD->getType()->isFunctionPointerType()) {
|
|
|
|
CheckFunctionPointerDecl(VD->getType(), VD);
|
|
|
|
if (VD->getInit()) {
|
|
|
|
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
|
|
|
|
RewriteCastExpr(CE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (VD->getType()->isRecordType()) {
|
|
|
|
RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
|
|
|
|
if (RD->isCompleteDefinition())
|
|
|
|
RewriteRecordBody(RD);
|
|
|
|
}
|
|
|
|
if (VD->getInit()) {
|
|
|
|
GlobalVarDecl = VD;
|
|
|
|
CurrentBody = VD->getInit();
|
|
|
|
RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
|
|
|
|
CurrentBody = 0;
|
|
|
|
if (PropParentMap) {
|
|
|
|
delete PropParentMap;
|
|
|
|
PropParentMap = 0;
|
|
|
|
}
|
|
|
|
SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
|
|
|
|
GlobalVarDecl = 0;
|
|
|
|
|
|
|
|
// This is needed for blocks.
|
|
|
|
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
|
|
|
|
RewriteCastExpr(CE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Decl::TypeAlias:
|
|
|
|
case Decl::Typedef: {
|
|
|
|
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
|
|
|
|
if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
|
|
|
|
RewriteBlockPointerDecl(TD);
|
|
|
|
else if (TD->getUnderlyingType()->isFunctionPointerType())
|
|
|
|
CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Decl::CXXRecord:
|
|
|
|
case Decl::Record: {
|
|
|
|
RecordDecl *RD = cast<RecordDecl>(D);
|
|
|
|
if (RD->isCompleteDefinition())
|
|
|
|
RewriteRecordBody(RD);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// Nothing yet.
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
|
|
|
|
if (Diags.hasErrorOccurred())
|
2008-10-28 01:20:55 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
RewriteInclude();
|
|
|
|
|
|
|
|
// Here's a great place to add any extra declarations that may be needed.
|
|
|
|
// Write out meta data for each @protocol(<expr>).
|
|
|
|
for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
|
|
|
|
E = ProtocolExprDecls.end(); I != E; ++I)
|
|
|
|
RewriteObjCProtocolMetaData(*I, "", "", Preamble);
|
|
|
|
|
|
|
|
InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
|
|
|
|
if (ClassImplementation.size() || CategoryImplementation.size())
|
|
|
|
RewriteImplementations();
|
|
|
|
|
|
|
|
// 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 {
|
|
|
|
llvm::errs() << "No changes\n";
|
2010-11-04 07:29:24 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
if (ClassImplementation.size() || CategoryImplementation.size() ||
|
|
|
|
ProtocolExprDecls.size()) {
|
|
|
|
// Rewrite Objective-c meta data*
|
|
|
|
std::string ResultStr;
|
|
|
|
RewriteMetaDataIntoBuffer(ResultStr);
|
|
|
|
// Emit metadata.
|
|
|
|
*OutFile << ResultStr;
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
OutFile->flush();
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjCFragileABI::Initialize(ASTContext &context) {
|
|
|
|
InitializeCommon(context);
|
2010-01-06 02:04:40 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// 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 += "struct __rw_objc_super { struct objc_object *object; ";
|
|
|
|
Preamble += "struct objc_object *superClass; ";
|
|
|
|
if (LangOpts.MicrosoftExt) {
|
|
|
|
// Add a constructor for creating temporary objects.
|
|
|
|
Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
|
|
|
|
": ";
|
|
|
|
Preamble += "object(o), superClass(s) {} ";
|
|
|
|
}
|
|
|
|
Preamble += "};\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.MicrosoftExt) {
|
|
|
|
Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
|
|
|
|
Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
|
|
|
|
} else
|
|
|
|
Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
|
|
|
|
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
|
|
|
|
Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
|
|
|
|
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
|
|
|
|
Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
|
|
|
|
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
|
|
|
|
Preamble += "(const char *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
|
|
|
|
Preamble += "(struct objc_class *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
|
|
|
|
Preamble += "(const char *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
|
|
|
|
Preamble += "(struct objc_class *, struct objc_object *);\n";
|
|
|
|
// @synchronized hooks.
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\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 += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\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 += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
|
|
|
|
Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
|
|
|
|
Preamble += "#else\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
|
|
|
|
Preamble += "#endif\n";
|
|
|
|
Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
|
|
|
|
Preamble += "#endif\n";
|
|
|
|
// Blocks preamble.
|
|
|
|
Preamble += "#ifndef BLOCK_IMPL\n";
|
|
|
|
Preamble += "#define BLOCK_IMPL\n";
|
|
|
|
Preamble += "struct __block_impl {\n";
|
|
|
|
Preamble += " void *isa;\n";
|
|
|
|
Preamble += " int Flags;\n";
|
|
|
|
Preamble += " int Reserved;\n";
|
|
|
|
Preamble += " void *FuncPtr;\n";
|
|
|
|
Preamble += "};\n";
|
|
|
|
Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
|
|
|
|
Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
|
|
|
|
Preamble += "extern \"C\" __declspec(dllexport) "
|
|
|
|
"void _Block_object_assign(void *, const void *, const int);\n";
|
|
|
|
Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
|
|
|
|
Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
|
|
|
|
Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
|
|
|
|
Preamble += "#else\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
|
|
|
|
Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
|
|
|
|
Preamble += "#endif\n";
|
|
|
|
Preamble += "#endif\n";
|
|
|
|
if (LangOpts.MicrosoftExt) {
|
|
|
|
Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
|
|
|
|
Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
|
|
|
|
Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.
|
|
|
|
Preamble += "#define __attribute__(X)\n";
|
|
|
|
Preamble += "#endif\n";
|
|
|
|
Preamble += "#define __weak\n";
|
2010-01-05 03:50:07 +08:00
|
|
|
}
|
2010-01-17 03:36:43 +08:00
|
|
|
else {
|
2011-12-09 02:25:15 +08:00
|
|
|
Preamble += "#define __block\n";
|
|
|
|
Preamble += "#define __weak\n";
|
2010-01-17 03:36:43 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
|
|
|
|
// as this avoids warning in any 64bit/32bit compilation model.
|
|
|
|
Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
/// RewriteIvarOffsetComputation - This rutine synthesizes computation of
|
|
|
|
/// ivar offset.
|
|
|
|
void RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
|
|
|
|
std::string &Result) {
|
|
|
|
if (ivar->isBitField()) {
|
|
|
|
// FIXME: The hack below doesn't work for bitfields. For now, we simply
|
|
|
|
// place all bitfields at offset 0.
|
|
|
|
Result += "0";
|
|
|
|
} else {
|
|
|
|
Result += "__OFFSETOFIVAR__(struct ";
|
|
|
|
Result += ivar->getContainingInterface()->getNameAsString();
|
|
|
|
if (LangOpts.MicrosoftExt)
|
|
|
|
Result += "_IMPL";
|
|
|
|
Result += ", ";
|
|
|
|
Result += ivar->getNameAsString();
|
|
|
|
Result += ")";
|
2010-01-06 03:21:35 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
|
|
|
|
void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
|
|
|
|
ObjCProtocolDecl *PDecl, StringRef prefix,
|
|
|
|
StringRef ClassName, std::string &Result) {
|
|
|
|
static bool objc_protocol_methods = false;
|
2010-01-06 03:21:35 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Output struct protocol_methods holder of method selector and type.
|
2012-01-02 03:29:29 +08:00
|
|
|
if (!objc_protocol_methods && PDecl->hasDefinition()) {
|
2011-12-09 02:25:15 +08:00
|
|
|
/* struct protocol_methods {
|
|
|
|
SEL _cmd;
|
|
|
|
char *method_types;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
Result += "\nstruct _protocol_methods {\n";
|
|
|
|
Result += "\tstruct objc_selector *_cmd;\n";
|
|
|
|
Result += "\tchar *method_types;\n";
|
|
|
|
Result += "};\n";
|
|
|
|
|
|
|
|
objc_protocol_methods = true;
|
2010-01-05 09:16:51 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// Do not synthesize the protocol more than once.
|
2012-01-02 02:09:12 +08:00
|
|
|
if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
|
2011-12-09 02:25:15 +08:00
|
|
|
return;
|
2009-12-23 10:07:37 +08:00
|
|
|
|
2012-01-02 10:00:30 +08:00
|
|
|
if (ObjCProtocolDecl *Def = PDecl->getDefinition())
|
|
|
|
PDecl = Def;
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
|
|
|
|
unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
|
|
|
|
PDecl->instmeth_end());
|
|
|
|
/* struct _objc_protocol_method_list {
|
|
|
|
int protocol_method_count;
|
|
|
|
struct protocol_methods protocols[];
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
Result += "\nstatic struct {\n";
|
|
|
|
Result += "\tint protocol_method_count;\n";
|
|
|
|
Result += "\tstruct _protocol_methods protocol_methods[";
|
|
|
|
Result += utostr(NumMethods);
|
|
|
|
Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
|
|
|
|
Result += PDecl->getNameAsString();
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
|
|
|
|
"{\n\t" + utostr(NumMethods) + "\n";
|
|
|
|
|
|
|
|
// Output instance methods declared in this protocol.
|
|
|
|
for (ObjCProtocolDecl::instmeth_iterator
|
|
|
|
I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (I == PDecl->instmeth_begin())
|
|
|
|
Result += "\t ,{{(struct objc_selector *)\"";
|
|
|
|
else
|
|
|
|
Result += "\t ,{(struct objc_selector *)\"";
|
|
|
|
Result += (*I)->getSelector().getAsString();
|
|
|
|
std::string MethodTypeString;
|
|
|
|
Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
|
|
|
|
Result += "\", \"";
|
|
|
|
Result += MethodTypeString;
|
|
|
|
Result += "\"}\n";
|
2010-01-05 09:16:51 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
Result += "\t }\n};\n";
|
2009-12-23 10:07:37 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
// Output class methods declared in this protocol.
|
|
|
|
unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
|
|
|
|
PDecl->classmeth_end());
|
|
|
|
if (NumMethods > 0) {
|
|
|
|
/* struct _objc_protocol_method_list {
|
|
|
|
int protocol_method_count;
|
|
|
|
struct protocol_methods protocols[];
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
Result += "\nstatic struct {\n";
|
|
|
|
Result += "\tint protocol_method_count;\n";
|
|
|
|
Result += "\tstruct _protocol_methods protocol_methods[";
|
|
|
|
Result += utostr(NumMethods);
|
|
|
|
Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
|
|
|
|
Result += PDecl->getNameAsString();
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
|
|
|
|
"{\n\t";
|
|
|
|
Result += utostr(NumMethods);
|
|
|
|
Result += "\n";
|
|
|
|
|
|
|
|
// Output instance methods declared in this protocol.
|
|
|
|
for (ObjCProtocolDecl::classmeth_iterator
|
|
|
|
I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (I == PDecl->classmeth_begin())
|
|
|
|
Result += "\t ,{{(struct objc_selector *)\"";
|
|
|
|
else
|
|
|
|
Result += "\t ,{(struct objc_selector *)\"";
|
|
|
|
Result += (*I)->getSelector().getAsString();
|
|
|
|
std::string MethodTypeString;
|
|
|
|
Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
|
|
|
|
Result += "\", \"";
|
|
|
|
Result += MethodTypeString;
|
|
|
|
Result += "\"}\n";
|
2010-01-05 09:16:51 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
Result += "\t }\n};\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output:
|
|
|
|
/* struct _objc_protocol {
|
|
|
|
// Objective-C 1.0 extensions
|
|
|
|
struct _objc_protocol_extension *isa;
|
|
|
|
char *protocol_name;
|
|
|
|
struct _objc_protocol **protocol_list;
|
|
|
|
struct _objc_protocol_method_list *instance_methods;
|
|
|
|
struct _objc_protocol_method_list *class_methods;
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
static bool objc_protocol = false;
|
|
|
|
if (!objc_protocol) {
|
|
|
|
Result += "\nstruct _objc_protocol {\n";
|
|
|
|
Result += "\tstruct _objc_protocol_extension *isa;\n";
|
|
|
|
Result += "\tchar *protocol_name;\n";
|
|
|
|
Result += "\tstruct _objc_protocol **protocol_list;\n";
|
|
|
|
Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
|
|
|
|
Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
|
|
|
|
Result += "};\n";
|
2009-12-24 01:24:33 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
objc_protocol = true;
|
2009-12-23 10:07:37 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
|
|
|
|
Result += PDecl->getNameAsString();
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
|
|
|
|
"{\n\t0, \"";
|
|
|
|
Result += PDecl->getNameAsString();
|
|
|
|
Result += "\", 0, ";
|
|
|
|
if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
|
|
|
|
Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
|
|
|
|
Result += PDecl->getNameAsString();
|
|
|
|
Result += ", ";
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
else
|
|
|
|
Result += "0, ";
|
|
|
|
if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {
|
|
|
|
Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
|
|
|
|
Result += PDecl->getNameAsString();
|
|
|
|
Result += "\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Result += "0\n";
|
|
|
|
Result += "};\n";
|
|
|
|
|
|
|
|
// Mark this protocol as having been generated.
|
2012-01-02 02:09:12 +08:00
|
|
|
if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()))
|
2011-12-09 02:25:15 +08:00
|
|
|
llvm_unreachable("protocol already synthesized");
|
|
|
|
|
2008-10-28 01:20:55 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
|
|
|
|
const ObjCList<ObjCProtocolDecl> &Protocols,
|
|
|
|
StringRef prefix, StringRef ClassName,
|
|
|
|
std::string &Result) {
|
|
|
|
if (Protocols.empty()) return;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i != Protocols.size(); i++)
|
|
|
|
RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
|
|
|
|
|
|
|
|
// Output the top lovel protocol meta-data for the class.
|
|
|
|
/* struct _objc_protocol_list {
|
|
|
|
struct _objc_protocol_list *next;
|
|
|
|
int protocol_count;
|
|
|
|
struct _objc_protocol *class_protocols[];
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
Result += "\nstatic struct {\n";
|
|
|
|
Result += "\tstruct _objc_protocol_list *next;\n";
|
|
|
|
Result += "\tint protocol_count;\n";
|
|
|
|
Result += "\tstruct _objc_protocol *class_protocols[";
|
|
|
|
Result += utostr(Protocols.size());
|
|
|
|
Result += "];\n} _OBJC_";
|
|
|
|
Result += prefix;
|
|
|
|
Result += "_PROTOCOLS_";
|
|
|
|
Result += ClassName;
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
|
|
|
|
"{\n\t0, ";
|
|
|
|
Result += utostr(Protocols.size());
|
|
|
|
Result += "\n";
|
|
|
|
|
|
|
|
Result += "\t,{&_OBJC_PROTOCOL_";
|
|
|
|
Result += Protocols[0]->getNameAsString();
|
|
|
|
Result += " \n";
|
|
|
|
|
|
|
|
for (unsigned i = 1; i != Protocols.size(); i++) {
|
|
|
|
Result += "\t ,&_OBJC_PROTOCOL_";
|
|
|
|
Result += Protocols[i]->getNameAsString();
|
|
|
|
Result += "\n";
|
|
|
|
}
|
|
|
|
Result += "\t }\n};\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
|
|
|
|
std::string &Result) {
|
|
|
|
ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
|
2010-02-25 06:48:18 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Explicitly declared @interface's are already synthesized.
|
|
|
|
if (CDecl->isImplicitInterfaceDecl()) {
|
2011-12-16 04:29:51 +08:00
|
|
|
// FIXME: Implementation of a class with no @interface (legacy) does not
|
2011-12-09 02:25:15 +08:00
|
|
|
// produce correct synthesis as yet.
|
|
|
|
RewriteObjCInternalStruct(CDecl, Result);
|
2010-02-25 06:48:18 +08:00
|
|
|
}
|
2009-12-07 05:14:13 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// Build _objc_ivar_list metadata for classes ivars if needed
|
|
|
|
unsigned NumIvars = !IDecl->ivar_empty()
|
|
|
|
? IDecl->ivar_size()
|
|
|
|
: (CDecl ? CDecl->ivar_size() : 0);
|
|
|
|
if (NumIvars > 0) {
|
|
|
|
static bool objc_ivar = false;
|
|
|
|
if (!objc_ivar) {
|
|
|
|
/* struct _objc_ivar {
|
|
|
|
char *ivar_name;
|
|
|
|
char *ivar_type;
|
|
|
|
int ivar_offset;
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
Result += "\nstruct _objc_ivar {\n";
|
|
|
|
Result += "\tchar *ivar_name;\n";
|
|
|
|
Result += "\tchar *ivar_type;\n";
|
|
|
|
Result += "\tint ivar_offset;\n";
|
|
|
|
Result += "};\n";
|
2010-02-04 08:07:58 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
objc_ivar = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* struct {
|
|
|
|
int ivar_count;
|
|
|
|
struct _objc_ivar ivar_list[nIvars];
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
Result += "\nstatic struct {\n";
|
|
|
|
Result += "\tint ivar_count;\n";
|
|
|
|
Result += "\tstruct _objc_ivar ivar_list[";
|
|
|
|
Result += utostr(NumIvars);
|
|
|
|
Result += "];\n} _OBJC_INSTANCE_VARIABLES_";
|
|
|
|
Result += IDecl->getNameAsString();
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
|
|
|
|
"{\n\t";
|
|
|
|
Result += utostr(NumIvars);
|
|
|
|
Result += "\n";
|
|
|
|
|
|
|
|
ObjCInterfaceDecl::ivar_iterator IVI, IVE;
|
|
|
|
SmallVector<ObjCIvarDecl *, 8> IVars;
|
|
|
|
if (!IDecl->ivar_empty()) {
|
|
|
|
for (ObjCInterfaceDecl::ivar_iterator
|
|
|
|
IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end();
|
|
|
|
IV != IVEnd; ++IV)
|
|
|
|
IVars.push_back(*IV);
|
|
|
|
IVI = IDecl->ivar_begin();
|
|
|
|
IVE = IDecl->ivar_end();
|
|
|
|
} else {
|
|
|
|
IVI = CDecl->ivar_begin();
|
|
|
|
IVE = CDecl->ivar_end();
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
Result += "\t,{{\"";
|
|
|
|
Result += (*IVI)->getNameAsString();
|
|
|
|
Result += "\", \"";
|
|
|
|
std::string TmpString, StrEncoding;
|
|
|
|
Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
|
|
|
|
QuoteDoublequotes(TmpString, StrEncoding);
|
|
|
|
Result += StrEncoding;
|
|
|
|
Result += "\", ";
|
|
|
|
RewriteIvarOffsetComputation(*IVI, Result);
|
|
|
|
Result += "}\n";
|
|
|
|
for (++IVI; IVI != IVE; ++IVI) {
|
|
|
|
Result += "\t ,{\"";
|
|
|
|
Result += (*IVI)->getNameAsString();
|
|
|
|
Result += "\", \"";
|
|
|
|
std::string TmpString, StrEncoding;
|
|
|
|
Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI);
|
|
|
|
QuoteDoublequotes(TmpString, StrEncoding);
|
|
|
|
Result += StrEncoding;
|
|
|
|
Result += "\", ";
|
|
|
|
RewriteIvarOffsetComputation((*IVI), Result);
|
|
|
|
Result += "}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
Result += "\t }\n};\n";
|
2009-12-07 05:14:13 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
// Build _objc_method_list for class's instance methods if needed
|
|
|
|
SmallVector<ObjCMethodDecl *, 32>
|
|
|
|
InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
|
|
|
|
|
|
|
|
// If any of our property implementations have associated getters or
|
|
|
|
// setters, produce metadata for them as well.
|
|
|
|
for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
|
|
|
|
PropEnd = IDecl->propimpl_end();
|
|
|
|
Prop != PropEnd; ++Prop) {
|
|
|
|
if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
|
|
|
|
continue;
|
|
|
|
if (!(*Prop)->getPropertyIvarDecl())
|
|
|
|
continue;
|
|
|
|
ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
|
|
|
|
if (!PD)
|
|
|
|
continue;
|
|
|
|
if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
|
|
|
|
if (!Getter->isDefined())
|
|
|
|
InstanceMethods.push_back(Getter);
|
|
|
|
if (PD->isReadOnly())
|
|
|
|
continue;
|
|
|
|
if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
|
|
|
|
if (!Setter->isDefined())
|
|
|
|
InstanceMethods.push_back(Setter);
|
|
|
|
}
|
|
|
|
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
|
|
|
|
true, "", IDecl->getName(), Result);
|
|
|
|
|
|
|
|
// Build _objc_method_list for class's class methods if needed
|
|
|
|
RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
|
|
|
|
false, "", IDecl->getName(), Result);
|
|
|
|
|
|
|
|
// Protocols referenced in class declaration?
|
|
|
|
RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
|
|
|
|
"CLASS", CDecl->getName(), Result);
|
|
|
|
|
|
|
|
// Declaration of class/meta-class metadata
|
|
|
|
/* struct _objc_class {
|
|
|
|
struct _objc_class *isa; // or const char *root_class_name when metadata
|
|
|
|
const char *super_class_name;
|
|
|
|
char *name;
|
|
|
|
long version;
|
|
|
|
long info;
|
|
|
|
long instance_size;
|
|
|
|
struct _objc_ivar_list *ivars;
|
|
|
|
struct _objc_method_list *methods;
|
|
|
|
struct objc_cache *cache;
|
|
|
|
struct objc_protocol_list *protocols;
|
|
|
|
const char *ivar_layout;
|
|
|
|
struct _objc_class_ext *ext;
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
static bool objc_class = false;
|
|
|
|
if (!objc_class) {
|
|
|
|
Result += "\nstruct _objc_class {\n";
|
|
|
|
Result += "\tstruct _objc_class *isa;\n";
|
|
|
|
Result += "\tconst char *super_class_name;\n";
|
|
|
|
Result += "\tchar *name;\n";
|
|
|
|
Result += "\tlong version;\n";
|
|
|
|
Result += "\tlong info;\n";
|
|
|
|
Result += "\tlong instance_size;\n";
|
|
|
|
Result += "\tstruct _objc_ivar_list *ivars;\n";
|
|
|
|
Result += "\tstruct _objc_method_list *methods;\n";
|
|
|
|
Result += "\tstruct objc_cache *cache;\n";
|
|
|
|
Result += "\tstruct _objc_protocol_list *protocols;\n";
|
|
|
|
Result += "\tconst char *ivar_layout;\n";
|
|
|
|
Result += "\tstruct _objc_class_ext *ext;\n";
|
|
|
|
Result += "};\n";
|
|
|
|
objc_class = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Meta-class metadata generation.
|
|
|
|
ObjCInterfaceDecl *RootClass = 0;
|
|
|
|
ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
|
|
|
|
while (SuperClass) {
|
|
|
|
RootClass = SuperClass;
|
|
|
|
SuperClass = SuperClass->getSuperClass();
|
|
|
|
}
|
|
|
|
SuperClass = CDecl->getSuperClass();
|
|
|
|
|
|
|
|
Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
|
|
|
|
"{\n\t(struct _objc_class *)\"";
|
|
|
|
Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());
|
|
|
|
Result += "\"";
|
|
|
|
|
|
|
|
if (SuperClass) {
|
|
|
|
Result += ", \"";
|
|
|
|
Result += SuperClass->getNameAsString();
|
|
|
|
Result += "\", \"";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += "\"";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Result += ", 0, \"";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += "\"";
|
|
|
|
}
|
|
|
|
// Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.
|
|
|
|
// 'info' field is initialized to CLS_META(2) for metaclass
|
|
|
|
Result += ", 0,2, sizeof(struct _objc_class), 0";
|
|
|
|
if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
|
|
|
|
Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
|
|
|
|
Result += IDecl->getNameAsString();
|
|
|
|
Result += "\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Result += ", 0\n";
|
|
|
|
if (CDecl->protocol_begin() != CDecl->protocol_end()) {
|
|
|
|
Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += ",0,0\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Result += "\t,0,0,0,0\n";
|
|
|
|
Result += "};\n";
|
|
|
|
|
|
|
|
// class metadata generation.
|
|
|
|
Result += "\nstatic struct _objc_class _OBJC_CLASS_";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "
|
|
|
|
"{\n\t&_OBJC_METACLASS_";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
if (SuperClass) {
|
|
|
|
Result += ", \"";
|
|
|
|
Result += SuperClass->getNameAsString();
|
|
|
|
Result += "\", \"";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += "\"";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Result += ", 0, \"";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += "\"";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
// 'info' field is initialized to CLS_CLASS(1) for class
|
|
|
|
Result += ", 0,1";
|
|
|
|
if (!ObjCSynthesizedStructs.count(CDecl))
|
|
|
|
Result += ",0";
|
|
|
|
else {
|
|
|
|
// class has size. Must synthesize its size.
|
|
|
|
Result += ",sizeof(struct ";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
if (LangOpts.MicrosoftExt)
|
|
|
|
Result += "_IMPL";
|
|
|
|
Result += ")";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
if (NumIvars > 0) {
|
|
|
|
Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += "\n\t";
|
2011-11-06 17:01:30 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
else
|
|
|
|
Result += ",0";
|
|
|
|
if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
|
|
|
|
Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += ", 0\n\t";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
else
|
|
|
|
Result += ",0,0";
|
|
|
|
if (CDecl->protocol_begin() != CDecl->protocol_end()) {
|
|
|
|
Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
|
|
|
|
Result += CDecl->getNameAsString();
|
|
|
|
Result += ", 0,0\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
else
|
|
|
|
Result += ",0,0,0\n";
|
|
|
|
Result += "};\n";
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
|
|
|
|
int ClsDefCount = ClassImplementation.size();
|
|
|
|
int CatDefCount = CategoryImplementation.size();
|
|
|
|
|
|
|
|
// For each implemented class, write out all its meta data.
|
|
|
|
for (int i = 0; i < ClsDefCount; i++)
|
|
|
|
RewriteObjCClassMetaData(ClassImplementation[i], Result);
|
|
|
|
|
|
|
|
// For each implemented category, write out all its meta data.
|
|
|
|
for (int i = 0; i < CatDefCount; i++)
|
|
|
|
RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
|
|
|
|
|
|
|
|
// Write objc_symtab metadata
|
|
|
|
/*
|
|
|
|
struct _objc_symtab
|
|
|
|
{
|
|
|
|
long sel_ref_cnt;
|
|
|
|
SEL *refs;
|
|
|
|
short cls_def_cnt;
|
|
|
|
short cat_def_cnt;
|
|
|
|
void *defs[cls_def_cnt + cat_def_cnt];
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
|
|
|
|
Result += "\nstruct _objc_symtab {\n";
|
|
|
|
Result += "\tlong sel_ref_cnt;\n";
|
|
|
|
Result += "\tSEL *refs;\n";
|
|
|
|
Result += "\tshort cls_def_cnt;\n";
|
|
|
|
Result += "\tshort cat_def_cnt;\n";
|
|
|
|
Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
|
|
|
|
Result += "};\n\n";
|
|
|
|
|
|
|
|
Result += "static struct _objc_symtab "
|
|
|
|
"_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
|
|
|
|
Result += "\t0, 0, " + utostr(ClsDefCount)
|
|
|
|
+ ", " + utostr(CatDefCount) + "\n";
|
|
|
|
for (int i = 0; i < ClsDefCount; i++) {
|
|
|
|
Result += "\t,&_OBJC_CLASS_";
|
|
|
|
Result += ClassImplementation[i]->getNameAsString();
|
|
|
|
Result += "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < CatDefCount; i++) {
|
|
|
|
Result += "\t,&_OBJC_CATEGORY_";
|
|
|
|
Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
|
|
|
|
Result += "_";
|
|
|
|
Result += CategoryImplementation[i]->getNameAsString();
|
|
|
|
Result += "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
Result += "};\n\n";
|
|
|
|
|
|
|
|
// Write objc_module metadata
|
|
|
|
|
|
|
|
/*
|
|
|
|
struct _objc_module {
|
|
|
|
long version;
|
|
|
|
long size;
|
|
|
|
const char *name;
|
|
|
|
struct _objc_symtab *symtab;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
Result += "\nstruct _objc_module {\n";
|
|
|
|
Result += "\tlong version;\n";
|
|
|
|
Result += "\tlong size;\n";
|
|
|
|
Result += "\tconst char *name;\n";
|
|
|
|
Result += "\tstruct _objc_symtab *symtab;\n";
|
|
|
|
Result += "};\n\n";
|
|
|
|
Result += "static struct _objc_module "
|
|
|
|
"_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
|
|
|
|
Result += "\t" + utostr(OBJC_ABI_VERSION) +
|
|
|
|
", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
|
|
|
|
Result += "};\n\n";
|
|
|
|
|
|
|
|
if (LangOpts.MicrosoftExt) {
|
|
|
|
if (ProtocolExprDecls.size()) {
|
|
|
|
Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
|
|
|
|
Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";
|
|
|
|
for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
|
|
|
|
E = ProtocolExprDecls.end(); I != E; ++I) {
|
|
|
|
Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
|
|
|
|
Result += (*I)->getNameAsString();
|
|
|
|
Result += " = &_OBJC_PROTOCOL_";
|
|
|
|
Result += (*I)->getNameAsString();
|
|
|
|
Result += ";\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
Result += "#pragma data_seg(pop)\n\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";
|
|
|
|
Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";
|
|
|
|
Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";
|
|
|
|
Result += "&_OBJC_MODULES;\n";
|
|
|
|
Result += "#pragma data_seg(pop)\n\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
|
|
|
|
/// implementation.
|
|
|
|
void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
|
|
|
|
std::string &Result) {
|
|
|
|
ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
|
|
|
|
// Find category declaration for this implementation.
|
|
|
|
ObjCCategoryDecl *CDecl;
|
|
|
|
for (CDecl = ClassDecl->getCategoryList(); CDecl;
|
|
|
|
CDecl = CDecl->getNextClassCategory())
|
|
|
|
if (CDecl->getIdentifier() == IDecl->getIdentifier())
|
|
|
|
break;
|
|
|
|
|
|
|
|
std::string FullCategoryName = ClassDecl->getNameAsString();
|
|
|
|
FullCategoryName += '_';
|
|
|
|
FullCategoryName += IDecl->getNameAsString();
|
|
|
|
|
|
|
|
// Build _objc_method_list for class's instance methods if needed
|
|
|
|
SmallVector<ObjCMethodDecl *, 32>
|
|
|
|
InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end());
|
|
|
|
|
|
|
|
// If any of our property implementations have associated getters or
|
|
|
|
// setters, produce metadata for them as well.
|
|
|
|
for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(),
|
|
|
|
PropEnd = IDecl->propimpl_end();
|
|
|
|
Prop != PropEnd; ++Prop) {
|
|
|
|
if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
|
|
|
|
continue;
|
|
|
|
if (!(*Prop)->getPropertyIvarDecl())
|
|
|
|
continue;
|
|
|
|
ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl();
|
|
|
|
if (!PD)
|
|
|
|
continue;
|
|
|
|
if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
|
|
|
|
InstanceMethods.push_back(Getter);
|
|
|
|
if (PD->isReadOnly())
|
|
|
|
continue;
|
|
|
|
if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
|
|
|
|
InstanceMethods.push_back(Setter);
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
|
|
|
|
true, "CATEGORY_", FullCategoryName.c_str(),
|
|
|
|
Result);
|
|
|
|
|
|
|
|
// Build _objc_method_list for class's class methods if needed
|
|
|
|
RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
|
|
|
|
false, "CATEGORY_", FullCategoryName.c_str(),
|
|
|
|
Result);
|
|
|
|
|
|
|
|
// Protocols referenced in class declaration?
|
|
|
|
// Null CDecl is case of a category implementation with no category interface
|
|
|
|
if (CDecl)
|
|
|
|
RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
|
|
|
|
FullCategoryName, Result);
|
|
|
|
/* struct _objc_category {
|
|
|
|
char *category_name;
|
|
|
|
char *class_name;
|
|
|
|
struct _objc_method_list *instance_methods;
|
|
|
|
struct _objc_method_list *class_methods;
|
|
|
|
struct _objc_protocol_list *protocols;
|
|
|
|
// Objective-C 1.0 extensions
|
|
|
|
uint32_t size; // sizeof (struct _objc_category)
|
|
|
|
struct _objc_property_list *instance_properties; // category's own
|
|
|
|
// @property decl.
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool objc_category = false;
|
|
|
|
if (!objc_category) {
|
|
|
|
Result += "\nstruct _objc_category {\n";
|
|
|
|
Result += "\tchar *category_name;\n";
|
|
|
|
Result += "\tchar *class_name;\n";
|
|
|
|
Result += "\tstruct _objc_method_list *instance_methods;\n";
|
|
|
|
Result += "\tstruct _objc_method_list *class_methods;\n";
|
|
|
|
Result += "\tstruct _objc_protocol_list *protocols;\n";
|
|
|
|
Result += "\tunsigned int size;\n";
|
|
|
|
Result += "\tstruct _objc_property_list *instance_properties;\n";
|
|
|
|
Result += "};\n";
|
|
|
|
objc_category = true;
|
2010-01-05 03:50:07 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
|
|
|
|
Result += FullCategoryName;
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
|
|
|
|
Result += IDecl->getNameAsString();
|
|
|
|
Result += "\"\n\t, \"";
|
|
|
|
Result += ClassDecl->getNameAsString();
|
|
|
|
Result += "\"\n";
|
2010-01-05 03:50:07 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
|
|
|
|
Result += "\t, (struct _objc_method_list *)"
|
|
|
|
"&_OBJC_CATEGORY_INSTANCE_METHODS_";
|
|
|
|
Result += FullCategoryName;
|
|
|
|
Result += "\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
else
|
|
|
|
Result += "\t, 0\n";
|
|
|
|
if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
|
|
|
|
Result += "\t, (struct _objc_method_list *)"
|
|
|
|
"&_OBJC_CATEGORY_CLASS_METHODS_";
|
|
|
|
Result += FullCategoryName;
|
|
|
|
Result += "\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
else
|
|
|
|
Result += "\t, 0\n";
|
|
|
|
|
|
|
|
if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
|
|
|
|
Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
|
|
|
|
Result += FullCategoryName;
|
|
|
|
Result += "\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Result += "\t, 0\n";
|
|
|
|
Result += "\t, sizeof(struct _objc_category), 0\n};\n";
|
|
|
|
}
|
2008-10-29 04:29:00 +08:00
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
|
|
|
|
/// class methods.
|
|
|
|
template<typename MethodIterator>
|
|
|
|
void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
|
|
|
|
MethodIterator MethodEnd,
|
|
|
|
bool IsInstanceMethod,
|
|
|
|
StringRef prefix,
|
|
|
|
StringRef ClassName,
|
|
|
|
std::string &Result) {
|
|
|
|
if (MethodBegin == MethodEnd) return;
|
|
|
|
|
|
|
|
if (!objc_impl_method) {
|
|
|
|
/* struct _objc_method {
|
|
|
|
SEL _cmd;
|
|
|
|
char *method_types;
|
|
|
|
void *_imp;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
Result += "\nstruct _objc_method {\n";
|
|
|
|
Result += "\tSEL _cmd;\n";
|
|
|
|
Result += "\tchar *method_types;\n";
|
|
|
|
Result += "\tvoid *_imp;\n";
|
|
|
|
Result += "};\n";
|
|
|
|
|
|
|
|
objc_impl_method = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build _objc_method_list for class's methods if needed
|
|
|
|
|
|
|
|
/* struct {
|
|
|
|
struct _objc_method_list *next_method;
|
|
|
|
int method_count;
|
|
|
|
struct _objc_method method_list[];
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
|
|
|
|
Result += "\nstatic struct {\n";
|
|
|
|
Result += "\tstruct _objc_method_list *next_method;\n";
|
|
|
|
Result += "\tint method_count;\n";
|
|
|
|
Result += "\tstruct _objc_method method_list[";
|
|
|
|
Result += utostr(NumMethods);
|
|
|
|
Result += "];\n} _OBJC_";
|
|
|
|
Result += prefix;
|
|
|
|
Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
|
|
|
|
Result += "_METHODS_";
|
|
|
|
Result += ClassName;
|
|
|
|
Result += " __attribute__ ((used, section (\"__OBJC, __";
|
|
|
|
Result += IsInstanceMethod ? "inst" : "cls";
|
|
|
|
Result += "_meth\")))= ";
|
|
|
|
Result += "{\n\t0, " + utostr(NumMethods) + "\n";
|
|
|
|
|
|
|
|
Result += "\t,{{(SEL)\"";
|
|
|
|
Result += (*MethodBegin)->getSelector().getAsString().c_str();
|
|
|
|
std::string MethodTypeString;
|
|
|
|
Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
|
|
|
|
Result += "\", \"";
|
|
|
|
Result += MethodTypeString;
|
|
|
|
Result += "\", (void *)";
|
|
|
|
Result += MethodInternalNames[*MethodBegin];
|
|
|
|
Result += "}\n";
|
|
|
|
for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
|
|
|
|
Result += "\t ,{(SEL)\"";
|
|
|
|
Result += (*MethodBegin)->getSelector().getAsString().c_str();
|
|
|
|
std::string MethodTypeString;
|
|
|
|
Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
|
|
|
|
Result += "\", \"";
|
|
|
|
Result += MethodTypeString;
|
|
|
|
Result += "\", (void *)";
|
|
|
|
Result += MethodInternalNames[*MethodBegin];
|
|
|
|
Result += "}\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
Result += "\t }\n};\n";
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 02:25:15 +08:00
|
|
|
Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
|
|
|
|
SourceRange OldRange = IV->getSourceRange();
|
|
|
|
Expr *BaseExpr = IV->getBase();
|
|
|
|
|
|
|
|
// Rewrite the base, but without actually doing replaces.
|
|
|
|
{
|
|
|
|
DisableReplaceStmtScope S(*this);
|
|
|
|
BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
|
|
|
|
IV->setBase(BaseExpr);
|
2009-12-05 23:55:59 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
ObjCIvarDecl *D = IV->getDecl();
|
|
|
|
|
|
|
|
Expr *Replacement = IV;
|
|
|
|
if (CurMethodDef) {
|
|
|
|
if (BaseExpr->getType()->isObjCObjectPointerType()) {
|
|
|
|
const ObjCInterfaceType *iFaceDecl =
|
|
|
|
dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
|
|
|
|
assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
|
|
|
|
// lookup which class implements the instance variable.
|
|
|
|
ObjCInterfaceDecl *clsDeclared = 0;
|
|
|
|
iFaceDecl->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);
|
|
|
|
RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
II);
|
|
|
|
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
|
|
|
|
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
|
|
|
|
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
|
|
|
|
CK_BitCast,
|
|
|
|
IV->getBase());
|
|
|
|
// Don't forget the parens to enforce the proper binding.
|
|
|
|
ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),
|
|
|
|
OldRange.getEnd(),
|
|
|
|
castExpr);
|
|
|
|
if (IV->isFreeIvar() &&
|
2011-12-15 08:29:59 +08:00
|
|
|
declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) {
|
2011-12-09 02:25:15 +08:00
|
|
|
MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
|
|
|
|
IV->getLocation(),
|
|
|
|
D->getType(),
|
|
|
|
VK_LValue, OK_Ordinary);
|
|
|
|
Replacement = ME;
|
|
|
|
} else {
|
|
|
|
IV->setBase(PE);
|
2008-10-30 02:15:37 +08:00
|
|
|
}
|
2011-12-06 06:59:54 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
} else { // we are outside a method.
|
|
|
|
assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
|
|
|
|
|
|
|
|
// Explicit ivar refs need to have a cast inserted.
|
|
|
|
// FIXME: consider sharing some of this code with the code above.
|
|
|
|
if (BaseExpr->getType()->isObjCObjectPointerType()) {
|
|
|
|
const ObjCInterfaceType *iFaceDecl =
|
|
|
|
dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
|
|
|
|
// lookup which class implements the instance variable.
|
|
|
|
ObjCInterfaceDecl *clsDeclared = 0;
|
|
|
|
iFaceDecl->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);
|
|
|
|
RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
|
|
|
|
SourceLocation(), SourceLocation(),
|
|
|
|
II);
|
|
|
|
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
|
|
|
|
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
|
|
|
|
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
|
|
|
|
CK_BitCast,
|
|
|
|
IV->getBase());
|
|
|
|
// Don't forget the parens to enforce the proper binding.
|
|
|
|
ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
|
|
|
|
IV->getBase()->getLocEnd(), castExpr);
|
|
|
|
// 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);
|
2011-12-06 06:59:54 +08:00
|
|
|
}
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
2011-12-09 02:25:15 +08:00
|
|
|
|
|
|
|
ReplaceStmtWithRange(IV, Replacement, OldRange);
|
|
|
|
return Replacement;
|
2008-10-29 04:29:00 +08:00
|
|
|
}
|
|
|
|
|