summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp16
-rw-r--r--clang/lib/Sema/TreeTransform.h58
-rw-r--r--clang/test/SemaObjCXX/instantiate-stmt.mm6
4 files changed, 76 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index b7ef8df1687..0e93ebda085 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -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);
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index abc8e5fb560..6fdf243d7bb 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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;
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 302d405b7f9..f9bc0c77371 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -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>
diff --git a/clang/test/SemaObjCXX/instantiate-stmt.mm b/clang/test/SemaObjCXX/instantiate-stmt.mm
index 5e14a99b9bd..e92f8e8d4f0 100644
--- a/clang/test/SemaObjCXX/instantiate-stmt.mm
+++ b/clang/test/SemaObjCXX/instantiate-stmt.mm
@@ -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}}
OpenPOWER on IntegriCloud