Implement template instantiation for Objective-C @catch

statements. This is the last of the Objective-C statements.

llvm-svn: 102356
This commit is contained in:
Douglas Gregor 2010-04-26 17:57:08 +00:00
parent 5de7f6e02b
commit f4e837f66c
4 changed files with 76 additions and 6 deletions

View File

@ -1726,6 +1726,8 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,
// FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"?
if (Invalid) {
// Don't do any further checking.
} else if (T->isDependentType()) {
// Okay: we don't know what this type will instantiate to.
} else if (!T->isObjCObjectPointerType()) {
Invalid = true;
Diag(NameLoc ,diag::err_catch_param_not_objc_type);

View File

@ -589,6 +589,11 @@ namespace {
IdentifierInfo *Name,
SourceLocation Loc, SourceRange TypeRange);
/// \brief Rebuild the Objective-C exception declaration and register the
/// declaration as an instantiated local.
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TSInfo, QualType T);
/// \brief Check for tag mismatches when instantiating an
/// elaborated type.
QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag);
@ -687,7 +692,16 @@ TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
SourceRange TypeRange) {
VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, T, Declarator,
Name, Loc, TypeRange);
if (Var && !Var->isInvalidDecl())
if (Var)
getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
return Var;
}
VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TSInfo,
QualType T) {
VarDecl *Var = inherited::RebuildObjCExceptionDecl(ExceptionDecl, TSInfo, T);
if (Var)
getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
return Var;
}

View File

@ -901,6 +901,30 @@ public:
move(Finally));
}
/// \brief Rebuild an Objective-C exception declaration.
///
/// By default, performs semantic analysis to build the new declaration.
/// Subclasses may override this routine to provide different behavior.
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
TypeSourceInfo *TInfo, QualType T) {
return getSema().BuildObjCExceptionDecl(TInfo, T,
ExceptionDecl->getIdentifier(),
ExceptionDecl->getLocation());
}
/// \brief Build a new Objective-C @catch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
OwningStmtResult RebuildObjCAtCatchStmt(SourceLocation AtLoc,
SourceLocation RParenLoc,
VarDecl *Var,
StmtArg Body) {
return getSema().ActOnObjCAtCatchStmt(AtLoc, RParenLoc,
Sema::DeclPtrTy::make(Var),
move(Body));
}
/// \brief Build a new Objective-C @finally statement.
///
/// By default, performs semantic analysis to build the new statement.
@ -3722,9 +3746,37 @@ TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
template<typename Derived>
Sema::OwningStmtResult
TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
// FIXME: Implement this
assert(false && "Cannot transform an Objective-C @catch statement");
return SemaRef.Owned(S->Retain());
// Transform the @catch parameter, if there is one.
VarDecl *Var = 0;
if (VarDecl *FromVar = S->getCatchParamDecl()) {
TypeSourceInfo *TSInfo = 0;
if (FromVar->getTypeSourceInfo()) {
TSInfo = getDerived().TransformType(FromVar->getTypeSourceInfo());
if (!TSInfo)
return SemaRef.StmtError();
}
QualType T;
if (TSInfo)
T = TSInfo->getType();
else {
T = getDerived().TransformType(FromVar->getType());
if (T.isNull())
return SemaRef.StmtError();
}
Var = getDerived().RebuildObjCExceptionDecl(FromVar, TSInfo, T);
if (!Var)
return SemaRef.StmtError();
}
OwningStmtResult Body = getDerived().TransformStmt(S->getCatchBody());
if (Body.isInvalid())
return SemaRef.StmtError();
return getDerived().RebuildObjCAtCatchStmt(S->getAtCatchLoc(),
S->getRParenLoc(),
Var, move(Body));
}
template<typename Derived>

View File

@ -65,11 +65,13 @@ void try_catch_finally_test(U value) {
@try {
value = 1; // expected-error{{assigning to 'int *' from incompatible type 'int'}}
}
// FIXME: Add @catch
@finally {
@catch (T obj) { // expected-error{{@catch parameter is not a pointer to an interface type}}
id x = obj;
} @finally {
value = 0;
}
}
template void try_catch_finally_test<NSString *>(int);
template void try_catch_finally_test<NSString *>(int*); // expected-note{{in instantiation of}}
template void try_catch_finally_test<NSString>(int); // expected-note{{in instantiation of function template specialization 'try_catch_finally_test<NSString, int>' requested here}}