diff options
| -rw-r--r-- | clang/lib/AST/DeclPrinter.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 37 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/instantiate-exception-spec.cpp | 11 | 
4 files changed, 83 insertions, 0 deletions
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 2c3b927e436..adf7ed3b0e2 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/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/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 2f58ebed4b9..4a2b9561729 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index c5173bbca7b..80dcfd4e6d2 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/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/clang/test/SemaTemplate/instantiate-exception-spec.cpp b/clang/test/SemaTemplate/instantiate-exception-spec.cpp new file mode 100644 index 00000000000..31db4487a27 --- /dev/null +++ b/clang/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);  +}  | 

