From: Richard Smith Date: Thu, 31 Jul 2014 21:57:55 +0000 (+0000) Subject: Factor out exception specification information from X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=06266415660bdbbd2b8b41ce83def93b98dd69ec;p=clang Factor out exception specification information from FunctionProtoType::ExtProtoInfo. Most of the users of these fields don't care about the other ExtProtoInfo bits and just want to talk about the exception specification. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@214450 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 09862e4fb7..f4109efb2a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2844,33 +2844,51 @@ public: /// type. class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { public: + struct ExceptionSpecInfo { + ExceptionSpecInfo() + : Type(EST_None), NoexceptExpr(nullptr), + SourceDecl(nullptr), SourceTemplate(nullptr) {} + + ExceptionSpecInfo(ExceptionSpecificationType EST) + : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr), + SourceTemplate(nullptr) {} + + /// The kind of exception specification this is. + ExceptionSpecificationType Type; + /// Explicitly-specified list of exception types. + ArrayRef Exceptions; + /// Noexcept expression, if this is EST_ComputedNoexcept. + Expr *NoexceptExpr; + /// The function whose exception specification this is, for + /// EST_Unevaluated and EST_Uninstantiated. + FunctionDecl *SourceDecl; + /// The function template whose exception specification this is instantiated + /// from, for EST_Uninstantiated. + FunctionDecl *SourceTemplate; + }; + /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { ExtProtoInfo() : Variadic(false), HasTrailingReturn(false), TypeQuals(0), - ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), - Exceptions(nullptr), NoexceptExpr(nullptr), - ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), - ConsumedParameters(nullptr) {} + RefQualifier(RQ_None), ConsumedParameters(nullptr) {} ExtProtoInfo(CallingConv CC) : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), - ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), - Exceptions(nullptr), NoexceptExpr(nullptr), - ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), - ConsumedParameters(nullptr) {} + RefQualifier(RQ_None), ConsumedParameters(nullptr) {} + + ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) { + ExtProtoInfo Result(*this); + Result.ExceptionSpec = O; + return Result; + } FunctionType::ExtInfo ExtInfo; bool Variadic : 1; bool HasTrailingReturn : 1; unsigned char TypeQuals; - ExceptionSpecificationType ExceptionSpecType; RefQualifierKind RefQualifier; - unsigned NumExceptions; - const QualType *Exceptions; - Expr *NoexceptExpr; - FunctionDecl *ExceptionSpecDecl; - FunctionDecl *ExceptionSpecTemplate; + ExceptionSpecInfo ExceptionSpec; const bool *ConsumedParameters; }; @@ -2960,19 +2978,18 @@ public: EPI.ExtInfo = getExtInfo(); EPI.Variadic = isVariadic(); EPI.HasTrailingReturn = hasTrailingReturn(); - EPI.ExceptionSpecType = getExceptionSpecType(); + EPI.ExceptionSpec.Type = getExceptionSpecType(); EPI.TypeQuals = static_cast(getTypeQuals()); EPI.RefQualifier = getRefQualifier(); - if (EPI.ExceptionSpecType == EST_Dynamic) { - EPI.NumExceptions = NumExceptions; - EPI.Exceptions = exception_begin(); - } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { - EPI.NoexceptExpr = getNoexceptExpr(); - } else if (EPI.ExceptionSpecType == EST_Uninstantiated) { - EPI.ExceptionSpecDecl = getExceptionSpecDecl(); - EPI.ExceptionSpecTemplate = getExceptionSpecTemplate(); - } else if (EPI.ExceptionSpecType == EST_Unevaluated) { - EPI.ExceptionSpecDecl = getExceptionSpecDecl(); + if (EPI.ExceptionSpec.Type == EST_Dynamic) { + EPI.ExceptionSpec.Exceptions = exceptions(); + } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { + EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr(); + } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { + EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); + EPI.ExceptionSpec.SourceTemplate = getExceptionSpecTemplate(); + } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { + EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); } if (hasAnyConsumedParams()) EPI.ConsumedParameters = getConsumedParamsBuffer(); @@ -3074,10 +3091,9 @@ public: } typedef const QualType *exception_iterator; - typedef llvm::iterator_range exception_range; - exception_range exceptions() const { - return exception_range(exception_begin(), exception_end()); + ArrayRef exceptions() const { + return llvm::makeArrayRef(exception_begin(), exception_end()); } exception_iterator exception_begin() const { // exceptions begin where arguments end diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 477a03c034..59a5e5dd4f 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1181,7 +1181,7 @@ public: const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT); void UpdateExceptionSpec(FunctionDecl *FD, - const FunctionProtoType::ExtProtoInfo &EPI); + const FunctionProtoType::ExceptionSpecInfo &ESI); bool CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); @@ -3934,24 +3934,20 @@ public: /// \brief Overwrite an EPI's exception specification with this /// computed exception specification. - void getEPI(FunctionProtoType::ExtProtoInfo &EPI) const { - EPI.ExceptionSpecType = getExceptionSpecType(); - if (EPI.ExceptionSpecType == EST_Dynamic) { - EPI.NumExceptions = size(); - EPI.Exceptions = data(); - } else if (EPI.ExceptionSpecType == EST_None) { + FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const { + FunctionProtoType::ExceptionSpecInfo ESI; + ESI.Type = getExceptionSpecType(); + if (ESI.Type == EST_Dynamic) { + ESI.Exceptions = Exceptions; + } else if (ESI.Type == EST_None) { /// C++11 [except.spec]p14: /// The exception-specification is noexcept(false) if the set of /// potential exceptions of the special member function contains "any" - EPI.ExceptionSpecType = EST_ComputedNoexcept; - EPI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(), + ESI.Type = EST_ComputedNoexcept; + ESI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(), tok::kw_false).get(); } - } - FunctionProtoType::ExtProtoInfo getEPI() const { - FunctionProtoType::ExtProtoInfo EPI; - getEPI(EPI); - return EPI; + return ESI; } }; @@ -3998,13 +3994,13 @@ public: void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD); /// \brief Check the given exception-specification and update the - /// extended prototype information with the results. + /// exception specification information with the results. void checkExceptionSpecification(ExceptionSpecificationType EST, ArrayRef DynamicExceptions, ArrayRef DynamicExceptionRanges, Expr *NoexceptExpr, SmallVectorImpl &Exceptions, - FunctionProtoType::ExtProtoInfo &EPI); + FunctionProtoType::ExceptionSpecInfo &ESI); /// \brief Determine if a special member function should have a deleted /// definition when it is defaulted. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 7c53a5373d..f43d51b715 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1142,7 +1142,7 @@ private: QualType readTypeRecord(unsigned Index); void readExceptionSpec(ModuleFile &ModuleFile, SmallVectorImpl &ExceptionStorage, - FunctionProtoType::ExtProtoInfo &EPI, + FunctionProtoType::ExceptionSpecInfo &ESI, const RecordData &Record, unsigned &Index); RecordLocation TypeCursorForIndex(unsigned Index); void LoadedDecl(unsigned Index, Decl *D); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 220b61dbe0..7a309603b4 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2846,7 +2846,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef ArgArray, // Determine whether the type being created is already canonical or not. bool isCanonical = - EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) && + EPI.ExceptionSpec.Type == EST_None && isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn; for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) @@ -2863,8 +2863,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef ArgArray, FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; CanonicalEPI.HasTrailingReturn = false; - CanonicalEPI.ExceptionSpecType = EST_None; - CanonicalEPI.NumExceptions = 0; + CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); // Result types do not have ARC lifetime qualifiers. QualType CanResultTy = getCanonicalType(ResultTy); @@ -2892,13 +2891,13 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef ArgArray, // specification. size_t Size = sizeof(FunctionProtoType) + NumArgs * sizeof(QualType); - if (EPI.ExceptionSpecType == EST_Dynamic) { - Size += EPI.NumExceptions * sizeof(QualType); - } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + if (EPI.ExceptionSpec.Type == EST_Dynamic) { + Size += EPI.ExceptionSpec.Exceptions.size() * sizeof(QualType); + } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { Size += sizeof(Expr*); - } else if (EPI.ExceptionSpecType == EST_Uninstantiated) { + } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { Size += 2 * sizeof(FunctionDecl*); - } else if (EPI.ExceptionSpecType == EST_Unevaluated) { + } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { Size += sizeof(FunctionDecl*); } if (EPI.ConsumedParameters) diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index df7a2cb471..ac3c652d47 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -914,13 +914,13 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { if (const FunctionProtoType *FPT = D->getType()->getAs()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - switch (EPI.ExceptionSpecType) { + switch (EPI.ExceptionSpec.Type) { default: break; case EST_Unevaluated: - OS << " noexcept-unevaluated " << EPI.ExceptionSpecDecl; + OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl; break; case EST_Uninstantiated: - OS << " noexcept-uninstantiated " << EPI.ExceptionSpecTemplate; + OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate; break; } } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index b0e0b1dc9e..395a4884e4 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1622,15 +1622,14 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ToEPI.HasTrailingReturn = FromEPI.HasTrailingReturn; ToEPI.TypeQuals = FromEPI.TypeQuals; ToEPI.RefQualifier = FromEPI.RefQualifier; - ToEPI.NumExceptions = ExceptionTypes.size(); - ToEPI.Exceptions = ExceptionTypes.data(); - ToEPI.ConsumedParameters = FromEPI.ConsumedParameters; - ToEPI.ExceptionSpecType = FromEPI.ExceptionSpecType; - ToEPI.NoexceptExpr = Importer.Import(FromEPI.NoexceptExpr); - ToEPI.ExceptionSpecDecl = cast_or_null( - Importer.Import(FromEPI.ExceptionSpecDecl)); - ToEPI.ExceptionSpecTemplate = cast_or_null( - Importer.Import(FromEPI.ExceptionSpecTemplate)); + ToEPI.ExceptionSpec.Type = FromEPI.ExceptionSpec.Type; + ToEPI.ExceptionSpec.Exceptions = ExceptionTypes; + ToEPI.ExceptionSpec.NoexceptExpr = + Importer.Import(FromEPI.ExceptionSpec.NoexceptExpr); + ToEPI.ExceptionSpec.SourceDecl = cast_or_null( + Importer.Import(FromEPI.ExceptionSpec.SourceDecl)); + ToEPI.ExceptionSpec.SourceTemplate = cast_or_null( + Importer.Import(FromEPI.ExceptionSpec.SourceTemplate)); return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI); } @@ -2712,8 +2711,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // FunctionDecl that we are importing the FunctionProtoType for. // To avoid an infinite recursion when importing, create the FunctionDecl // with a simplified function type and update it afterwards. - if (FromEPI.ExceptionSpecDecl || FromEPI.ExceptionSpecTemplate || - FromEPI.NoexceptExpr) { + if (FromEPI.ExceptionSpec.SourceDecl || + FromEPI.ExceptionSpec.SourceTemplate || + FromEPI.ExceptionSpec.NoexceptExpr) { FunctionProtoType::ExtProtoInfo DefaultEPI; FromTy = Importer.getFromContext().getFunctionType( FromFPT->getReturnType(), FromFPT->getParamTypes(), DefaultEPI); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1677874302..1d05c1024c 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1596,8 +1596,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, result->isInstantiationDependentType(), result->isVariablyModifiedType(), result->containsUnexpandedParameterPack(), epi.ExtInfo), - NumParams(params.size()), NumExceptions(epi.NumExceptions), - ExceptionSpecType(epi.ExceptionSpecType), + NumParams(params.size()), + NumExceptions(epi.ExceptionSpec.Exceptions.size()), + ExceptionSpecType(epi.ExceptionSpec.Type), HasAnyConsumedParams(epi.ConsumedParameters != nullptr), Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn), RefQualifier(epi.RefQualifier) { @@ -1620,27 +1621,28 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, if (getExceptionSpecType() == EST_Dynamic) { // Fill in the exception array. QualType *exnSlot = argSlot + NumParams; - for (unsigned i = 0, e = epi.NumExceptions; i != e; ++i) { - if (epi.Exceptions[i]->isDependentType()) + unsigned I = 0; + for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) { + if (ExceptionType->isDependentType()) setDependent(); - else if (epi.Exceptions[i]->isInstantiationDependentType()) + else if (ExceptionType->isInstantiationDependentType()) setInstantiationDependent(); - - if (epi.Exceptions[i]->containsUnexpandedParameterPack()) + + if (ExceptionType->containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); - exnSlot[i] = epi.Exceptions[i]; + exnSlot[I++] = ExceptionType; } } else if (getExceptionSpecType() == EST_ComputedNoexcept) { // Store the noexcept expression and context. Expr **noexSlot = reinterpret_cast(argSlot + NumParams); - *noexSlot = epi.NoexceptExpr; - - if (epi.NoexceptExpr) { - if (epi.NoexceptExpr->isValueDependent() - || epi.NoexceptExpr->isTypeDependent()) + *noexSlot = epi.ExceptionSpec.NoexceptExpr; + + if (epi.ExceptionSpec.NoexceptExpr) { + if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() + || epi.ExceptionSpec.NoexceptExpr->isTypeDependent()) setDependent(); - else if (epi.NoexceptExpr->isInstantiationDependent()) + else if (epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent()) setInstantiationDependent(); } } else if (getExceptionSpecType() == EST_Uninstantiated) { @@ -1648,8 +1650,8 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, // exception specification. FunctionDecl **slot = reinterpret_cast(argSlot + NumParams); - slot[0] = epi.ExceptionSpecDecl; - slot[1] = epi.ExceptionSpecTemplate; + slot[0] = epi.ExceptionSpec.SourceDecl; + slot[1] = epi.ExceptionSpec.SourceTemplate; // This exception specification doesn't make the type dependent, because // it's not instantiated as part of instantiating the type. } else if (getExceptionSpecType() == EST_Unevaluated) { @@ -1657,7 +1659,7 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef params, // exception specification. FunctionDecl **slot = reinterpret_cast(argSlot + NumParams); - slot[0] = epi.ExceptionSpecDecl; + slot[0] = epi.ExceptionSpec.SourceDecl; } if (epi.ConsumedParameters) { @@ -1755,20 +1757,21 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, assert(!(unsigned(epi.Variadic) & ~1) && !(unsigned(epi.TypeQuals) & ~255) && !(unsigned(epi.RefQualifier) & ~3) && - !(unsigned(epi.ExceptionSpecType) & ~7) && + !(unsigned(epi.ExceptionSpec.Type) & ~7) && "Values larger than expected."); ID.AddInteger(unsigned(epi.Variadic) + (epi.TypeQuals << 1) + (epi.RefQualifier << 9) + - (epi.ExceptionSpecType << 11)); - if (epi.ExceptionSpecType == EST_Dynamic) { - for (unsigned i = 0; i != epi.NumExceptions; ++i) - ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr()); - } else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){ - epi.NoexceptExpr->Profile(ID, Context, false); - } else if (epi.ExceptionSpecType == EST_Uninstantiated || - epi.ExceptionSpecType == EST_Unevaluated) { - ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl()); + (epi.ExceptionSpec.Type << 11)); + if (epi.ExceptionSpec.Type == EST_Dynamic) { + for (QualType Ex : epi.ExceptionSpec.Exceptions) + ID.AddPointer(Ex.getAsOpaquePtr()); + } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept && + epi.ExceptionSpec.NoexceptExpr) { + epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, false); + } else if (epi.ExceptionSpec.Type == EST_Uninstantiated || + epi.ExceptionSpec.Type == EST_Unevaluated) { + ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl()); } if (epi.ConsumedParameters) { for (unsigned i = 0; i != NumParams; ++i) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d24cf6a7be..59953dc9e6 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7110,12 +7110,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, const FunctionProtoType *FPT = R->getAs(); if ((Name.getCXXOverloadedOperator() == OO_Delete || Name.getCXXOverloadedOperator() == OO_Array_Delete) && - getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) { - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.ExceptionSpecType = EST_BasicNoexcept; - NewFD->setType(Context.getFunctionType(FPT->getReturnType(), - FPT->getParamTypes(), EPI)); - } + getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) + NewFD->setType(Context.getFunctionType( + FPT->getReturnType(), FPT->getParamTypes(), + FPT->getExtProtoInfo().withExceptionSpec(EST_BasicNoexcept))); } // Filter out previous declarations that don't match the scope. diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 8a760a8267..77285edbc0 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4818,8 +4818,8 @@ static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S, FunctionProtoType::ExtProtoInfo EPI; // Build an exception specification pointing back at this member. - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = MD; + EPI.ExceptionSpec.Type = EST_Unevaluated; + EPI.ExceptionSpec.SourceDecl = MD; // Set the calling convention to the default for C++ instance methods. EPI.ExtInfo = EPI.ExtInfo.withCallingConv( @@ -4834,14 +4834,10 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) return; // Evaluate the exception specification. - ImplicitExceptionSpecification ExceptSpec = - computeImplicitExceptionSpec(*this, Loc, MD); - - FunctionProtoType::ExtProtoInfo EPI; - ExceptSpec.getEPI(EPI); + auto ESI = computeImplicitExceptionSpec(*this, Loc, MD).getExceptionSpec(); // Update the type of the special member to use it. - UpdateExceptionSpec(MD, EPI); + UpdateExceptionSpec(MD, ESI); // A user-provided destructor can be defined outside the class. When that // happens, be sure to update the exception specification on both @@ -4849,7 +4845,7 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) const FunctionProtoType *CanonicalFPT = MD->getCanonicalDecl()->getType()->castAs(); if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated) - UpdateExceptionSpec(MD->getCanonicalDecl(), EPI); + UpdateExceptionSpec(MD->getCanonicalDecl(), ESI); } void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { @@ -4995,8 +4991,8 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // -- it is implicitly considered to have the same exception-specification // as if it had been implicitly declared, FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = MD; + EPI.ExceptionSpec.Type = EST_Unevaluated; + EPI.ExceptionSpec.SourceDecl = MD; MD->setType(Context.getFunctionType(ReturnType, ArrayRef(&ArgType, ExpectedParams), @@ -5030,7 +5026,8 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false, /*IsCXXMethod=*/true); FunctionProtoType::ExtProtoInfo EPI(CC); - computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI); + EPI.ExceptionSpec = computeImplicitExceptionSpec(*this, MD->getLocation(), MD) + .getExceptionSpec(); const FunctionProtoType *ImplicitType = cast( Context.getFunctionType(Context.VoidTy, None, EPI)); @@ -8744,8 +8741,8 @@ private: // Build an unevaluated exception specification for this constructor. const FunctionProtoType *FPT = DerivedType->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = DerivedCtor; + EPI.ExceptionSpec.Type = EST_Unevaluated; + EPI.ExceptionSpec.SourceDecl = DerivedCtor; DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI)); @@ -9002,8 +8999,8 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, // the only thing of interest in the destructor type is its extended info. // The return and arguments are fixed. FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo(); - EPI.ExceptionSpecType = EST_Unevaluated; - EPI.ExceptionSpecDecl = Destructor; + EPI.ExceptionSpec.Type = EST_Unevaluated; + EPI.ExceptionSpec.SourceDecl = Destructor; Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); // FIXME: If the destructor has a body that could throw, and the newly created @@ -12981,9 +12978,9 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST, ArrayRef DynamicExceptionRanges, Expr *NoexceptExpr, SmallVectorImpl &Exceptions, - FunctionProtoType::ExtProtoInfo &EPI) { + FunctionProtoType::ExceptionSpecInfo &ESI) { Exceptions.clear(); - EPI.ExceptionSpecType = EST; + ESI.Type = EST; if (EST == EST_Dynamic) { Exceptions.reserve(DynamicExceptions.size()); for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) { @@ -13004,11 +13001,10 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST, if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei])) Exceptions.push_back(ET); } - EPI.NumExceptions = Exceptions.size(); - EPI.Exceptions = Exceptions.data(); + ESI.Exceptions = Exceptions; return; } - + if (EST == EST_ComputedNoexcept) { // If an error occurred, there's no expression here. if (NoexceptExpr) { @@ -13017,15 +13013,15 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST, Context.BoolTy) && "Parser should have made sure that the expression is boolean"); if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) { - EPI.ExceptionSpecType = EST_BasicNoexcept; + ESI.Type = EST_BasicNoexcept; return; } - + if (!NoexceptExpr->isValueDependent()) NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, nullptr, diag::err_noexcept_needs_constant_expression, /*AllowFold*/ false).get(); - EPI.NoexceptExpr = NoexceptExpr; + ESI.NoexceptExpr = NoexceptExpr; } return; } diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index b92fcbd2a0..192b273c7c 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -132,21 +132,19 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { return SourceDecl->getType()->castAs(); } -void Sema::UpdateExceptionSpec(FunctionDecl *FD, - const FunctionProtoType::ExtProtoInfo &EPI) { - const FunctionProtoType *Proto = FD->getType()->castAs(); +void +Sema::UpdateExceptionSpec(FunctionDecl *FD, + const FunctionProtoType::ExceptionSpecInfo &ESI) { + const FunctionProtoType *Proto = + FD->getType()->castAs(); // Overwrite the exception spec and rebuild the function type. - FunctionProtoType::ExtProtoInfo NewEPI = Proto->getExtProtoInfo(); - NewEPI.ExceptionSpecType = EPI.ExceptionSpecType; - NewEPI.NumExceptions = EPI.NumExceptions; - NewEPI.Exceptions = EPI.Exceptions; - NewEPI.NoexceptExpr = EPI.NoexceptExpr; - FD->setType(Context.getFunctionType(Proto->getReturnType(), - Proto->getParamTypes(), NewEPI)); + FD->setType(Context.getFunctionType( + Proto->getReturnType(), Proto->getParamTypes(), + Proto->getExtProtoInfo().withExceptionSpec(ESI))); // If we've fully resolved the exception specification, notify listeners. - if (!isUnresolvedExceptionSpec(EPI.ExceptionSpecType)) + if (!isUnresolvedExceptionSpec(ESI.Type)) if (auto *Listener = getASTMutationListener()) Listener->ResolvedExceptionSpec(FD); } @@ -227,32 +225,28 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { (Old->getLocation().isInvalid() || Context.getSourceManager().isInSystemHeader(Old->getLocation())) && Old->isExternC()) { - FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); - EPI.ExceptionSpecType = EST_DynamicNone; - QualType NewType = Context.getFunctionType(NewProto->getReturnType(), - NewProto->getParamTypes(), EPI); - New->setType(NewType); + New->setType(Context.getFunctionType( + NewProto->getReturnType(), NewProto->getParamTypes(), + NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone))); return false; } const FunctionProtoType *OldProto = Old->getType()->castAs(); - FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); - EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); - if (EPI.ExceptionSpecType == EST_Dynamic) { - EPI.NumExceptions = OldProto->getNumExceptions(); - EPI.Exceptions = OldProto->exception_begin(); - } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType(); + if (ESI.Type == EST_Dynamic) { + ESI.Exceptions = OldProto->exceptions(); + } else if (ESI.Type == EST_ComputedNoexcept) { // FIXME: We can't just take the expression from the old prototype. It // likely contains references to the old prototype's parameters. } // Update the type of the function with the appropriate exception // specification. - QualType NewType = Context.getFunctionType(NewProto->getReturnType(), - NewProto->getParamTypes(), EPI); - New->setType(NewType); + New->setType(Context.getFunctionType( + NewProto->getReturnType(), NewProto->getParamTypes(), + NewProto->getExtProtoInfo().withExceptionSpec(ESI))); // Warn about the lack of exception specification. SmallString<128> ExceptionSpecString; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 425297cdb3..eb7924f473 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2072,13 +2072,12 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, if (!getLangOpts().CPlusPlus11) { BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); assert(StdBadAlloc && "Must have std::bad_alloc declared"); - EPI.ExceptionSpecType = EST_Dynamic; - EPI.NumExceptions = 1; - EPI.Exceptions = &BadAllocType; + EPI.ExceptionSpec.Type = EST_Dynamic; + EPI.ExceptionSpec.Exceptions = llvm::makeArrayRef(BadAllocType); } } else { - EPI.ExceptionSpecType = getLangOpts().CPlusPlus11 ? - EST_BasicNoexcept : EST_DynamicNone; + EPI.ExceptionSpec = + getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone; } QualType Params[] = { Param1, Param2 }; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 06170b5e3a..d0997ccb2b 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -735,8 +735,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // FIXME: Calling convention! FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_C); - EPI.ExceptionSpecType = EST_None; - EPI.NumExceptions = 0; + EPI.ExceptionSpec = EST_None; QualType ExpectedType = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), None, EPI); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index accec95bf7..cddd5b188d 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3131,13 +3131,12 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New, } } - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExceptionSpecType = Proto->getExceptionSpecType(); - EPI.NumExceptions = Exceptions.size(); - EPI.Exceptions = Exceptions.data(); - EPI.NoexceptExpr = NoexceptExpr; + FunctionProtoType::ExceptionSpecInfo ESI; + ESI.Type = Proto->getExceptionSpecType(); + ESI.Exceptions = Exceptions; + ESI.NoexceptExpr = NoexceptExpr; - SemaRef.UpdateExceptionSpec(New, EPI); + SemaRef.UpdateExceptionSpec(New, ESI); } void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, @@ -3151,9 +3150,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, if (Inst.isInvalid()) { // We hit the instantiation depth limit. Clear the exception specification // so that our callers don't have to cope with EST_Uninstantiated. - FunctionProtoType::ExtProtoInfo EPI; - EPI.ExceptionSpecType = EST_None; - UpdateExceptionSpec(Decl, EPI); + UpdateExceptionSpec(Decl, EST_None); return; } @@ -3218,14 +3215,14 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, // DR1330: In C++11, defer instantiation of a non-trivial // exception specification. if (SemaRef.getLangOpts().CPlusPlus11 && - EPI.ExceptionSpecType != EST_None && - EPI.ExceptionSpecType != EST_DynamicNone && - EPI.ExceptionSpecType != EST_BasicNoexcept) { + EPI.ExceptionSpec.Type != EST_None && + EPI.ExceptionSpec.Type != EST_DynamicNone && + EPI.ExceptionSpec.Type != EST_BasicNoexcept) { FunctionDecl *ExceptionSpecTemplate = Tmpl; - if (EPI.ExceptionSpecType == EST_Uninstantiated) - ExceptionSpecTemplate = EPI.ExceptionSpecTemplate; + if (EPI.ExceptionSpec.Type == EST_Uninstantiated) + ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate; ExceptionSpecificationType NewEST = EST_Uninstantiated; - if (EPI.ExceptionSpecType == EST_Unevaluated) + if (EPI.ExceptionSpec.Type == EST_Unevaluated) NewEST = EST_Unevaluated; // Mark the function has having an uninstantiated exception specification. @@ -3233,9 +3230,9 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, = New->getType()->getAs(); assert(NewProto && "Template instantiation without function prototype?"); EPI = NewProto->getExtProtoInfo(); - EPI.ExceptionSpecType = NewEST; - EPI.ExceptionSpecDecl = New; - EPI.ExceptionSpecTemplate = ExceptionSpecTemplate; + EPI.ExceptionSpec.Type = NewEST; + EPI.ExceptionSpec.SourceDecl = New; + EPI.ExceptionSpec.SourceTemplate = ExceptionSpecTemplate; New->setType(SemaRef.Context.getFunctionType( NewProto->getReturnType(), NewProto->getParamTypes(), EPI)); } else { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 47df3a69aa..b6b024c89a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2994,7 +2994,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, DynamicExceptionRanges, NoexceptExpr, Exceptions, - EPI); + EPI.ExceptionSpec); T = Context.getFunctionType(T, ParamTys, EPI); } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 2ae05adea4..2423785157 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -5268,7 +5268,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) { EPI.TypeQuals = Record[Idx++]; EPI.RefQualifier = static_cast(Record[Idx++]); SmallVector ExceptionStorage; - readExceptionSpec(*Loc.F, ExceptionStorage, EPI, Record, Idx); + readExceptionSpec(*Loc.F, ExceptionStorage, EPI.ExceptionSpec, Record, Idx); unsigned NumParams = Record[Idx++]; SmallVector ParamTypes; @@ -5537,24 +5537,22 @@ QualType ASTReader::readTypeRecord(unsigned Index) { void ASTReader::readExceptionSpec(ModuleFile &ModuleFile, SmallVectorImpl &Exceptions, - FunctionProtoType::ExtProtoInfo &EPI, + FunctionProtoType::ExceptionSpecInfo &ESI, const RecordData &Record, unsigned &Idx) { ExceptionSpecificationType EST = static_cast(Record[Idx++]); - EPI.ExceptionSpecType = EST; + ESI.Type = EST; if (EST == EST_Dynamic) { - EPI.NumExceptions = Record[Idx++]; - for (unsigned I = 0; I != EPI.NumExceptions; ++I) + for (unsigned I = 0, N = Record[Idx++]; I != N; ++I) Exceptions.push_back(readType(ModuleFile, Record, Idx)); - EPI.Exceptions = Exceptions.data(); + ESI.Exceptions = Exceptions; } else if (EST == EST_ComputedNoexcept) { - EPI.NoexceptExpr = ReadExpr(ModuleFile); + ESI.NoexceptExpr = ReadExpr(ModuleFile); } else if (EST == EST_Uninstantiated) { - EPI.ExceptionSpecDecl = ReadDeclAs(ModuleFile, Record, Idx); - EPI.ExceptionSpecTemplate = - ReadDeclAs(ModuleFile, Record, Idx); + ESI.SourceDecl = ReadDeclAs(ModuleFile, Record, Idx); + ESI.SourceTemplate = ReadDeclAs(ModuleFile, Record, Idx); } else if (EST == EST_Unevaluated) { - EPI.ExceptionSpecDecl = ReadDeclAs(ModuleFile, Record, Idx); + ESI.SourceDecl = ReadDeclAs(ModuleFile, Record, Idx); } } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 44214f8209..f68284b9dd 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -3290,11 +3290,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, case UPD_CXX_RESOLVED_EXCEPTION_SPEC: { auto *FD = cast(D); auto *FPT = FD->getType()->castAs(); - auto EPI = FPT->getExtProtoInfo(); SmallVector ExceptionStorage; - Reader.readExceptionSpec(ModuleFile, ExceptionStorage, EPI, Record, Idx); - FD->setType(Reader.Context.getFunctionType(FPT->getReturnType(), - FPT->getParamTypes(), EPI)); + FunctionProtoType::ExceptionSpecInfo ESI; + Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx); + FD->setType(Reader.Context.getFunctionType( + FPT->getReturnType(), FPT->getParamTypes(), + FPT->getExtProtoInfo().withExceptionSpec(ESI))); break; }