diff options
author | Hans Wennborg <hans@hanshq.net> | 2014-09-18 16:01:32 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2014-09-18 16:01:32 +0000 |
commit | e113c20c1d8834383c89ee395eb37887cd3919fe (patch) | |
tree | 9e6775c2d4e655b622ca637dcaa6b430324240a5 /clang/lib/Sema | |
parent | 6462f948847dc54ad498cb899fc8ec216a810bbd (diff) | |
download | bcm5719-llvm-e113c20c1d8834383c89ee395eb37887cd3919fe.tar.gz bcm5719-llvm-e113c20c1d8834383c89ee395eb37887cd3919fe.zip |
Revert r217995 and follow-ups:
r218053: Use exceptions() instead of getNumExceptions()/getExceptionType() to avoid
r218011: Work around MSVC parser bug by putting redundant braces around the body of
r217997: Skip parens when detecting whether we're instantiating a function declaration.
r217995: Instantiate exception specifications when instantiating function types (other
The Windows build was broken for 16 hours and no one had any good ideas of how to
fix it. Reverting for now to make the builders green. See the cfe-commits thread [1] for
more info.
This was the build error (from [2]):
C:\bb-win7\ninja-clang-i686-msc17-R\llvm-project\clang\lib\Sema\SemaTemplateInstantiate.cpp(1590) : error C2668: '`anonymous-namespace'::TemplateInstantiator::TransformFunctionProtoType' : ambiguous call to overloaded function
C:\bb-win7\ninja-clang-i686-msc17-R\llvm-project\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>
]
c:\bb-win7\ninja-clang-i686-msc17-r\llvm-project\clang\lib\sema\TreeTransform.h(4532): or 'clang::QualType clang::TreeTransform<Derived>::TransformFunctionProtoType<clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>>(clang::TypeLocBuilder &,clang::FunctionProtoTypeLoc,clang::CXXRecordDecl *,unsigned int,Fn)'
with
[
Derived=`anonymous-namespace'::TemplateInstantiator,
Fn=clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>
]
while trying to match the argument list '(clang::TypeLocBuilder, clang::FunctionProtoTypeLoc, clang::CXXRecordDecl *, unsigned int, clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>)'
1. http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20140915/115011.html
2. http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/10515/steps/build_clang_tools_1/logs/stdio
llvm-svn: 218058
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExceptionSpec.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 60 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 168 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 156 |
6 files changed, 191 insertions, 252 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index a03e308f99b..006a3c49d7c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13051,12 +13051,13 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) { return false; } -void Sema::checkExceptionSpecification( - bool IsTopLevel, ExceptionSpecificationType EST, - ArrayRef<ParsedType> DynamicExceptions, - ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr, - SmallVectorImpl<QualType> &Exceptions, - FunctionProtoType::ExceptionSpecInfo &ESI) { +void +Sema::checkExceptionSpecification(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) { @@ -13065,15 +13066,13 @@ void Sema::checkExceptionSpecification( // FIXME: Preserve type source info. QualType ET = GetTypeFromParser(DynamicExceptions[ei]); - if (IsTopLevel) { - SmallVector<UnexpandedParameterPack, 2> Unexpanded; - collectUnexpandedParameterPacks(ET, Unexpanded); - if (!Unexpanded.empty()) { - DiagnoseUnexpandedParameterPacks( - DynamicExceptionRanges[ei].getBegin(), UPPC_ExceptionType, - Unexpanded); - continue; - } + 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 @@ -13092,8 +13091,7 @@ void Sema::checkExceptionSpecification( NoexceptExpr->getType()->getCanonicalTypeUnqualified() == Context.BoolTy) && "Parser should have made sure that the expression is boolean"); - if (IsTopLevel && NoexceptExpr && - DiagnoseUnexpandedParameterPack(NoexceptExpr)) { + if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) { ESI.Type = EST_BasicNoexcept; return; } diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 4e4de5a3e7f..e4963b13d64 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -720,11 +720,10 @@ static bool CheckSpecForTypesEquivalent(Sema &S, /// 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(), @@ -745,30 +744,23 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &NoteID, 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 || ToFunc->hasDependentExceptionSpec()) + if (!ToFunc) return false; // SourceType must be a function or function pointer. const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType()); - if (!FromFunc || FromFunc->hasDependentExceptionSpec()) + if (!FromFunc) 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(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 25b2802f029..f44780407ba 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -788,14 +788,12 @@ namespace { /// pack. ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E); - // Pull in the base class overload; it just forwards to our function. - using inherited::TransformFunctionProtoType; - template<typename Fn> + QualType TransformFunctionProtoType(TypeLocBuilder &TLB, + FunctionProtoTypeLoc TL); QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - unsigned ThisTypeQuals, - Fn TransformExceptionSpec); + unsigned ThisTypeQuals); ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, @@ -1309,16 +1307,21 @@ ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( E->getParam()); } -template<typename Fn> +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); +} + QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - unsigned ThisTypeQuals, - Fn TransformExceptionSpec) { + unsigned ThisTypeQuals) { // We need a local instantiation scope for this function prototype. LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); - return inherited::TransformFunctionProtoType( - TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec); + return inherited::TransformFunctionProtoType(TLB, TL, ThisContext, + ThisTypeQuals); } ParmVarDecl * @@ -1553,8 +1556,7 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) { /// 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 and to avoid -/// instantiating an exception-specification. +/// instantiation of default-argument expressions. TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &Args, SourceLocation Loc, @@ -1577,17 +1579,9 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, QualType Result; - if (FunctionProtoTypeLoc Proto = - TL.IgnoreParens().getAs<FunctionProtoTypeLoc>()) { - // 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; }); + if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { + Result = Instantiator.TransformFunctionProtoType(TLB, Proto, ThisContext, + ThisTypeQuals); } else { Result = Instantiator.TransformType(TLB, TL); } @@ -1597,26 +1591,6 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, 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, diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index ddd47ee1e3c..62a3e11ac9a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2988,7 +2988,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, /// Introduce the instantiated function parameters into the local /// instantiation scope, and set the parameter names to those used /// in the template. -static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, +static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, const FunctionDecl *PatternDecl, LocalInstantiationScope &Scope, const MultiLevelTemplateArgumentList &TemplateArgs) { @@ -2999,22 +2999,15 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, // 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. Substitute into the type from the pattern, in case - // it's instantiation-dependent. + // per core issue 1668. // FIXME: Updating the type to work around this is at best fragile. - if (!PatternDecl->getType()->isDependentType()) { - QualType T = S.SubstType(PatternParam->getType(), TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); - if (T.isNull()) - return true; - FunctionParam->setType(T); - } + if (!PatternDecl->getType()->isDependentType()) + FunctionParam->setType(PatternParam->getType()); + FunctionParam->setDeclName(PatternParam->getDeclName()); Scope.InstantiatedLocal(PatternParam, FunctionParam); ++FParamIdx; continue; @@ -3026,27 +3019,136 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, = 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()); - if (!PatternDecl->getType()->isDependentType()) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg); - QualType T = S.SubstType(PatternType, TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->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 (T.isNull()) - return true; - FunctionParam->setType(T); + break; + + T = SemaRef.Context.getPackExpansionType(T, NumExpansions); + Exceptions.push_back(T); + continue; } - Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); - ++FParamIdx; + // 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); + } + + 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(); } } - return false; + FunctionProtoType::ExceptionSpecInfo ESI; + ESI.Type = Proto->getExceptionSpecType(); + ESI.Exceptions = Exceptions; + ESI.NoexceptExpr = NoexceptExpr; + + SemaRef.UpdateExceptionSpec(New, ESI); } void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, @@ -3073,14 +3175,11 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true); FunctionDecl *Template = Proto->getExceptionSpecTemplate(); - if (addInstantiatedParametersToScope(*this, Decl, Template, Scope, - TemplateArgs)) { - UpdateExceptionSpec(Decl, EST_None); - return; - } + addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs); - SubstExceptionSpec(Decl, Template->getType()->castAs<FunctionProtoType>(), - TemplateArgs); + ::InstantiateExceptionSpec(*this, Decl, + Template->getType()->castAs<FunctionProtoType>(), + TemplateArgs); } /// \brief Initializes the common fields of an instantiation function @@ -3149,7 +3248,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, New->setType(SemaRef.Context.getFunctionType( NewProto->getReturnType(), NewProto->getParamTypes(), EPI)); } else { - SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs); + ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs); } } @@ -3339,9 +3438,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl); - if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope, - TemplateArgs)) - return; + addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope, + TemplateArgs); // If this is a constructor, instantiate the member initializers. if (const CXXConstructorDecl *Ctor = diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 76649a8acb6..51f36feaa46 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2989,8 +2989,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, NoexceptExpr = FTI.NoexceptExpr; } - S.checkExceptionSpecification(D.isFunctionDeclarationContext(), - FTI.getExceptionSpecType(), + S.checkExceptionSpecification(FTI.getExceptionSpecType(), DynamicExceptions, DynamicExceptionRanges, NoexceptExpr, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 07ce0273e1e..92baa0ebd22 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -542,17 +542,10 @@ 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, - Fn TransformExceptionSpec); - - bool TransformExceptionSpec(SourceLocation Loc, - FunctionProtoType::ExceptionSpecInfo &ESI, - SmallVectorImpl<QualType> &Exceptions, - bool &Changed); + unsigned ThisTypeQuals); StmtResult TransformSEHHandler(Stmt *Handler); @@ -4519,19 +4512,15 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL) { - 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> template<typename Fn> -QualType TreeTransform<Derived>::TransformFunctionProtoType( - TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext, - unsigned ThisTypeQuals, Fn TransformExceptionSpec) { + return getDerived().TransformFunctionProtoType(TLB, TL, nullptr, 0); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, + FunctionProtoTypeLoc TL, + CXXRecordDecl *ThisContext, + unsigned ThisTypeQuals) { // Transform the parameters and return type. // // We are required to instantiate the params and return type in source order. @@ -4576,21 +4565,15 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType( return QualType(); } - FunctionProtoType::ExtProtoInfo EPI = T->getExtProtoInfo(); - - bool EPIChanged = false; - if (TransformExceptionSpec(EPI.ExceptionSpec, EPIChanged)) - return QualType(); - - // FIXME: Need to transform ConsumedParameters for variadic template - // expansion. + // FIXME: Need to transform the exception-specification too. 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()) || EPIChanged) { - Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, EPI); + ParamTypes.begin())) { + Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, + T->getExtProtoInfo()); if (Result.isNull()) return QualType(); } @@ -4607,107 +4590,6 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType( } 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) { @@ -9024,13 +8906,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // transformed parameters. TypeLocBuilder NewCallOpTLBuilder; - SmallVector<QualType, 4> ExceptionStorage; - QualType NewCallOpType = TransformFunctionProtoType( - NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0, - [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { - return TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI, - ExceptionStorage, Changed); - }); + QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder, + OldCallOpFPTL, + nullptr, 0); NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType); } |