r217995 - Instantiate exception specifications when instantiating function types (other

Bataev, Alexey a.bataev at hotmail.com
Wed Sep 17 20:19:39 PDT 2014


+    for (const auto &E : T->exceptions())
+      TRY_TO(TraverseType(E));

You just need to enclose the body of this loop into braces.

Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team
Intel Corp.

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140918/7937272a/attachment.html>


More information about the cfe-commits mailing list