diff options
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 18 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 37 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-exception-spec.cpp | 11 |
4 files changed, 83 insertions, 0 deletions
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 2c3b927e43..adf7ed3b0e 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -361,6 +361,24 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } Proto += ")"; + + if (FT && FT->hasExceptionSpec()) { + Proto += " throw("; + if (FT->hasAnyExceptionSpec()) + Proto += "..."; + else + for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) { + if (I) + Proto += ", "; + + + std::string ExceptionType; + FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy); + Proto += ExceptionType; + } + Proto += ")"; + } + if (D->hasAttr<NoReturnAttr>()) Proto += " __attribute((noreturn))"; if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) { diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 2f58ebed4b..4a2b956172 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -285,6 +285,23 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, } S += ")"; + + if (T->hasExceptionSpec()) { + S += " throw("; + if (T->hasAnyExceptionSpec()) + S += "..."; + else + for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) { + if (I) + S += ", "; + + std::string ExceptionType; + Print(T->getExceptionType(I), ExceptionType); + S += ExceptionType; + } + S += ")"; + } + if (T->getNoReturnAttr()) S += " __attribute__((noreturn))"; Print(T->getResultType(), S); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index c5173bbca7..80dcfd4e6d 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1390,6 +1390,43 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, } } + const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>(); + assert(Proto && "Function template without prototype?"); + + if (Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec() || + Proto->getNoReturnAttr()) { + // The function has an exception specification or a "noreturn" + // attribute. Substitute into each of the exception types. + llvm::SmallVector<QualType, 4> Exceptions; + for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) { + // FIXME: Poor location information! + QualType T + = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs, + New->getLocation(), New->getDeclName()); + if (T.isNull() || + SemaRef.CheckSpecifiedExceptionType(T, New->getLocation())) + continue; + + Exceptions.push_back(T); + } + + // Rebuild the function type + + const FunctionProtoType *NewProto + = New->getType()->getAs<FunctionProtoType>(); + assert(NewProto && "Template instantiation without function prototype?"); + New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), + NewProto->arg_type_begin(), + NewProto->getNumArgs(), + NewProto->isVariadic(), + NewProto->getTypeQuals(), + Proto->hasExceptionSpec(), + Proto->hasAnyExceptionSpec(), + Exceptions.size(), + Exceptions.data(), + Proto->getNoReturnAttr())); + } + return false; } diff --git a/test/SemaTemplate/instantiate-exception-spec.cpp b/test/SemaTemplate/instantiate-exception-spec.cpp new file mode 100644 index 0000000000..31db4487a2 --- /dev/null +++ b/test/SemaTemplate/instantiate-exception-spec.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// FIXME: the "note" should be down at the call site! +template<typename T> void f1(T*) throw(T); // expected-error{{incomplete type 'struct Incomplete' is not allowed in exception specification}} \ + // expected-note{{instantiation of}} +struct Incomplete; // expected-note{{forward}} + +void test_f1(Incomplete *incomplete_p, int *int_p) { + f1(int_p); + f1(incomplete_p); +} |