r217995 - Instantiate exception specifications when instantiating function types (other
Richard Smith
richard at metafoo.co.uk
Wed Sep 17 20:59:26 PDT 2014
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
>>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140917/ed7fdac2/attachment.html>
More information about the cfe-commits
mailing list