r217995 - Instantiate exception specifications when instantiating function types (other

Yaron Keren yaron.keren at gmail.com
Thu Sep 18 05:23:44 PDT 2014


Didn't work here either, MSVC 2013 update 2, same error as Timur.


2014-09-18 12:56 GMT+03:00 Timur Iskhodzhanov <timurrrr at google.com>:

> I don't think it worked:
> ..\tools\clang\lib\Sema\SemaTemplateInstantiate.cpp(1590) : error C2668:
> 'clang::TreeTransform<`anonymous-namespace'::TemplateInstantiator>::TransformFunctionProtoType'
> :
>  ambiguous call to overloaded function
>         ..\tools\clang\lib\Sema\SemaTemplateInstantiate.cpp(1313): could
> be 'clang::QualType
> `anonymous-namespace'::TemplateInstantiator::TransformFunctionProtoType<clang
> ::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>>(clang::TypeLocBuilder
> &,clang::FunctionProtoTypeLoc,clang::CXXRecordDecl *,unsigned int,Fn)'
>         with
>         [
>
> Fn=clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>
>         ]
>         d:\src\llvm-trunk\tools\clang\lib\sema\TreeTransform.h(4532): or
>     'clang::QualType
> clang::TreeTransform<`anonymous-namespace'::TemplateInstantiator>::Transfo
> rmFunctionProtoType<clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>>(clang::TypeLocBuilder
> &,clang::FunctionProtoTypeLoc,clang::CXXRecordDec
> l *,unsigned int,Fn)'
>         with
>         [
>
> Fn=clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>
>         ]
>         while trying to match the argument list '(clang::TypeLocBuilder,
> clang::FunctionProtoTypeLoc, clang::CXXRecordDecl *, unsigned int,
> clang::Sema::SubstFunctionDecl
> Type::<lambda_756edcbe7bd5c7584849a6e3a1491735>)'
>
> 2014-09-18 7:59 GMT+04:00 Richard Smith <richard at metafoo.co.uk>:
>
>> Thanks, should be fixed in r218011.
>>
>> On Wed, Sep 17, 2014 at 8:19 PM, Bataev, Alexey <a.bataev at hotmail.com>
>> wrote:
>>
>>>  +    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> 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
>>>>
>>>
>>>
>>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
>>
>
> _______________________________________________
> 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/20140918/33a18f30/attachment.html>


More information about the cfe-commits mailing list