From: Sebastian Redl Date: Sun, 13 Mar 2011 17:09:40 +0000 (+0000) Subject: Instead of storing an ASTContext* in FunctionProtoTypes with computed noexcept specif... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8026f6d82f7fa544bc0453714fe94bca62a1196e;p=clang 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 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index c0eeb5af38..2f2cc9a3e1 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -96,7 +96,8 @@ class ASTContext { DependentSizedExtVectorTypes; mutable llvm::FoldingSet VectorTypes; mutable llvm::FoldingSet FunctionNoProtoTypes; - mutable llvm::FoldingSet FunctionProtoTypes; + mutable llvm::ContextualFoldingSet + FunctionProtoTypes; mutable llvm::FoldingSet DependentTypeOfExprTypes; mutable llvm::FoldingSet DependentDecltypeTypes; mutable llvm::FoldingSet TemplateTypeParmTypes; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 1f9b3b7228..30481ba779 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1090,7 +1090,7 @@ public: /// has a non-throwing exception-specification. The '03 rule is /// identical except that the definition of a non-throwing /// exception specification is just "is it throw()?". - bool shouldNullCheckAllocation() const; + bool shouldNullCheckAllocation(ASTContext &Ctx) const; FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 6d5ca71ed4..963f4b5543 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2430,8 +2430,7 @@ private: } FunctionProtoType(QualType result, const QualType *args, unsigned numArgs, - QualType canonical, const ExtProtoInfo &epi, - const ASTContext *Context); + QualType canonical, const ExtProtoInfo &epi); /// NumArgs - The number of arguments this function has, not counting '...'. unsigned NumArgs : 20; @@ -2451,16 +2450,6 @@ private: /// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing /// 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(arg_type_end()) + 1); - return 0; - } - friend class ASTContext; // ASTContext creates these. public: @@ -2511,7 +2500,7 @@ public: NR_Nothrow ///< The noexcept specifier evaluates to true. }; /// \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; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); @@ -2523,13 +2512,13 @@ public: // NoexceptExpr sits where the arguments end. return *reinterpret_cast(arg_type_end()); } - bool isNothrow() const { + bool isNothrow(ASTContext &Ctx) const { ExceptionSpecificationType EST = getExceptionSpecType(); if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) return true; if (EST != EST_ComputedNoexcept) return false; - return getNoexceptSpec() == NR_Nothrow; + return getNoexceptSpec(Ctx) == NR_Nothrow; } using FunctionType::isVariadic; @@ -2575,10 +2564,10 @@ public: } 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, arg_type_iterator ArgTys, unsigned NumArgs, - const ExtProtoInfo &EPI, const ASTContext *Context); + const ExtProtoInfo &EPI, const ASTContext &Context); }; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c128ce598b..0526ebb5cb 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -195,6 +195,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, unsigned size_reserve) : + FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), GlobalNestedNameSpecifier(0), IsInt128Installed(false), @@ -1909,7 +1910,7 @@ ASTContext::getFunctionType(QualType ResultTy, // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; - FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, this); + FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, *this); void *InsertPos = 0; if (FunctionProtoType *FTP = @@ -1960,13 +1961,12 @@ ASTContext::getFunctionType(QualType ResultTy, if (EPI.ExceptionSpecType == EST_Dynamic) Size += EPI.NumExceptions * sizeof(QualType); else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { - Size += sizeof(Expr*) + sizeof(ASTContext*); + Size += sizeof(Expr*); } FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv); - new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI, - this); + new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI); Types.push_back(FTP); FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 1c7807e6d2..9c4444225e 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1629,7 +1629,7 @@ static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) { return R; } -static Expr::CanThrowResult CanCalleeThrow(const Decl *D, +static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Decl *D, bool NullThrows = true) { if (!D) return NullThrows ? Expr::CT_Can : Expr::CT_Cannot; @@ -1659,7 +1659,7 @@ static Expr::CanThrowResult CanCalleeThrow(const Decl *D, if (!FT) 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) { @@ -1723,7 +1723,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CallExprClass: case CXXOperatorCallExprClass: case CXXMemberCallExprClass: { - CanThrowResult CT = CanCalleeThrow(cast(this)->getCalleeDecl()); + CanThrowResult CT = CanCalleeThrow(C,cast(this)->getCalleeDecl()); if (CT == CT_Can) return CT; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); @@ -1731,7 +1731,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CXXConstructExprClass: case CXXTemporaryObjectExprClass: { - CanThrowResult CT = CanCalleeThrow( + CanThrowResult CT = CanCalleeThrow(C, cast(this)->getConstructor()); if (CT == CT_Can) return CT; @@ -1740,8 +1740,8 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CXXNewExprClass: { CanThrowResult CT = MergeCanThrow( - CanCalleeThrow(cast(this)->getOperatorNew()), - CanCalleeThrow(cast(this)->getConstructor(), + CanCalleeThrow(C, cast(this)->getOperatorNew()), + CanCalleeThrow(C, cast(this)->getConstructor(), /*NullThrows*/false)); if (CT == CT_Can) return CT; @@ -1749,7 +1749,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { } case CXXDeleteExprClass: { - CanThrowResult CT = CanCalleeThrow( + CanThrowResult CT = CanCalleeThrow(C, cast(this)->getOperatorDelete()); if (CT == CT_Can) return CT; @@ -1759,7 +1759,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { Arg = Cast->getSubExpr(); if (const PointerType *PT = Arg->getType()->getAs()) { if (const RecordType *RT = PT->getPointeeType()->getAs()) { - CanThrowResult CT2 = CanCalleeThrow( + CanThrowResult CT2 = CanCalleeThrow(C, cast(RT->getDecl())->getDestructor()); if (CT2 == CT_Can) return CT2; @@ -1771,7 +1771,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case CXXBindTemporaryExprClass: { // The bound temporary has to be destroyed again, which might throw. - CanThrowResult CT = CanCalleeThrow( + CanThrowResult CT = CanCalleeThrow(C, cast(this)->getTemporary()->getDestructor()); if (CT == CT_Can) return CT; diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index fd94dd108d..35c2d41008 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -100,9 +100,9 @@ void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, SubExprs = new (C) Stmt*[TotalSize]; } -bool CXXNewExpr::shouldNullCheckAllocation() const { +bool CXXNewExpr::shouldNullCheckAllocation(ASTContext &Ctx) const { return getOperatorNew()->getType()-> - castAs()->isNothrow(); + castAs()->isNothrow(Ctx); } // CXXDeleteExpr diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index eb5254e96e..1e2a6c48fd 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1166,8 +1166,7 @@ llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) { FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, unsigned numArgs, QualType canonical, - const ExtProtoInfo &epi, - const ASTContext *context) + const ExtProtoInfo &epi) : FunctionType(FunctionProto, result, epi.Variadic, epi.TypeQuals, epi.RefQualifier, canonical, result->isDependentType(), @@ -1205,14 +1204,11 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args, // Store the noexcept expression and context. Expr **noexSlot = reinterpret_cast(argSlot + numArgs); *noexSlot = epi.NoexceptExpr; - const ASTContext **contextSlot = const_cast( - reinterpret_cast(noexSlot + 1)); - *contextSlot = context; } } FunctionProtoType::NoexceptResult -FunctionProtoType::getNoexceptSpec() const { +FunctionProtoType::getNoexceptSpec(ASTContext &ctx) const { ExceptionSpecificationType est = getExceptionSpecType(); if (est == EST_BasicNoexcept) return NR_Nothrow; @@ -1227,7 +1223,6 @@ FunctionProtoType::getNoexceptSpec() const { return NR_Dependent; llvm::APSInt value; - ASTContext& ctx = const_cast(*getContext()); bool isICE = noexceptExpr->isIntegerConstantExpr(value, ctx, 0, /*evaluated*/false); (void)isICE; @@ -1247,7 +1242,7 @@ bool FunctionProtoType::isTemplateVariadic() const { void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result, const QualType *ArgTys, unsigned NumArgs, const ExtProtoInfo &epi, - const ASTContext *Context) { + const ASTContext &Context) { ID.AddPointer(Result.getAsOpaquePtr()); for (unsigned i = 0; i != NumArgs; ++i) 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) ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr()); } else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){ - epi.NoexceptExpr->Profile(ID, *Context, true); + epi.NoexceptExpr->Profile(ID, Context, true); } 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(), - getContext()); + Ctx); } QualType TypedefType::desugar() const { diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 8f8c475d35..4772a69b4a 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1118,7 +1118,7 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { return Block; } -static bool CanThrow(Expr *E) { +static bool CanThrow(Expr *E, ASTContext &Ctx) { QualType Ty = E->getType(); if (Ty->isFunctionPointerType()) Ty = Ty->getAs()->getPointeeType(); @@ -1128,7 +1128,7 @@ static bool CanThrow(Expr *E) { const FunctionType *FT = Ty->getAs(); if (FT) { if (const FunctionProtoType *Proto = dyn_cast(FT)) - if (Proto->isNothrow()) + if (Proto->isNothrow(Ctx)) return false; } return true; @@ -1156,7 +1156,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { AddEHEdge = false; } - if (!CanThrow(C->getCallee())) + if (!CanThrow(C->getCallee(), *Context)) AddEHEdge = false; if (!NoReturn && !AddEHEdge) diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index d72e6dc429..15ab6b080b 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -709,7 +709,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, FuncAttrs |= llvm::Attribute::NoUnwind; else if (const FunctionDecl *Fn = dyn_cast(TargetDecl)) { const FunctionProtoType *FPT = Fn->getType()->getAs(); - if (FPT && FPT->isNothrow()) + if (FPT && FPT->isNothrow(getContext())) FuncAttrs |= llvm::Attribute::NoUnwind; } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index c9c8a6a35d..32d1928b44 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -982,7 +982,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // exception spec; for this part, we inline // CXXNewExpr::shouldNullCheckAllocation()) and we have an // interesting initializer. - bool nullCheck = allocatorType->isNothrow() && + bool nullCheck = allocatorType->isNothrow(getContext()) && !(allocType->isPODType() && !E->hasInitializer()); llvm::BasicBlock *nullCheckBB = 0; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f6551054c1..04c21bc47c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3091,7 +3091,7 @@ namespace { // Check out noexcept specs. if (EST == EST_ComputedNoexcept) { - FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(); + FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(Context); assert(NR != FunctionProtoType::NR_NoNoexcept && "Must have noexcept result for EST_ComputedNoexcept."); assert(NR != FunctionProtoType::NR_Dependent && diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 01ee712254..285f400b07 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -313,8 +313,8 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, if (OldEST == EST_None && NewEST == EST_None) return false; - FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(); - FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(); + FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context); + FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context); if (OldNR == FunctionProtoType::NR_BadNoexcept || NewNR == FunctionProtoType::NR_BadNoexcept) return false; @@ -460,7 +460,7 @@ bool Sema::CheckExceptionSpecSubset( // omissions we make here. // 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 || SuperNR == FunctionProtoType::NR_Dependent) return false; @@ -479,7 +479,7 @@ bool Sema::CheckExceptionSpecSubset( return true; } - FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(); + FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context); if (SubNR == FunctionProtoType::NR_BadNoexcept || SubNR == FunctionProtoType::NR_Dependent) return false; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a1cd43ac23..ea93449d7b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2423,7 +2423,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, FoundAssign = true; const FunctionProtoType *CPT = Operator->getType()->getAs(); - if (!CPT->isNothrow()) { + if (!CPT->isNothrow(Self.Context)) { AllNoThrow = false; break; } @@ -2465,7 +2465,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, = Constructor->getType()->getAs(); // FIXME: check whether evaluating default arguments 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; break; } @@ -2500,7 +2500,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, = Constructor->getType()->getAs(); // TODO: check whether evaluating default arguments 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; } } }