r217995 - Instantiate exception specifications when instantiating function types (other

Reid Kleckner rnk at google.com
Wed Sep 17 20:10:53 PDT 2014


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>
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
> 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/20140917/4f56bf2e/attachment.html>


More information about the cfe-commits mailing list