Instead of storing an ASTContext* in FunctionProtoTypes with computed noexcept specifiers, unique FunctionProtoTypes with a ContextualFoldingSet, as suggested by John McCall.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127568 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sebastian Redl 2011-03-13 17:09:40 +00:00
Родитель 0b34dbaafe
Коммит 8026f6d82f
13 изменённых файлов: 44 добавлений и 58 удалений

Просмотреть файл

@ -96,7 +96,8 @@ class ASTContext {
DependentSizedExtVectorTypes; DependentSizedExtVectorTypes;
mutable llvm::FoldingSet<VectorType> VectorTypes; mutable llvm::FoldingSet<VectorType> VectorTypes;
mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
mutable llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&>
FunctionProtoTypes;
mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;

Просмотреть файл

@ -1090,7 +1090,7 @@ public:
/// has a non-throwing exception-specification. The '03 rule is /// has a non-throwing exception-specification. The '03 rule is
/// identical except that the definition of a non-throwing /// identical except that the definition of a non-throwing
/// exception specification is just "is it throw()?". /// exception specification is just "is it throw()?".
bool shouldNullCheckAllocation() const; bool shouldNullCheckAllocation(ASTContext &Ctx) const;
FunctionDecl *getOperatorNew() const { return OperatorNew; } FunctionDecl *getOperatorNew() const { return OperatorNew; }
void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; }

Просмотреть файл

@ -2430,8 +2430,7 @@ private:
} }
FunctionProtoType(QualType result, const QualType *args, unsigned numArgs, FunctionProtoType(QualType result, const QualType *args, unsigned numArgs,
QualType canonical, const ExtProtoInfo &epi, QualType canonical, const ExtProtoInfo &epi);
const ASTContext *Context);
/// NumArgs - The number of arguments this function has, not counting '...'. /// NumArgs - The number of arguments this function has, not counting '...'.
unsigned NumArgs : 20; unsigned NumArgs : 20;
@ -2451,16 +2450,6 @@ private:
/// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing /// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing
/// to the expression in the noexcept() specifier. /// to the expression in the noexcept() specifier.
/// Context - If there is a NoexceptExpr, we need to store a pointer to the
/// ASTContext as well. We do it right after NoexceptExpr.
const ASTContext *getContext() const {
// Context sits after NoexceptExpr, one pointer past where the arguments end
if(getExceptionSpecType() == EST_ComputedNoexcept)
return *(reinterpret_cast<const ASTContext *const *>(arg_type_end()) + 1);
return 0;
}
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
public: public:
@ -2511,7 +2500,7 @@ public:
NR_Nothrow ///< The noexcept specifier evaluates to true. NR_Nothrow ///< The noexcept specifier evaluates to true.
}; };
/// \brief Get the meaning of the noexcept spec on this function, if any. /// \brief Get the meaning of the noexcept spec on this function, if any.
NoexceptResult getNoexceptSpec() const; NoexceptResult getNoexceptSpec(ASTContext &Ctx) const;
unsigned getNumExceptions() const { return NumExceptions; } unsigned getNumExceptions() const { return NumExceptions; }
QualType getExceptionType(unsigned i) const { QualType getExceptionType(unsigned i) const {
assert(i < NumExceptions && "Invalid exception number!"); assert(i < NumExceptions && "Invalid exception number!");
@ -2523,13 +2512,13 @@ public:
// NoexceptExpr sits where the arguments end. // NoexceptExpr sits where the arguments end.
return *reinterpret_cast<Expr *const *>(arg_type_end()); return *reinterpret_cast<Expr *const *>(arg_type_end());
} }
bool isNothrow() const { bool isNothrow(ASTContext &Ctx) const {
ExceptionSpecificationType EST = getExceptionSpecType(); ExceptionSpecificationType EST = getExceptionSpecType();
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
return true; return true;
if (EST != EST_ComputedNoexcept) if (EST != EST_ComputedNoexcept)
return false; return false;
return getNoexceptSpec() == NR_Nothrow; return getNoexceptSpec(Ctx) == NR_Nothrow;
} }
using FunctionType::isVariadic; using FunctionType::isVariadic;
@ -2575,10 +2564,10 @@ public:
} }
static bool classof(const FunctionProtoType *) { return true; } static bool classof(const FunctionProtoType *) { return true; }
void Profile(llvm::FoldingSetNodeID &ID); void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys, unsigned NumArgs, arg_type_iterator ArgTys, unsigned NumArgs,
const ExtProtoInfo &EPI, const ASTContext *Context); const ExtProtoInfo &EPI, const ASTContext &Context);
}; };

Просмотреть файл

@ -195,6 +195,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
IdentifierTable &idents, SelectorTable &sels, IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins, Builtin::Context &builtins,
unsigned size_reserve) : unsigned size_reserve) :
FunctionProtoTypes(this_()),
TemplateSpecializationTypes(this_()), TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()),
GlobalNestedNameSpecifier(0), IsInt128Installed(false), GlobalNestedNameSpecifier(0), IsInt128Installed(false),
@ -1909,7 +1910,7 @@ ASTContext::getFunctionType(QualType ResultTy,
// Unique functions, to guarantee there is only one function of a particular // Unique functions, to guarantee there is only one function of a particular
// structure. // structure.
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, this); FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, *this);
void *InsertPos = 0; void *InsertPos = 0;
if (FunctionProtoType *FTP = if (FunctionProtoType *FTP =
@ -1960,13 +1961,12 @@ ASTContext::getFunctionType(QualType ResultTy,
if (EPI.ExceptionSpecType == EST_Dynamic) if (EPI.ExceptionSpecType == EST_Dynamic)
Size += EPI.NumExceptions * sizeof(QualType); Size += EPI.NumExceptions * sizeof(QualType);
else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
Size += sizeof(Expr*) + sizeof(ASTContext*); Size += sizeof(Expr*);
} }
FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment);
FunctionProtoType::ExtProtoInfo newEPI = EPI; FunctionProtoType::ExtProtoInfo newEPI = EPI;
newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv); newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv);
new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI, new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI);
this);
Types.push_back(FTP); Types.push_back(FTP);
FunctionProtoTypes.InsertNode(FTP, InsertPos); FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0); return QualType(FTP, 0);

Просмотреть файл

@ -1629,7 +1629,7 @@ static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) {
return R; return R;
} }
static Expr::CanThrowResult CanCalleeThrow(const Decl *D, static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Decl *D,
bool NullThrows = true) { bool NullThrows = true) {
if (!D) if (!D)
return NullThrows ? Expr::CT_Can : Expr::CT_Cannot; return NullThrows ? Expr::CT_Can : Expr::CT_Cannot;
@ -1659,7 +1659,7 @@ static Expr::CanThrowResult CanCalleeThrow(const Decl *D,
if (!FT) if (!FT)
return Expr::CT_Can; return Expr::CT_Can;
return FT->isNothrow() ? Expr::CT_Cannot : Expr::CT_Can; return FT->isNothrow(Ctx) ? Expr::CT_Cannot : Expr::CT_Can;
} }
static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) { static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) {
@ -1723,7 +1723,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
case CallExprClass: case CallExprClass:
case CXXOperatorCallExprClass: case CXXOperatorCallExprClass:
case CXXMemberCallExprClass: { case CXXMemberCallExprClass: {
CanThrowResult CT = CanCalleeThrow(cast<CallExpr>(this)->getCalleeDecl()); CanThrowResult CT = CanCalleeThrow(C,cast<CallExpr>(this)->getCalleeDecl());
if (CT == CT_Can) if (CT == CT_Can)
return CT; return CT;
return MergeCanThrow(CT, CanSubExprsThrow(C, this)); return MergeCanThrow(CT, CanSubExprsThrow(C, this));
@ -1731,7 +1731,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
case CXXConstructExprClass: case CXXConstructExprClass:
case CXXTemporaryObjectExprClass: { case CXXTemporaryObjectExprClass: {
CanThrowResult CT = CanCalleeThrow( CanThrowResult CT = CanCalleeThrow(C,
cast<CXXConstructExpr>(this)->getConstructor()); cast<CXXConstructExpr>(this)->getConstructor());
if (CT == CT_Can) if (CT == CT_Can)
return CT; return CT;
@ -1740,8 +1740,8 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
case CXXNewExprClass: { case CXXNewExprClass: {
CanThrowResult CT = MergeCanThrow( CanThrowResult CT = MergeCanThrow(
CanCalleeThrow(cast<CXXNewExpr>(this)->getOperatorNew()), CanCalleeThrow(C, cast<CXXNewExpr>(this)->getOperatorNew()),
CanCalleeThrow(cast<CXXNewExpr>(this)->getConstructor(), CanCalleeThrow(C, cast<CXXNewExpr>(this)->getConstructor(),
/*NullThrows*/false)); /*NullThrows*/false));
if (CT == CT_Can) if (CT == CT_Can)
return CT; return CT;
@ -1749,7 +1749,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
} }
case CXXDeleteExprClass: { case CXXDeleteExprClass: {
CanThrowResult CT = CanCalleeThrow( CanThrowResult CT = CanCalleeThrow(C,
cast<CXXDeleteExpr>(this)->getOperatorDelete()); cast<CXXDeleteExpr>(this)->getOperatorDelete());
if (CT == CT_Can) if (CT == CT_Can)
return CT; return CT;
@ -1759,7 +1759,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
Arg = Cast->getSubExpr(); Arg = Cast->getSubExpr();
if (const PointerType *PT = Arg->getType()->getAs<PointerType>()) { if (const PointerType *PT = Arg->getType()->getAs<PointerType>()) {
if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) { if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) {
CanThrowResult CT2 = CanCalleeThrow( CanThrowResult CT2 = CanCalleeThrow(C,
cast<CXXRecordDecl>(RT->getDecl())->getDestructor()); cast<CXXRecordDecl>(RT->getDecl())->getDestructor());
if (CT2 == CT_Can) if (CT2 == CT_Can)
return CT2; return CT2;
@ -1771,7 +1771,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
case CXXBindTemporaryExprClass: { case CXXBindTemporaryExprClass: {
// The bound temporary has to be destroyed again, which might throw. // The bound temporary has to be destroyed again, which might throw.
CanThrowResult CT = CanCalleeThrow( CanThrowResult CT = CanCalleeThrow(C,
cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor()); cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor());
if (CT == CT_Can) if (CT == CT_Can)
return CT; return CT;

Просмотреть файл

@ -100,9 +100,9 @@ void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray,
SubExprs = new (C) Stmt*[TotalSize]; SubExprs = new (C) Stmt*[TotalSize];
} }
bool CXXNewExpr::shouldNullCheckAllocation() const { bool CXXNewExpr::shouldNullCheckAllocation(ASTContext &Ctx) const {
return getOperatorNew()->getType()-> return getOperatorNew()->getType()->
castAs<FunctionProtoType>()->isNothrow(); castAs<FunctionProtoType>()->isNothrow(Ctx);
} }
// CXXDeleteExpr // CXXDeleteExpr

Просмотреть файл

@ -1166,8 +1166,7 @@ llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) {
FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
unsigned numArgs, QualType canonical, unsigned numArgs, QualType canonical,
const ExtProtoInfo &epi, const ExtProtoInfo &epi)
const ASTContext *context)
: FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals, : FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals,
epi.RefQualifier, canonical, epi.RefQualifier, canonical,
result->isDependentType(), result->isDependentType(),
@ -1205,14 +1204,11 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
// Store the noexcept expression and context. // Store the noexcept expression and context.
Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + numArgs); Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + numArgs);
*noexSlot = epi.NoexceptExpr; *noexSlot = epi.NoexceptExpr;
const ASTContext **contextSlot = const_cast<const ASTContext**>(
reinterpret_cast<ASTContext**>(noexSlot + 1));
*contextSlot = context;
} }
} }
FunctionProtoType::NoexceptResult FunctionProtoType::NoexceptResult
FunctionProtoType::getNoexceptSpec() const { FunctionProtoType::getNoexceptSpec(ASTContext &ctx) const {
ExceptionSpecificationType est = getExceptionSpecType(); ExceptionSpecificationType est = getExceptionSpecType();
if (est == EST_BasicNoexcept) if (est == EST_BasicNoexcept)
return NR_Nothrow; return NR_Nothrow;
@ -1227,7 +1223,6 @@ FunctionProtoType::getNoexceptSpec() const {
return NR_Dependent; return NR_Dependent;
llvm::APSInt value; llvm::APSInt value;
ASTContext& ctx = const_cast<ASTContext&>(*getContext());
bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, 0, bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, 0,
/*evaluated*/false); /*evaluated*/false);
(void)isICE; (void)isICE;
@ -1247,7 +1242,7 @@ bool FunctionProtoType::isTemplateVariadic() const {
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
const QualType *ArgTys, unsigned NumArgs, const QualType *ArgTys, unsigned NumArgs,
const ExtProtoInfo &epi, const ExtProtoInfo &epi,
const ASTContext *Context) { const ASTContext &Context) {
ID.AddPointer(Result.getAsOpaquePtr()); ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i) for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr()); ID.AddPointer(ArgTys[i].getAsOpaquePtr());
@ -1259,14 +1254,15 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
for (unsigned i = 0; i != epi.NumExceptions; ++i) for (unsigned i = 0; i != epi.NumExceptions; ++i)
ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr()); ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
} else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){ } else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){
epi.NoexceptExpr->Profile(ID, *Context, true); epi.NoexceptExpr->Profile(ID, Context, true);
} }
epi.ExtInfo.Profile(ID); epi.ExtInfo.Profile(ID);
} }
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) { void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Ctx) {
Profile(ID, getResultType(), arg_type_begin(), NumArgs, getExtProtoInfo(), Profile(ID, getResultType(), arg_type_begin(), NumArgs, getExtProtoInfo(),
getContext()); Ctx);
} }
QualType TypedefType::desugar() const { QualType TypedefType::desugar() const {

Просмотреть файл

@ -1118,7 +1118,7 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
return Block; return Block;
} }
static bool CanThrow(Expr *E) { static bool CanThrow(Expr *E, ASTContext &Ctx) {
QualType Ty = E->getType(); QualType Ty = E->getType();
if (Ty->isFunctionPointerType()) if (Ty->isFunctionPointerType())
Ty = Ty->getAs<PointerType>()->getPointeeType(); Ty = Ty->getAs<PointerType>()->getPointeeType();
@ -1128,7 +1128,7 @@ static bool CanThrow(Expr *E) {
const FunctionType *FT = Ty->getAs<FunctionType>(); const FunctionType *FT = Ty->getAs<FunctionType>();
if (FT) { if (FT) {
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
if (Proto->isNothrow()) if (Proto->isNothrow(Ctx))
return false; return false;
} }
return true; return true;
@ -1156,7 +1156,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
AddEHEdge = false; AddEHEdge = false;
} }
if (!CanThrow(C->getCallee())) if (!CanThrow(C->getCallee(), *Context))
AddEHEdge = false; AddEHEdge = false;
if (!NoReturn && !AddEHEdge) if (!NoReturn && !AddEHEdge)

Просмотреть файл

@ -709,7 +709,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
FuncAttrs |= llvm::Attribute::NoUnwind; FuncAttrs |= llvm::Attribute::NoUnwind;
else if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { else if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>(); const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>();
if (FPT && FPT->isNothrow()) if (FPT && FPT->isNothrow(getContext()))
FuncAttrs |= llvm::Attribute::NoUnwind; FuncAttrs |= llvm::Attribute::NoUnwind;
} }

Просмотреть файл

@ -982,7 +982,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// exception spec; for this part, we inline // exception spec; for this part, we inline
// CXXNewExpr::shouldNullCheckAllocation()) and we have an // CXXNewExpr::shouldNullCheckAllocation()) and we have an
// interesting initializer. // interesting initializer.
bool nullCheck = allocatorType->isNothrow() && bool nullCheck = allocatorType->isNothrow(getContext()) &&
!(allocType->isPODType() && !E->hasInitializer()); !(allocType->isPODType() && !E->hasInitializer());
llvm::BasicBlock *nullCheckBB = 0; llvm::BasicBlock *nullCheckBB = 0;

Просмотреть файл

@ -3091,7 +3091,7 @@ namespace {
// Check out noexcept specs. // Check out noexcept specs.
if (EST == EST_ComputedNoexcept) { if (EST == EST_ComputedNoexcept) {
FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(); FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(Context);
assert(NR != FunctionProtoType::NR_NoNoexcept && assert(NR != FunctionProtoType::NR_NoNoexcept &&
"Must have noexcept result for EST_ComputedNoexcept."); "Must have noexcept result for EST_ComputedNoexcept.");
assert(NR != FunctionProtoType::NR_Dependent && assert(NR != FunctionProtoType::NR_Dependent &&

Просмотреть файл

@ -313,8 +313,8 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (OldEST == EST_None && NewEST == EST_None) if (OldEST == EST_None && NewEST == EST_None)
return false; return false;
FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(); FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context);
FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(); FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context);
if (OldNR == FunctionProtoType::NR_BadNoexcept || if (OldNR == FunctionProtoType::NR_BadNoexcept ||
NewNR == FunctionProtoType::NR_BadNoexcept) NewNR == FunctionProtoType::NR_BadNoexcept)
return false; return false;
@ -460,7 +460,7 @@ bool Sema::CheckExceptionSpecSubset(
// omissions we make here. // omissions we make here.
// We also shortcut checking if a noexcept expression was bad. // We also shortcut checking if a noexcept expression was bad.
FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(); FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context);
if (SuperNR == FunctionProtoType::NR_BadNoexcept || if (SuperNR == FunctionProtoType::NR_BadNoexcept ||
SuperNR == FunctionProtoType::NR_Dependent) SuperNR == FunctionProtoType::NR_Dependent)
return false; return false;
@ -479,7 +479,7 @@ bool Sema::CheckExceptionSpecSubset(
return true; return true;
} }
FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(); FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context);
if (SubNR == FunctionProtoType::NR_BadNoexcept || if (SubNR == FunctionProtoType::NR_BadNoexcept ||
SubNR == FunctionProtoType::NR_Dependent) SubNR == FunctionProtoType::NR_Dependent)
return false; return false;

Просмотреть файл

@ -2423,7 +2423,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
FoundAssign = true; FoundAssign = true;
const FunctionProtoType *CPT const FunctionProtoType *CPT
= Operator->getType()->getAs<FunctionProtoType>(); = Operator->getType()->getAs<FunctionProtoType>();
if (!CPT->isNothrow()) { if (!CPT->isNothrow(Self.Context)) {
AllNoThrow = false; AllNoThrow = false;
break; break;
} }
@ -2465,7 +2465,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
= Constructor->getType()->getAs<FunctionProtoType>(); = Constructor->getType()->getAs<FunctionProtoType>();
// FIXME: check whether evaluating default arguments can throw. // FIXME: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw. // For now, we'll be conservative and assume that they can throw.
if (!CPT->isNothrow() || CPT->getNumArgs() > 1) { if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) {
AllNoThrow = false; AllNoThrow = false;
break; break;
} }
@ -2500,7 +2500,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
= Constructor->getType()->getAs<FunctionProtoType>(); = Constructor->getType()->getAs<FunctionProtoType>();
// TODO: check whether evaluating default arguments can throw. // TODO: check whether evaluating default arguments can throw.
// For now, we'll be conservative and assume that they can throw. // For now, we'll be conservative and assume that they can throw.
return CPT->isNothrow() && CPT->getNumArgs() == 0; return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
} }
} }
} }