// Objective-c statements
virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
SourceLocation RParen,
- StmtArg Parm, StmtArg Body,
+ DeclTy *Parm, StmtArg Body,
StmtArg CatchList) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
bool sawIdTypedCatch = false;
Stmt *lastCatchBody = 0;
while (catchList) {
- Stmt *catchStmt = catchList->getCatchParamStmt();
+ ParmVarDecl *catchDecl = catchList->getCatchParamDecl();
if (catchList == S->getCatchStmts())
buf = "if ("; // we are generating code for the first catch clause
buf += "1) { id _tmp = _caught;";
Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1,
buf.c_str(), buf.size());
- } else if (DeclStmt *declStmt = dyn_cast<DeclStmt>(catchStmt)) {
- QualType t = dyn_cast<ValueDecl>(declStmt->getSolitaryDecl())->getType();
+ } else if (catchDecl) {
+ QualType t = catchDecl->getType();
if (t == Context->getObjCIdType()) {
buf += "1) { ";
ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size());
// Here we replace ") {" with "= _caught;" (which initializes and
// declares the @catch parameter).
ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, buf.c_str(), buf.size());
- } else if (!isa<NullStmt>(catchStmt)) {
+ } else {
assert(false && "@catch rewrite bug");
}
// make sure all the catch bodies get rewritten!
class ASTContext;
class Expr;
class Decl;
+ class ParmVarDecl;
class QualType;
class IdentifierInfo;
class SourceManager;
/// ObjCAtCatchStmt - This represents objective-c's @catch statement.
class ObjCAtCatchStmt : public Stmt {
private:
- enum { SELECTOR, BODY, NEXT_CATCH, END_EXPR };
+ enum { BODY, NEXT_CATCH, END_EXPR };
+ ParmVarDecl *ExceptionDecl;
Stmt *SubExprs[END_EXPR];
SourceLocation AtCatchLoc, RParenLoc;
public:
ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
- DeclStmt *catchVarStmtDecl,
+ ParmVarDecl *catchVarDecl,
Stmt *atCatchStmt, Stmt *atCatchList);
const Stmt *getCatchBody() const { return SubExprs[BODY]; }
return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]);
}
- const DeclStmt *getCatchParamStmt() const {
- return static_cast<const DeclStmt*>(SubExprs[SELECTOR]); }
- DeclStmt *getCatchParamStmt() {
- return static_cast<DeclStmt*>(SubExprs[SELECTOR]);
+ const ParmVarDecl *getCatchParamDecl() const {
+ return ExceptionDecl;
+ }
+ ParmVarDecl *getCatchParamDecl() {
+ return ExceptionDecl;
}
SourceLocation getRParenLoc() const { return RParenLoc; }
return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd());
}
- bool hasEllipsis() const { return getCatchParamStmt() == 0; }
+ bool hasEllipsis() const { return getCatchParamDecl() == 0; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtCatchStmtClass;
// Objective-c statements
virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
SourceLocation RParen,
- StmtArg Parm, StmtArg Body,
+ DeclTy *Parm, StmtArg Body,
StmtArg CatchList) {
return StmtEmpty();
}
ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
SourceLocation rparenloc,
- DeclStmt *catchVarStmtDecl, Stmt *atCatchStmt,
+ ParmVarDecl *catchVarDecl, Stmt *atCatchStmt,
Stmt *atCatchList)
: Stmt(ObjCAtCatchStmtClass) {
- SubExprs[SELECTOR] = catchVarStmtDecl;
+ ExceptionDecl = catchVarDecl;
SubExprs[BODY] = atCatchStmt;
SubExprs[NEXT_CATCH] = NULL;
// FIXME: O(N^2) in number of catch blocks.
catchStmt =
static_cast<ObjCAtCatchStmt *>(catchStmt->getNextCatchStmt())) {
Indent() << "@catch(";
- if (catchStmt->getCatchParamStmt()) {
- if (DeclStmt *DS = dyn_cast<DeclStmt>(catchStmt->getCatchParamStmt()))
- PrintRawDeclStmt(DS);
+ if (catchStmt->getCatchParamDecl()) {
+ if (Decl *DS = catchStmt->getCatchParamDecl())
+ PrintRawDecl(DS);
}
OS << ")";
if (CompoundStmt *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody()))
for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch");
- const DeclStmt *CatchParam = CatchStmt->getCatchParamStmt();
- const VarDecl *VD = 0;
+ const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl();
const PointerType *PT = 0;
// catch(...) always matches.
if (!CatchParam) {
AllMatched = true;
} else {
- VD = cast<VarDecl>(CatchParam->getSolitaryDecl());
- PT = VD->getType()->getAsPointerType();
+ PT = CatchParam->getType()->getAsPointerType();
// catch(id e) always matches.
// FIXME: For the time being we also match id<X>; this should
// be rejected by Sema instead.
if ((PT && CGF.getContext().isObjCIdStructType(PT->getPointeeType())) ||
- VD->getType()->isObjCQualifiedIdType())
+ CatchParam->getType()->isObjCQualifiedIdType())
AllMatched = true;
}
if (AllMatched) {
if (CatchParam) {
- CGF.EmitStmt(CatchParam);
+ CGF.EmitLocalBlockVarDecl(*CatchParam);
assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
- CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(VD));
+ CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
}
CGF.EmitStmt(CatchStmt->getCatchBody());
// Emit the @catch block.
CGF.EmitBlock(MatchedBlock);
- CGF.EmitStmt(CatchParam);
+ CGF.EmitLocalBlockVarDecl(*CatchParam);
assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
llvm::Value *Tmp =
- CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(VD->getType()),
+ CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(CatchParam->getType()),
"tmp");
- CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(VD));
+ CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
CGF.EmitStmt(CatchStmt->getCatchBody());
CGF.EmitBranchThroughCleanup(FinallyEnd);
SelectorArgs.push_back(ObjCTypes.EHPersonalityPtr);
// Construct the lists of (type, catch body) to handle.
- llvm::SmallVector<std::pair<const DeclStmt*, const Stmt*>, 8> Handlers;
+ llvm::SmallVector<std::pair<const Decl*, const Stmt*>, 8> Handlers;
bool HasCatchAll = false;
if (isTry) {
if (const ObjCAtCatchStmt* CatchStmt =
cast<ObjCAtTryStmt>(S).getCatchStmts()) {
for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
- const DeclStmt *DS = CatchStmt->getCatchParamStmt();
- Handlers.push_back(std::make_pair(DS, CatchStmt->getCatchBody()));
+ const Decl *CatchDecl = CatchStmt->getCatchParamDecl();
+ Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody()));
// catch(...) always matches.
- if (!DS) {
+ if (!CatchDecl) {
// Use i8* null here to signal this is a catch all, not a cleanup.
llvm::Value *Null = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
SelectorArgs.push_back(Null);
break;
}
- const VarDecl *VD = cast<VarDecl>(DS->getSolitaryDecl());
+ const VarDecl *VD = cast<VarDecl>(CatchDecl);
if (CGF.getContext().isObjCIdType(VD->getType()) ||
VD->getType()->isObjCQualifiedIdType()) {
llvm::Value *IDEHType =
// We use a cleanup unless there was already a catch all.
if (!HasCatchAll) {
SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
- Handlers.push_back(std::make_pair((const DeclStmt*) 0, (const Stmt*) 0));
+ Handlers.push_back(std::make_pair((const Decl*) 0, (const Stmt*) 0));
}
llvm::Value *Selector =
SelectorArgs.begin(), SelectorArgs.end(),
"selector");
for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
- const DeclStmt *CatchParam = Handlers[i].first;
+ const Decl *CatchParam = Handlers[i].first;
const Stmt *CatchBody = Handlers[i].second;
llvm::BasicBlock *Next = 0;
// Bind the catch parameter if it exists.
if (CatchParam) {
- const VarDecl *VD = cast<VarDecl>(CatchParam->getSolitaryDecl());
+ const VarDecl *VD = dyn_cast<VarDecl>(CatchParam);
ExcObject = CGF.Builder.CreateBitCast(ExcObject,
CGF.ConvertType(VD->getType()));
- CGF.EmitStmt(CatchParam);
+ CGF.EmitLocalBlockVarDecl(*VD);
CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(VD));
}
SourceLocation AtCatchFinallyLoc = ConsumeToken();
if (Tok.isObjCAtKeyword(tok::objc_catch)) {
- OwningStmtResult FirstPart(Actions);
+ DeclTy *FirstPart = 0;
ConsumeToken(); // consume catch
if (Tok.is(tok::l_paren)) {
ConsumeParen();
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
// For some odd reason, the name of the exception variable is
- // optional. As a result, we need to use PrototypeContext.
- Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
- ParseDeclarator(DeclaratorInfo);
- if (DeclaratorInfo.getIdentifier()) {
- DeclTy *aBlockVarDecl = Actions.ActOnDeclarator(CurScope,
- DeclaratorInfo, 0);
- FirstPart =
- Actions.ActOnDeclStmt(aBlockVarDecl,
- DS.getSourceRange().getBegin(),
- DeclaratorInfo.getSourceRange().getEnd());
- }
+ // optional. As a result, we need to use "PrototypeContext", because
+ // we must accept either 'declarator' or 'abstract-declarator' here.
+ Declarator ParmDecl(DS, Declarator::PrototypeContext);
+ ParseDeclarator(ParmDecl);
+
+ // Inform the actions module about the parameter declarator, so it
+ // gets added to the current scope.
+ FirstPart = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
} else
ConsumeToken(); // consume '...'
SourceLocation RParenLoc = ConsumeParen();
if (CatchBody.isInvalid())
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
- RParenLoc, move(FirstPart), move(CatchBody),
+ RParenLoc, FirstPart, move(CatchBody),
move(CatchStmts));
} else {
Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
SourceLocation RParen,
- StmtArg Parm, StmtArg Body,
+ DeclTy *Parm, StmtArg Body,
StmtArg CatchList);
virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
Action::OwningStmtResult
Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
- SourceLocation RParen, StmtArg Parm,
+ SourceLocation RParen, DeclTy *Parm,
StmtArg Body, StmtArg catchList) {
Stmt *CatchList = static_cast<Stmt*>(catchList.release());
ObjCAtCatchStmt *CS = new (Context) ObjCAtCatchStmt(AtLoc, RParen,
- static_cast<DeclStmt*>(Parm.release()), static_cast<Stmt*>(Body.release()),
+ static_cast<ParmVarDecl*>(Parm), static_cast<Stmt*>(Body.release()),
CatchList);
return Owned(CatchList ? CatchList : CS);
}