Implement template instantiation for exception specifications. Also,

print exception specifications on function types and
declarations. Fixes <rdar://problem/7450999>.

There is some poor source-location information here, because we don't
track locations of the types in exception specifications. Filed PR5719.

Failures during template instantiation of the signature of a function
or function template have wrong point-of-instantiation location
information. I'll tackle that with a separate commit.

llvm-svn: 90863
This commit is contained in:
Douglas Gregor 2009-12-08 17:45:32 +00:00
parent 04bc01833e
commit 049bdcac49
4 changed files with 83 additions and 0 deletions

View File

@ -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)) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}