<div dir="ltr"><div>This appears to not compile with MSVC 2013:</div>llvm\tools\clang\include\clang/AST/RecursiveASTVisitor.h(2171) : error C2059: syntax error : '}'<br><div><a href="http://build.chromium.org/p/chromium.fyi/builders/Cr%20Win%20Clang/builds/395/steps/runhooks/logs/stdio">http://build.chromium.org/p/chromium.fyi/builders/Cr%20Win%20Clang/builds/395/steps/runhooks/logs/stdio</a><br></div><div><br></div><div>I believe it is trying to say that TRY_TO doesn't work inside of range-based for loops due to some insanity. This is a known issue when updating RAV. =/</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 17, 2014 at 4:57 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Wed Sep 17 18:57:05 2014<br>
New Revision: 217995<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=217995&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=217995&view=rev</a><br>
Log:<br>
Instantiate exception specifications when instantiating function types (other<br>
than the type of a function declaration). We previously didn't instantiate<br>
these at all! This also covers the pathological case where the only mention of<br>
a parameter pack is within the exception specification; this gives us a second<br>
way (other than alias templates) to reach the horrible state where a type<br>
contains an unexpanded pack, but its canonical type does not.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h<br>
    cfe/trunk/include/clang/AST/Expr.h<br>
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
    cfe/trunk/include/clang/AST/Type.h<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/lib/AST/Type.cpp<br>
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp<br>
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp<br>
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
    cfe/trunk/lib/Sema/SemaType.cpp<br>
    cfe/trunk/lib/Sema/TreeTransform.h<br>
    cfe/trunk/test/CXX/except/except.spec/p1.cpp<br>
    cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp<br>
    cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original)<br>
+++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Wed Sep 17 18:57:05 2014<br>
@@ -876,6 +876,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {<br>
   for (const auto &E : T->exceptions()) {<br>
     TRY_TO(TraverseType(E));<br>
   }<br>
+<br>
+  if (Expr *NE = T->getNoexceptExpr())<br>
+    TRY_TO(TraverseStmt(NE));<br>
 })<br>
<br>
 DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})<br>
@@ -1084,6 +1087,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType,<br>
   for (const auto &E : T->exceptions()) {<br>
     TRY_TO(TraverseType(E));<br>
   }<br>
+<br>
+  if (Expr *NE = T->getNoexceptExpr())<br>
+    TRY_TO(TraverseStmt(NE));<br>
 })<br>
<br>
 DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})<br>
@@ -2123,21 +2129,28 @@ bool RecursiveASTVisitor<Derived>::Trave<br>
     TRY_TO(TraverseLambdaCapture(S, C));<br>
   }<br>
<br>
-  if (S->hasExplicitParameters() || S->hasExplicitResultType()) {<br>
-    TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();<br>
-    if (S->hasExplicitParameters() && S->hasExplicitResultType()) {<br>
-      // Visit the whole type.<br>
-      TRY_TO(TraverseTypeLoc(TL));<br>
-    } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {<br>
-      if (S->hasExplicitParameters()) {<br>
-        // Visit parameters.<br>
-        for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {<br>
-          TRY_TO(TraverseDecl(Proto.getParam(I)));<br>
-        }<br>
-      } else {<br>
-        TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));<br>
+  TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();<br>
+  FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();<br>
+<br>
+  if (S->hasExplicitParameters() && S->hasExplicitResultType()) {<br>
+    // Visit the whole type.<br>
+    TRY_TO(TraverseTypeLoc(TL));<br>
+  } else {<br>
+    if (S->hasExplicitParameters()) {<br>
+      // Visit parameters.<br>
+      for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {<br>
+        TRY_TO(TraverseDecl(Proto.getParam(I)));<br>
       }<br>
+    } else if (S->hasExplicitResultType()) {<br>
+      TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));<br>
     }<br>
+<br>
+    auto *T = Proto.getTypePtr();<br>
+    for (const auto &E : T->exceptions())<br>
+      TRY_TO(TraverseType(E));<br>
+<br>
+    if (Expr *NE = T->getNoexceptExpr())<br>
+      TRY_TO(TraverseStmt(NE));<br>
   }<br>
<br>
   TRY_TO(TraverseLambdaBody(S));<br>
<br>
Modified: cfe/trunk/include/clang/AST/Expr.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/Expr.h (original)<br>
+++ cfe/trunk/include/clang/AST/Expr.h Wed Sep 17 18:57:05 2014<br>
@@ -2673,20 +2673,23 @@ private:<br>
   }<br>
<br>
 protected:<br>
-  CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,<br>
-           const CastKind kind, Expr *op, unsigned BasePathSize) :<br>
-    Expr(SC, ty, VK, OK_Ordinary,<br>
-         // Cast expressions are type-dependent if the type is<br>
-         // dependent (C++ [temp.dep.expr]p3).<br>
-         ty->isDependentType(),<br>
-         // Cast expressions are value-dependent if the type is<br>
-         // dependent or if the subexpression is value-dependent.<br>
-         ty->isDependentType() || (op && op->isValueDependent()),<br>
-         (ty->isInstantiationDependentType() ||<br>
-          (op && op->isInstantiationDependent())),<br>
-         (ty->containsUnexpandedParameterPack() ||<br>
-          (op && op->containsUnexpandedParameterPack()))),<br>
-    Op(op) {<br>
+  CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind,<br>
+           Expr *op, unsigned BasePathSize)<br>
+      : Expr(SC, ty, VK, OK_Ordinary,<br>
+             // Cast expressions are type-dependent if the type is<br>
+             // dependent (C++ [temp.dep.expr]p3).<br>
+             ty->isDependentType(),<br>
+             // Cast expressions are value-dependent if the type is<br>
+             // dependent or if the subexpression is value-dependent.<br>
+             ty->isDependentType() || (op && op->isValueDependent()),<br>
+             (ty->isInstantiationDependentType() ||<br>
+              (op && op->isInstantiationDependent())),<br>
+             // An implicit cast expression doesn't (lexically) contain an<br>
+             // unexpanded pack, even if its target type does.<br>
+             ((SC != ImplicitCastExprClass &&<br>
+               ty->containsUnexpandedParameterPack()) ||<br>
+              (op && op->containsUnexpandedParameterPack()))),<br>
+        Op(op) {<br>
     assert(kind != CK_Invalid && "creating cast with invalid cast kind");<br>
     CastExprBits.Kind = kind;<br>
     setBasePathSize(BasePathSize);<br>
<br>
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)<br>
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Sep 17 18:57:05 2014<br>
@@ -941,6 +941,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {<br>
   for (const auto &E : T->exceptions()) {<br>
     TRY_TO(TraverseType(E));<br>
   }<br>
+<br>
+  if (Expr *NE = T->getNoexceptExpr())<br>
+    TRY_TO(TraverseStmt(NE));<br>
 })<br>
<br>
 DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})<br>
@@ -1149,6 +1152,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType,<br>
   for (const auto &E : T->exceptions()) {<br>
     TRY_TO(TraverseType(E));<br>
   }<br>
+<br>
+  if (Expr *NE = T->getNoexceptExpr())<br>
+    TRY_TO(TraverseStmt(NE));<br>
 })<br>
<br>
 DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})<br>
@@ -2145,21 +2151,28 @@ bool RecursiveASTVisitor<Derived>::Trave<br>
     TRY_TO(TraverseLambdaCapture(S, C));<br>
   }<br>
<br>
-  if (S->hasExplicitParameters() || S->hasExplicitResultType()) {<br>
-    TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();<br>
-    if (S->hasExplicitParameters() && S->hasExplicitResultType()) {<br>
-      // Visit the whole type.<br>
-      TRY_TO(TraverseTypeLoc(TL));<br>
-    } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {<br>
-      if (S->hasExplicitParameters()) {<br>
-        // Visit parameters.<br>
-        for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {<br>
-          TRY_TO(TraverseDecl(Proto.getParam(I)));<br>
-        }<br>
-      } else {<br>
-        TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));<br>
+  TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();<br>
+  FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();<br>
+<br>
+  if (S->hasExplicitParameters() && S->hasExplicitResultType()) {<br>
+    // Visit the whole type.<br>
+    TRY_TO(TraverseTypeLoc(TL));<br>
+  } else {<br>
+    if (S->hasExplicitParameters()) {<br>
+      // Visit parameters.<br>
+      for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {<br>
+        TRY_TO(TraverseDecl(Proto.getParam(I)));<br>
       }<br>
+    } else if (S->hasExplicitResultType()) {<br>
+      TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));<br>
     }<br>
+<br>
+    auto *T = Proto.getTypePtr();<br>
+    for (const auto &E : T->exceptions())<br>
+      TRY_TO(TraverseType(E));<br>
+<br>
+    if (Expr *NE = T->getNoexceptExpr())<br>
+      TRY_TO(TraverseStmt(NE));<br>
   }<br>
<br>
   TRY_TO(TraverseLambdaBody(S));<br>
<br>
Modified: cfe/trunk/include/clang/AST/Type.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/Type.h (original)<br>
+++ cfe/trunk/include/clang/AST/Type.h Wed Sep 17 18:57:05 2014<br>
@@ -3012,6 +3012,8 @@ public:<br>
   bool hasNoexceptExceptionSpec() const {<br>
     return isNoexceptExceptionSpec(getExceptionSpecType());<br>
   }<br>
+  /// \brief Return whether this function has a dependent exception spec.<br>
+  bool hasDependentExceptionSpec() const;<br>
   /// \brief Result type of getNoexceptSpec().<br>
   enum NoexceptResult {<br>
     NR_NoNoexcept,  ///< There is no noexcept specifier.<br>
@@ -5247,8 +5249,8 @@ template <typename T> const T *Type::cas<br>
   ArrayType_cannot_be_used_with_getAs<T> at;<br>
   (void) at;<br>
<br>
-  assert(isa<T>(CanonicalType));<br>
   if (const T *ty = dyn_cast<T>(this)) return ty;<br>
+  assert(isa<T>(CanonicalType));<br>
   return cast<T>(getUnqualifiedDesugaredType());<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Sep 17 18:57:05 2014<br>
@@ -4025,7 +4025,8 @@ public:<br>
<br>
   /// \brief Check the given exception-specification and update the<br>
   /// exception specification information with the results.<br>
-  void checkExceptionSpecification(ExceptionSpecificationType EST,<br>
+  void checkExceptionSpecification(bool IsTopLevel,<br>
+                                   ExceptionSpecificationType EST,<br>
                                    ArrayRef<ParsedType> DynamicExceptions,<br>
                                    ArrayRef<SourceRange> DynamicExceptionRanges,<br>
                                    Expr *NoexceptExpr,<br>
@@ -6652,6 +6653,8 @@ public:<br>
                                         DeclarationName Entity,<br>
                                         CXXRecordDecl *ThisContext,<br>
                                         unsigned ThisTypeQuals);<br>
+  void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,<br>
+                          const MultiLevelTemplateArgumentList &Args);<br>
   ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,<br>
                             const MultiLevelTemplateArgumentList &TemplateArgs,<br>
                                 int indexAdjustment,<br>
<br>
Modified: cfe/trunk/lib/AST/Type.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/Type.cpp (original)<br>
+++ cfe/trunk/lib/AST/Type.cpp Wed Sep 17 18:57:05 2014<br>
@@ -1623,9 +1623,9 @@ FunctionProtoType::FunctionProtoType(Qua<br>
     QualType *exnSlot = argSlot + NumParams;<br>
     unsigned I = 0;<br>
     for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) {<br>
-      if (ExceptionType->isDependentType())<br>
-        setDependent();<br>
-      else if (ExceptionType->isInstantiationDependentType())<br>
+      // Note that a dependent exception specification does *not* make<br>
+      // a type dependent; it's not even part of the C++ type system.<br>
+      if (ExceptionType->isInstantiationDependentType())<br>
         setInstantiationDependent();<br>
<br>
       if (ExceptionType->containsUnexpandedParameterPack())<br>
@@ -1639,11 +1639,12 @@ FunctionProtoType::FunctionProtoType(Qua<br>
     *noexSlot = epi.ExceptionSpec.NoexceptExpr;<br>
<br>
     if (epi.ExceptionSpec.NoexceptExpr) {<br>
-      if (epi.ExceptionSpec.NoexceptExpr->isValueDependent()<br>
-          || epi.ExceptionSpec.NoexceptExpr->isTypeDependent())<br>
-        setDependent();<br>
-      else if (epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())<br>
+      if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||<br>
+          epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())<br>
         setInstantiationDependent();<br>
+<br>
+      if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())<br>
+        setContainsUnexpandedParameterPack();<br>
     }<br>
   } else if (getExceptionSpecType() == EST_Uninstantiated) {<br>
     // Store the function decl from which we will resolve our<br>
@@ -1669,6 +1670,19 @@ FunctionProtoType::FunctionProtoType(Qua<br>
   }<br>
 }<br>
<br>
+bool FunctionProtoType::hasDependentExceptionSpec() const {<br>
+  if (Expr *NE = getNoexceptExpr())<br>
+    return NE->isValueDependent();<br>
+  for (unsigned I = 0, N = getNumExceptions(); I != N; ++I)<br>
+    // A pack expansion with a non-dependent pattern is still dependent,<br>
+    // because we don't know whether the pattern is in the exception spec<br>
+    // or not (that depends on whether the pack has 0 expansions).<br>
+    if (getExceptionType(I)->isDependentType() ||<br>
+        getExceptionType(I)->getAs<PackExpansionType>())<br>
+      return true;<br>
+  return false;<br>
+}<br>
+<br>
 FunctionProtoType::NoexceptResult<br>
 FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {<br>
   ExceptionSpecificationType est = getExceptionSpecType();<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Sep 17 18:57:05 2014<br>
@@ -13051,13 +13051,12 @@ bool Sema::checkThisInStaticMemberFuncti<br>
   return false;<br>
 }<br>
<br>
-void<br>
-Sema::checkExceptionSpecification(ExceptionSpecificationType EST,<br>
-                                  ArrayRef<ParsedType> DynamicExceptions,<br>
-                                  ArrayRef<SourceRange> DynamicExceptionRanges,<br>
-                                  Expr *NoexceptExpr,<br>
-                                  SmallVectorImpl<QualType> &Exceptions,<br>
-                                  FunctionProtoType::ExceptionSpecInfo &ESI) {<br>
+void Sema::checkExceptionSpecification(<br>
+    bool IsTopLevel, ExceptionSpecificationType EST,<br>
+    ArrayRef<ParsedType> DynamicExceptions,<br>
+    ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr,<br>
+    SmallVectorImpl<QualType> &Exceptions,<br>
+    FunctionProtoType::ExceptionSpecInfo &ESI) {<br>
   Exceptions.clear();<br>
   ESI.Type = EST;<br>
   if (EST == EST_Dynamic) {<br>
@@ -13066,13 +13065,15 @@ Sema::checkExceptionSpecification(Except<br>
       // FIXME: Preserve type source info.<br>
       QualType ET = GetTypeFromParser(DynamicExceptions[ei]);<br>
<br>
-      SmallVector<UnexpandedParameterPack, 2> Unexpanded;<br>
-      collectUnexpandedParameterPacks(ET, Unexpanded);<br>
-      if (!Unexpanded.empty()) {<br>
-        DiagnoseUnexpandedParameterPacks(DynamicExceptionRanges[ei].getBegin(),<br>
-                                         UPPC_ExceptionType,<br>
-                                         Unexpanded);<br>
-        continue;<br>
+      if (IsTopLevel) {<br>
+        SmallVector<UnexpandedParameterPack, 2> Unexpanded;<br>
+        collectUnexpandedParameterPacks(ET, Unexpanded);<br>
+        if (!Unexpanded.empty()) {<br>
+          DiagnoseUnexpandedParameterPacks(<br>
+              DynamicExceptionRanges[ei].getBegin(), UPPC_ExceptionType,<br>
+              Unexpanded);<br>
+          continue;<br>
+        }<br>
       }<br>
<br>
       // Check that the type is valid for an exception spec, and<br>
@@ -13091,7 +13092,8 @@ Sema::checkExceptionSpecification(Except<br>
               NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==<br>
               Context.BoolTy) &&<br>
              "Parser should have made sure that the expression is boolean");<br>
-      if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {<br>
+      if (IsTopLevel && NoexceptExpr &&<br>
+          DiagnoseUnexpandedParameterPack(NoexceptExpr)) {<br>
         ESI.Type = EST_BasicNoexcept;<br>
         return;<br>
       }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Wed Sep 17 18:57:05 2014<br>
@@ -720,10 +720,11 @@ static bool CheckSpecForTypesEquivalent(<br>
 /// assignment and override compatibility check. We do not check the parameters<br>
 /// of parameter function pointers recursively, as no sane programmer would<br>
 /// even be able to write such a function type.<br>
-bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,<br>
-    const FunctionProtoType *Target, SourceLocation TargetLoc,<br>
-    const FunctionProtoType *Source, SourceLocation SourceLoc)<br>
-{<br>
+bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &NoteID,<br>
+                                   const FunctionProtoType *Target,<br>
+                                   SourceLocation TargetLoc,<br>
+                                   const FunctionProtoType *Source,<br>
+                                   SourceLocation SourceLoc) {<br>
   if (CheckSpecForTypesEquivalent(<br>
           *this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(),<br>
           Target->getReturnType(), TargetLoc, Source->getReturnType(),<br>
@@ -744,23 +745,30 @@ bool Sema::CheckParamExceptionSpec(const<br>
   return false;<br>
 }<br>
<br>
-bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)<br>
-{<br>
+bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {<br>
   // First we check for applicability.<br>
   // Target type must be a function, function pointer or function reference.<br>
   const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);<br>
-  if (!ToFunc)<br>
+  if (!ToFunc || ToFunc->hasDependentExceptionSpec())<br>
     return false;<br>
<br>
   // SourceType must be a function or function pointer.<br>
   const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());<br>
-  if (!FromFunc)<br>
+  if (!FromFunc || FromFunc->hasDependentExceptionSpec())<br>
     return false;<br>
<br>
   // Now we've got the correct types on both sides, check their compatibility.<br>
   // This means that the source of the conversion can only throw a subset of<br>
   // the exceptions of the target, and any exception specs on arguments or<br>
   // return types must be equivalent.<br>
+  //<br>
+  // FIXME: If there is a nested dependent exception specification, we should<br>
+  // not be checking it here. This is fine:<br>
+  //   template<typename T> void f() {<br>
+  //     void (*p)(void (*) throw(T));<br>
+  //     void (*q)(void (*) throw(int)) = p;<br>
+  //   }<br>
+  // ... because it might be instantiated with T=int.<br>
   return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),<br>
                                   PDiag(), ToFunc,<br>
                                   From->getSourceRange().getBegin(),<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Sep 17 18:57:05 2014<br>
@@ -788,12 +788,14 @@ namespace {<br>
     /// pack.<br>
     ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);<br>
<br>
-    QualType TransformFunctionProtoType(TypeLocBuilder &TLB,<br>
-                                        FunctionProtoTypeLoc TL);<br>
+    // Pull in the base class overload; it just forwards to our function.<br>
+    using inherited::TransformFunctionProtoType;<br>
+    template<typename Fn><br>
     QualType TransformFunctionProtoType(TypeLocBuilder &TLB,<br>
                                         FunctionProtoTypeLoc TL,<br>
                                         CXXRecordDecl *ThisContext,<br>
-                                        unsigned ThisTypeQuals);<br>
+                                        unsigned ThisTypeQuals,<br>
+                                        Fn TransformExceptionSpec);<br>
<br>
     ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,<br>
                                             int indexAdjustment,<br>
@@ -1307,21 +1309,16 @@ ExprResult TemplateInstantiator::Transfo<br>
                                         E->getParam());<br>
 }<br>
<br>
-QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,<br>
-                                                      FunctionProtoTypeLoc TL) {<br>
-  // We need a local instantiation scope for this function prototype.<br>
-  LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);<br>
-  return inherited::TransformFunctionProtoType(TLB, TL);<br>
-}<br>
-<br>
+template<typename Fn><br>
 QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,<br>
                                  FunctionProtoTypeLoc TL,<br>
                                  CXXRecordDecl *ThisContext,<br>
-                                 unsigned ThisTypeQuals) {<br>
+                                 unsigned ThisTypeQuals,<br>
+                                 Fn TransformExceptionSpec) {<br>
   // We need a local instantiation scope for this function prototype.<br>
   LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);<br>
-  return inherited::TransformFunctionProtoType(TLB, TL, ThisContext,<br>
-                                               ThisTypeQuals);<br>
+  return inherited::TransformFunctionProtoType(<br>
+      TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);<br>
 }<br>
<br>
 ParmVarDecl *<br>
@@ -1556,7 +1553,8 @@ static bool NeedsInstantiationAsFunction<br>
<br>
 /// A form of SubstType intended specifically for instantiating the<br>
 /// type of a FunctionDecl.  Its purpose is solely to force the<br>
-/// instantiation of default-argument expressions.<br>
+/// instantiation of default-argument expressions and to avoid<br>
+/// instantiating an exception-specification.<br>
 TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,<br>
                                 const MultiLevelTemplateArgumentList &Args,<br>
                                 SourceLocation Loc,<br>
@@ -1579,9 +1577,17 @@ TypeSourceInfo *Sema::SubstFunctionDeclT<br>
<br>
   QualType Result;<br>
<br>
+  // FIXME: What if the function type is parenthesized?<br>
   if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {<br>
-    Result = Instantiator.TransformFunctionProtoType(TLB, Proto, ThisContext,<br>
-                                                     ThisTypeQuals);<br>
+    // Instantiate the type, other than its exception specification. The<br>
+    // exception specification is instantiated in InitFunctionInstantiation<br>
+    // once we've built the FunctionDecl.<br>
+    // FIXME: Set the exception specification to EST_Uninstantiated here,<br>
+    // instead of rebuilding the function type again later.<br>
+    Result = Instantiator.TransformFunctionProtoType(<br>
+        TLB, Proto, ThisContext, ThisTypeQuals,<br>
+        [](FunctionProtoType::ExceptionSpecInfo &ESI,<br>
+           bool &Changed) { return false; });<br>
   } else {<br>
     Result = Instantiator.TransformType(TLB, TL);<br>
   }<br>
@@ -1591,6 +1597,26 @@ TypeSourceInfo *Sema::SubstFunctionDeclT<br>
   return TLB.getTypeSourceInfo(Context, Result);<br>
 }<br>
<br>
+void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,<br>
+                              const MultiLevelTemplateArgumentList &Args) {<br>
+  FunctionProtoType::ExceptionSpecInfo ESI =<br>
+      Proto->getExtProtoInfo().ExceptionSpec;<br>
+  assert(ESI.Type != EST_Uninstantiated);<br>
+<br>
+  TemplateInstantiator Instantiator(*this, Args, New->getLocation(),<br>
+                                    New->getDeclName());<br>
+<br>
+  SmallVector<QualType, 4> ExceptionStorage;<br>
+  bool Changed = false;<br>
+  if (Instantiator.TransformExceptionSpec(<br>
+          New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), ESI,<br>
+          ExceptionStorage, Changed))<br>
+    // On error, recover by dropping the exception specification.<br>
+    ESI.Type = EST_None;<br>
+<br>
+  UpdateExceptionSpec(New, ESI);<br>
+}<br>
+<br>
 ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,<br>
                             const MultiLevelTemplateArgumentList &TemplateArgs,<br>
                                     int indexAdjustment,<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Sep 17 18:57:05 2014<br>
@@ -2988,7 +2988,7 @@ TemplateDeclInstantiator::SubstFunctionT<br>
 /// Introduce the instantiated function parameters into the local<br>
 /// instantiation scope, and set the parameter names to those used<br>
 /// in the template.<br>
-static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,<br>
+static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,<br>
                                              const FunctionDecl *PatternDecl,<br>
                                              LocalInstantiationScope &Scope,<br>
                            const MultiLevelTemplateArgumentList &TemplateArgs) {<br>
@@ -2999,15 +2999,22 @@ static void addInstantiatedParametersToS<br>
       // Simple case: not a parameter pack.<br>
       assert(FParamIdx < Function->getNumParams());<br>
       ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);<br>
+      FunctionParam->setDeclName(PatternParam->getDeclName());<br>
       // If the parameter's type is not dependent, update it to match the type<br>
       // in the pattern. They can differ in top-level cv-qualifiers, and we want<br>
       // the pattern's type here. If the type is dependent, they can't differ,<br>
-      // per core issue 1668.<br>
+      // per core issue 1668. Substitute into the type from the pattern, in case<br>
+      // it's instantiation-dependent.<br>
       // FIXME: Updating the type to work around this is at best fragile.<br>
-      if (!PatternDecl->getType()->isDependentType())<br>
-        FunctionParam->setType(PatternParam->getType());<br>
+      if (!PatternDecl->getType()->isDependentType()) {<br>
+        QualType T = S.SubstType(PatternParam->getType(), TemplateArgs,<br>
+                                 FunctionParam->getLocation(),<br>
+                                 FunctionParam->getDeclName());<br>
+        if (T.isNull())<br>
+          return true;<br>
+        FunctionParam->setType(T);<br>
+      }<br>
<br>
-      FunctionParam->setDeclName(PatternParam->getDeclName());<br>
       Scope.InstantiatedLocal(PatternParam, FunctionParam);<br>
       ++FParamIdx;<br>
       continue;<br>
@@ -3019,136 +3026,27 @@ static void addInstantiatedParametersToS<br>
       = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);<br>
     assert(NumArgumentsInExpansion &&<br>
            "should only be called when all template arguments are known");<br>
+    QualType PatternType =<br>
+        PatternParam->getType()->castAs<PackExpansionType>()->getPattern();<br>
     for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {<br>
       ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);<br>
-      if (!PatternDecl->getType()->isDependentType())<br>
-        FunctionParam->setType(PatternParam->getType());<br>
-<br>
       FunctionParam->setDeclName(PatternParam->getDeclName());<br>
-      Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);<br>
-      ++FParamIdx;<br>
-    }<br>
-  }<br>
-}<br>
-<br>
-static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,<br>
-                                     const FunctionProtoType *Proto,<br>
-                           const MultiLevelTemplateArgumentList &TemplateArgs) {<br>
-  assert(Proto->getExceptionSpecType() != EST_Uninstantiated);<br>
-<br>
-  // C++11 [expr.prim.general]p3:<br>
-  //   If a declaration declares a member function or member function<br>
-  //   template of a class X, the expression this is a prvalue of type<br>
-  //   "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq<br>
-  //   and the end of the function-definition, member-declarator, or<br>
-  //   declarator.<br>
-  CXXRecordDecl *ThisContext = nullptr;<br>
-  unsigned ThisTypeQuals = 0;<br>
-  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {<br>
-    ThisContext = Method->getParent();<br>
-    ThisTypeQuals = Method->getTypeQualifiers();<br>
-  }<br>
-  Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,<br>
-                                   SemaRef.getLangOpts().CPlusPlus11);<br>
-<br>
-  // The function has an exception specification or a "noreturn"<br>
-  // attribute. Substitute into each of the exception types.<br>
-  SmallVector<QualType, 4> Exceptions;<br>
-  for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {<br>
-    // FIXME: Poor location information!<br>
-    if (const PackExpansionType *PackExpansion<br>
-          = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {<br>
-      // We have a pack expansion. Instantiate it.<br>
-      SmallVector<UnexpandedParameterPack, 2> Unexpanded;<br>
-      SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),<br>
-                                              Unexpanded);<br>
-      assert(!Unexpanded.empty() &&<br>
-             "Pack expansion without parameter packs?");<br>
-<br>
-      bool Expand = false;<br>
-      bool RetainExpansion = false;<br>
-      Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();<br>
-      if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),<br>
-                                                  SourceRange(),<br>
-                                                  Unexpanded,<br>
-                                                  TemplateArgs,<br>
-                                                  Expand,<br>
-                                                  RetainExpansion,<br>
-                                                  NumExpansions))<br>
-        break;<br>
-<br>
-      if (!Expand) {<br>
-        // We can't expand this pack expansion into separate arguments yet;<br>
-        // just substitute into the pattern and create a new pack expansion<br>
-        // type.<br>
-        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);<br>
-        QualType T = SemaRef.SubstType(PackExpansion->getPattern(),<br>
-                                       TemplateArgs,<br>
-                                     New->getLocation(), New->getDeclName());<br>
+      if (!PatternDecl->getType()->isDependentType()) {<br>
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg);<br>
+        QualType T = S.SubstType(PatternType, TemplateArgs,<br>
+                                 FunctionParam->getLocation(),<br>
+                                 FunctionParam->getDeclName());<br>
         if (T.isNull())<br>
-          break;<br>
-<br>
-        T = SemaRef.Context.getPackExpansionType(T, NumExpansions);<br>
-        Exceptions.push_back(T);<br>
-        continue;<br>
-      }<br>
-<br>
-      // Substitute into the pack expansion pattern for each template<br>
-      bool Invalid = false;<br>
-      for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {<br>
-        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);<br>
-<br>
-        QualType T = SemaRef.SubstType(PackExpansion->getPattern(),<br>
-                                       TemplateArgs,<br>
-                                     New->getLocation(), New->getDeclName());<br>
-        if (T.isNull()) {<br>
-          Invalid = true;<br>
-          break;<br>
-        }<br>
-<br>
-        Exceptions.push_back(T);<br>
+          return true;<br>
+        FunctionParam->setType(T);<br>
       }<br>
<br>
-      if (Invalid)<br>
-        break;<br>
-<br>
-      continue;<br>
-    }<br>
-<br>
-    QualType T<br>
-      = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,<br>
-                          New->getLocation(), New->getDeclName());<br>
-    if (T.isNull() ||<br>
-        SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))<br>
-      continue;<br>
-<br>
-    Exceptions.push_back(T);<br>
-  }<br>
-  Expr *NoexceptExpr = nullptr;<br>
-  if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {<br>
-    EnterExpressionEvaluationContext Unevaluated(SemaRef,<br>
-                                                 Sema::ConstantEvaluated);<br>
-    ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);<br>
-    if (E.isUsable())<br>
-      E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());<br>
-<br>
-    if (E.isUsable()) {<br>
-      NoexceptExpr = E.get();<br>
-      if (!NoexceptExpr->isTypeDependent() &&<br>
-          !NoexceptExpr->isValueDependent())<br>
-        NoexceptExpr<br>
-          = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,<br>
-              nullptr, diag::err_noexcept_needs_constant_expression,<br>
-              /*AllowFold*/ false).get();<br>
+      Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);<br>
+      ++FParamIdx;<br>
     }<br>
   }<br>
<br>
-  FunctionProtoType::ExceptionSpecInfo ESI;<br>
-  ESI.Type = Proto->getExceptionSpecType();<br>
-  ESI.Exceptions = Exceptions;<br>
-  ESI.NoexceptExpr = NoexceptExpr;<br>
-<br>
-  SemaRef.UpdateExceptionSpec(New, ESI);<br>
+  return false;<br>
 }<br>
<br>
 void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,<br>
@@ -3175,11 +3073,14 @@ void Sema::InstantiateExceptionSpec(Sour<br>
     getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);<br>
<br>
   FunctionDecl *Template = Proto->getExceptionSpecTemplate();<br>
-  addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);<br>
+  if (addInstantiatedParametersToScope(*this, Decl, Template, Scope,<br>
+                                       TemplateArgs)) {<br>
+    UpdateExceptionSpec(Decl, EST_None);<br>
+    return;<br>
+  }<br>
<br>
-  ::InstantiateExceptionSpec(*this, Decl,<br>
-                             Template->getType()->castAs<FunctionProtoType>(),<br>
-                             TemplateArgs);<br>
+  SubstExceptionSpec(Decl, Template->getType()->castAs<FunctionProtoType>(),<br>
+                     TemplateArgs);<br>
 }<br>
<br>
 /// \brief Initializes the common fields of an instantiation function<br>
@@ -3248,7 +3149,7 @@ TemplateDeclInstantiator::InitFunctionIn<br>
       New->setType(SemaRef.Context.getFunctionType(<br>
           NewProto->getReturnType(), NewProto->getParamTypes(), EPI));<br>
     } else {<br>
-      ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);<br>
+      SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs);<br>
     }<br>
   }<br>
<br>
@@ -3438,8 +3339,9 @@ void Sema::InstantiateFunctionDefinition<br>
     MultiLevelTemplateArgumentList TemplateArgs =<br>
       getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);<br>
<br>
-    addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,<br>
-                                     TemplateArgs);<br>
+    if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,<br>
+                                         TemplateArgs))<br>
+      return;<br>
<br>
     // If this is a constructor, instantiate the member initializers.<br>
     if (const CXXConstructorDecl *Ctor =<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaType.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaType.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Sep 17 18:57:05 2014<br>
@@ -2989,7 +2989,8 @@ static TypeSourceInfo *GetFullTypeForDec<br>
           NoexceptExpr = FTI.NoexceptExpr;<br>
         }<br>
<br>
-        S.checkExceptionSpecification(FTI.getExceptionSpecType(),<br>
+        S.checkExceptionSpecification(D.isFunctionDeclarationContext(),<br>
+                                      FTI.getExceptionSpecType(),<br>
                                       DynamicExceptions,<br>
                                       DynamicExceptionRanges,<br>
                                       NoexceptExpr,<br>
<br>
Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Sep 17 18:57:05 2014<br>
@@ -542,10 +542,17 @@ public:<br>
   QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);<br>
 #include "clang/AST/TypeLocNodes.def"<br>
<br>
+  template<typename Fn><br>
   QualType TransformFunctionProtoType(TypeLocBuilder &TLB,<br>
                                       FunctionProtoTypeLoc TL,<br>
                                       CXXRecordDecl *ThisContext,<br>
-                                      unsigned ThisTypeQuals);<br>
+                                      unsigned ThisTypeQuals,<br>
+                                      Fn TransformExceptionSpec);<br>
+<br>
+  bool TransformExceptionSpec(SourceLocation Loc,<br>
+                              FunctionProtoType::ExceptionSpecInfo &ESI,<br>
+                              SmallVectorImpl<QualType> &Exceptions,<br>
+                              bool &Changed);<br>
<br>
   StmtResult TransformSEHHandler(Stmt *Handler);<br>
<br>
@@ -4512,15 +4519,19 @@ template<typename Derived><br>
 QualType<br>
 TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,<br>
                                                    FunctionProtoTypeLoc TL) {<br>
-  return getDerived().TransformFunctionProtoType(TLB, TL, nullptr, 0);<br>
+  SmallVector<QualType, 4> ExceptionStorage;<br>
+  return getDerived().TransformFunctionProtoType(<br>
+      TLB, TL, nullptr, 0,<br>
+      [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {<br>
+        return TransformExceptionSpec(TL.getBeginLoc(), ESI, ExceptionStorage,<br>
+                                      Changed);<br>
+      });<br>
 }<br>
<br>
-template<typename Derived><br>
-QualType<br>
-TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,<br>
-                                                   FunctionProtoTypeLoc TL,<br>
-                                                   CXXRecordDecl *ThisContext,<br>
-                                                   unsigned ThisTypeQuals) {<br>
+template<typename Derived> template<typename Fn><br>
+QualType TreeTransform<Derived>::TransformFunctionProtoType(<br>
+    TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext,<br>
+    unsigned ThisTypeQuals, Fn TransformExceptionSpec) {<br>
   // Transform the parameters and return type.<br>
   //<br>
   // We are required to instantiate the params and return type in source order.<br>
@@ -4565,15 +4576,21 @@ TreeTransform<Derived>::TransformFunctio<br>
       return QualType();<br>
   }<br>
<br>
-  // FIXME: Need to transform the exception-specification too.<br>
+  FunctionProtoType::ExtProtoInfo EPI = T->getExtProtoInfo();<br>
+<br>
+  bool EPIChanged = false;<br>
+  if (TransformExceptionSpec(EPI.ExceptionSpec, EPIChanged))<br>
+    return QualType();<br>
+<br>
+  // FIXME: Need to transform ConsumedParameters for variadic template<br>
+  // expansion.<br>
<br>
   QualType Result = TL.getType();<br>
   if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType() ||<br>
       T->getNumParams() != ParamTypes.size() ||<br>
       !std::equal(T->param_type_begin(), T->param_type_end(),<br>
-                  ParamTypes.begin())) {<br>
-    Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes,<br>
-                                                   T->getExtProtoInfo());<br>
+                  ParamTypes.begin()) || EPIChanged) {<br>
+    Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, EPI);<br>
     if (Result.isNull())<br>
       return QualType();<br>
   }<br>
@@ -4590,6 +4607,107 @@ TreeTransform<Derived>::TransformFunctio<br>
 }<br>
<br>
 template<typename Derived><br>
+bool TreeTransform<Derived>::TransformExceptionSpec(<br>
+    SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI,<br>
+    SmallVectorImpl<QualType> &Exceptions, bool &Changed) {<br>
+  assert(ESI.Type != EST_Uninstantiated && ESI.Type != EST_Unevaluated);<br>
+<br>
+  // Instantiate a dynamic noexcept expression, if any.<br>
+  if (ESI.Type == EST_ComputedNoexcept) {<br>
+    EnterExpressionEvaluationContext Unevaluated(getSema(),<br>
+                                                 Sema::ConstantEvaluated);<br>
+    ExprResult NoexceptExpr = getDerived().TransformExpr(ESI.NoexceptExpr);<br>
+    if (NoexceptExpr.isInvalid())<br>
+      return true;<br>
+<br>
+    NoexceptExpr = getSema().CheckBooleanCondition(<br>
+        NoexceptExpr.get(), NoexceptExpr.get()->getLocStart());<br>
+    if (NoexceptExpr.isInvalid())<br>
+      return true;<br>
+<br>
+    if (!NoexceptExpr.get()->isValueDependent()) {<br>
+      NoexceptExpr = getSema().VerifyIntegerConstantExpression(<br>
+          NoexceptExpr.get(), nullptr,<br>
+          diag::err_noexcept_needs_constant_expression,<br>
+          /*AllowFold*/false);<br>
+      if (NoexceptExpr.isInvalid())<br>
+        return true;<br>
+    }<br>
+<br>
+    if (ESI.NoexceptExpr != NoexceptExpr.get())<br>
+      Changed = true;<br>
+    ESI.NoexceptExpr = NoexceptExpr.get();<br>
+  }<br>
+<br>
+  if (ESI.Type != EST_Dynamic)<br>
+    return false;<br>
+<br>
+  // Instantiate a dynamic exception specification's type.<br>
+  for (QualType T : ESI.Exceptions) {<br>
+    if (const PackExpansionType *PackExpansion =<br>
+            T->getAs<PackExpansionType>()) {<br>
+      Changed = true;<br>
+<br>
+      // We have a pack expansion. Instantiate it.<br>
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;<br>
+      SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),<br>
+                                              Unexpanded);<br>
+      assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");<br>
+<br>
+      // Determine whether the set of unexpanded parameter packs can and<br>
+      // should<br>
+      // be expanded.<br>
+      bool Expand = false;<br>
+      bool RetainExpansion = false;<br>
+      Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();<br>
+      // FIXME: Track the location of the ellipsis (and track source location<br>
+      // information for the types in the exception specification in general).<br>
+      if (getDerived().TryExpandParameterPacks(<br>
+              Loc, SourceRange(), Unexpanded, Expand,<br>
+              RetainExpansion, NumExpansions))<br>
+        return true;<br>
+<br>
+      if (!Expand) {<br>
+        // We can't expand this pack expansion into separate arguments yet;<br>
+        // just substitute into the pattern and create a new pack expansion<br>
+        // type.<br>
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);<br>
+        QualType U = getDerived().TransformType(PackExpansion->getPattern());<br>
+        if (U.isNull())<br>
+          return true;<br>
+<br>
+        U = SemaRef.Context.getPackExpansionType(U, NumExpansions);<br>
+        Exceptions.push_back(U);<br>
+        continue;<br>
+      }<br>
+<br>
+      // Substitute into the pack expansion pattern for each slice of the<br>
+      // pack.<br>
+      for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {<br>
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), ArgIdx);<br>
+<br>
+        QualType U = getDerived().TransformType(PackExpansion->getPattern());<br>
+        if (U.isNull() || SemaRef.CheckSpecifiedExceptionType(U, Loc))<br>
+          return true;<br>
+<br>
+        Exceptions.push_back(U);<br>
+      }<br>
+    } else {<br>
+      QualType U = getDerived().TransformType(T);<br>
+      if (U.isNull() || SemaRef.CheckSpecifiedExceptionType(U, Loc))<br>
+        return true;<br>
+      if (T != U)<br>
+        Changed = true;<br>
+<br>
+      Exceptions.push_back(U);<br>
+    }<br>
+  }<br>
+<br>
+  ESI.Exceptions = Exceptions;<br>
+  return false;<br>
+}<br>
+<br>
+template<typename Derived><br>
 QualType TreeTransform<Derived>::TransformFunctionNoProtoType(<br>
                                                  TypeLocBuilder &TLB,<br>
                                                  FunctionNoProtoTypeLoc TL) {<br>
@@ -8895,9 +9013,13 @@ TreeTransform<Derived>::TransformLambdaE<br>
     // transformed parameters.<br>
<br>
     TypeLocBuilder NewCallOpTLBuilder;<br>
-    QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder,<br>
-                                                        OldCallOpFPTL,<br>
-                                                        nullptr, 0);<br>
+    SmallVector<QualType, 4> ExceptionStorage;<br>
+    QualType NewCallOpType = TransformFunctionProtoType(<br>
+        NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0,<br>
+        [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {<br>
+          return TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,<br>
+                                        ExceptionStorage, Changed);<br>
+        });<br>
     NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,<br>
                                                         NewCallOpType);<br>
   }<br>
<br>
Modified: cfe/trunk/test/CXX/except/except.spec/p1.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p1.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p1.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/except/except.spec/p1.cpp (original)<br>
+++ cfe/trunk/test/CXX/except/except.spec/p1.cpp Wed Sep 17 18:57:05 2014<br>
@@ -77,5 +77,12 @@ namespace PR11084 {<br>
     static int f() noexcept(1/X) { return 10; }  // expected-error{{argument to noexcept specifier must be a constant expression}} expected-note{{division by zero}}<br>
   };<br>
<br>
-  void g() { A<0>::f(); } // expected-note{{in instantiation of exception specification for 'f' requested here}}<br>
+  template<int X> void f() {<br>
+    int (*p)() noexcept(1/X); // expected-error{{argument to noexcept specifier must be a constant expression}} expected-note{{division by zero}}<br>
+  };<br>
+<br>
+  void g() {<br>
+    A<0>::f(); // expected-note{{in instantiation of exception specification for 'f'}}<br>
+    f<0>(); // expected-note{{in instantiation of function template specialization}}<br>
+  }<br>
 }<br>
<br>
Modified: cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp (original)<br>
+++ cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp Wed Sep 17 18:57:05 2014<br>
@@ -137,3 +137,37 @@ namespace PR12763 {<br>
   };<br>
   void X::g() {} // expected-note {{in instantiation of}}<br>
 }<br>
+<br>
+namespace Variadic {<br>
+  template<bool B> void check() { static_assert(B, ""); }<br>
+  template<bool B, bool B2, bool ...Bs> void check() { static_assert(B, ""); check<B2, Bs...>(); }<br>
+<br>
+  template<typename ...T> void consume(T...);<br>
+<br>
+  template<typename ...T> void f(void (*...p)() throw (T)) {<br>
+    void (*q[])() = { p... };<br>
+    consume((p(),0)...);<br>
+  }<br>
+  template<bool ...B> void g(void (*...p)() noexcept (B)) {<br>
+    consume((p(),0)...);<br>
+    check<noexcept(p()) == B ...>();<br>
+  }<br>
+  template<typename ...T> void i() {<br>
+    consume([]() throw(T) {} ...);<br>
+    consume([]() noexcept(sizeof(T) == 4) {} ...);<br>
+  }<br>
+  template<bool ...B> void j() {<br>
+    consume([](void (*p)() noexcept(B)) {<br>
+      void (*q)() noexcept = p; // expected-error {{not superset of source}}<br>
+    } ...);<br>
+  }<br>
+<br>
+  void z() {<br>
+    f<int, char, double>(nullptr, nullptr, nullptr);<br>
+    g<true, false, true>(nullptr, nullptr, nullptr);<br>
+    i<int, long, short>();<br>
+    j<true, true>();<br>
+    j<true, false>(); // expected-note {{in instantiation of}}<br>
+  }<br>
+<br>
+}<br>
<br>
Modified: cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp?rev=217995&r1=217994&r2=217995&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp?rev=217995&r1=217994&r2=217995&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp (original)<br>
+++ cfe/trunk/test/SemaTemplate/instantiate-exception-spec.cpp Wed Sep 17 18:57:05 2014<br>
@@ -1,5 +1,7 @@<br>
-// RUN: %clang_cc1 -fsyntax-only -verify %s<br>
+// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -verify %s -DERRORS<br>
+// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -emit-llvm-only %s<br>
<br>
+#ifdef ERRORS<br>
 template<typename T> void f1(T*) throw(T); // expected-error{{incomplete type 'Incomplete' is not allowed in exception specification}}<br>
 struct Incomplete; // expected-note{{forward}}<br>
<br>
@@ -7,3 +9,20 @@ void test_f1(Incomplete *incomplete_p, i<br>
   f1(int_p);<br>
   f1(incomplete_p); // expected-note{{instantiation of}}<br>
 }<br>
+#endif<br>
+<br>
+template<typename T> void f(void (*p)() throw(T)) {<br>
+#ifdef ERRORS<br>
+  void (*q)() throw(char) = p; // expected-error {{target exception spec}}<br>
+<br>
+  extern void (*p2)() throw(T);<br>
+  void (*q2)() throw(char) = p2; // expected-error {{target exception spec}}<br>
+<br>
+  extern void (*p3)() throw(char);<br>
+  void (*q3)() throw(T) = p3; // expected-error {{target exception spec}}<br>
+<br>
+  void (*q4)() throw(T) = p2; // ok<br>
+#endif<br>
+  p();<br>
+}<br>
+void g() { f<int>(0); } // expected-note {{instantiation of}}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>