]> granicus.if.org Git - clang/commitdiff
Instead of storing an ASTContext* in FunctionProtoTypes with computed noexcept specif...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 13 Mar 2011 17:09:40 +0000 (17:09 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Sun, 13 Mar 2011 17:09:40 +0000 (17:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127568 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/ExprCXX.h
include/clang/AST/Type.h
lib/AST/ASTContext.cpp
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/AST/Type.cpp
lib/Analysis/CFG.cpp
lib/CodeGen/CGCall.cpp
lib/CodeGen/CGExprCXX.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExceptionSpec.cpp
lib/Sema/SemaExprCXX.cpp

index c0eeb5af38922ad294ef2bfb5c2eda89e5ab1f40..2f2cc9a3e125cedcd46126f8d75307da860569e1 100644 (file)
@@ -96,7 +96,8 @@ class ASTContext {
     DependentSizedExtVectorTypes;
   mutable llvm::FoldingSet<VectorType> VectorTypes;
   mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
-  mutable llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes;
+  mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&>
+    FunctionProtoTypes;
   mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
   mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
   mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
index 1f9b3b7228e543dc6a499ab50127d0e12d7b0a29..30481ba779e76e5022903d23b18bf3c2e7362e77 100644 (file)
@@ -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; }
index 6d5ca71ed4666b46e4f56260c4ddd55fa2b8f6ba..963f4b55432b3d92b77719969867e8dc9fb4f6c8 100644 (file)
@@ -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<const ASTContext *const *>(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<Expr *const *>(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);
 };
 
 
index c128ce598bdf9f223e01a73edf7c19fea140ccaa..0526ebb5cb0bf8fe7f1b713f00809355334410e6 100644 (file)
@@ -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);
index 1c7807e6d201eb89bbc5ba3d634558d6459a2388..9c4444225eed2336a7b0a5040d3e60350e878eef 100644 (file)
@@ -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<CallExpr>(this)->getCalleeDecl());
+    CanThrowResult CT = CanCalleeThrow(C,cast<CallExpr>(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<CXXConstructExpr>(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<CXXNewExpr>(this)->getOperatorNew()),
-        CanCalleeThrow(cast<CXXNewExpr>(this)->getConstructor(),
+        CanCalleeThrow(C, cast<CXXNewExpr>(this)->getOperatorNew()),
+        CanCalleeThrow(C, cast<CXXNewExpr>(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<CXXDeleteExpr>(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<PointerType>()) {
       if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) {
-        CanThrowResult CT2 = CanCalleeThrow(
+        CanThrowResult CT2 = CanCalleeThrow(C,
             cast<CXXRecordDecl>(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<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor());
     if (CT == CT_Can)
       return CT;
index fd94dd108db68de46e99b5eb9e1520036001dff1..35c2d4100823f13a497896bf67853b09fbd1da58 100644 (file)
@@ -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<FunctionProtoType>()->isNothrow();
+    castAs<FunctionProtoType>()->isNothrow(Ctx);
 }
 
 // CXXDeleteExpr
index eb5254e96e9438d41920180a2bef7a199d709cd6..1e2a6c48fddda636025a5f75c6c37cc89e473d64 100644 (file)
@@ -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<Expr**>(argSlot + numArgs);
     *noexSlot = epi.NoexceptExpr;
-    const ASTContext **contextSlot = const_cast<const ASTContext**>(
-        reinterpret_cast<ASTContext**>(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<ASTContext&>(*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 {
index 8f8c475d354d07d3852f1739be32d9097b898ec1..4772a69b4ae05579f84b7c64bb4f2938a2583ee6 100644 (file)
@@ -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<PointerType>()->getPointeeType();
@@ -1128,7 +1128,7 @@ static bool CanThrow(Expr *E) {
   const FunctionType *FT = Ty->getAs<FunctionType>();
   if (FT) {
     if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(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)
index d72e6dc42954ce101b6c3c2549d8ea94df58ca89..15ab6b080bef2cb5253f671f6b1fb9ddb84ff365 100644 (file)
@@ -709,7 +709,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
       FuncAttrs |= llvm::Attribute::NoUnwind;
     else if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
       const FunctionProtoType *FPT = Fn->getType()->getAs<FunctionProtoType>();
-      if (FPT && FPT->isNothrow())
+      if (FPT && FPT->isNothrow(getContext()))
         FuncAttrs |= llvm::Attribute::NoUnwind;
     }
 
index c9c8a6a35d736a99998de987a31ad006287a6d1b..32d1928b443194c0dc10fdf4ea09b6ed8ff5d23e 100644 (file)
@@ -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;
index f6551054c183901f90b0a9aeb68fb2de795fe228..04c21bc47ca4f948e86fb1cbc60cec9ac0d50b5c 100644 (file)
@@ -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 &&
index 01ee712254dbf09e8ee2321e1644055d7980ec48..285f400b07b3a6a378f0402bbd4c82944e9073cc 100644 (file)
@@ -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;
index a1cd43ac23fc543ba4ad6dfdb32d5ac51505fd02..ea93449d7b816a6c5edc9d741ddbc83aae28610e 100644 (file)
@@ -2423,7 +2423,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
             FoundAssign = true;
             const FunctionProtoType *CPT
                 = Operator->getType()->getAs<FunctionProtoType>();
-            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<FunctionProtoType>();
           // 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<FunctionProtoType>();
           // 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;
         }
       }
     }