зеркало из https://github.com/microsoft/clang.git
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:
Родитель
0b34dbaafe
Коммит
8026f6d82f
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче