]> granicus.if.org Git - clang/commitdiff
Fix the memory leak of FloatingLiteral/IntegerLiteral.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 28 Aug 2010 09:06:06 +0000 (09:06 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 28 Aug 2010 09:06:06 +0000 (09:06 +0000)
For large floats/integers, APFloat/APInt will allocate memory from the heap to represent these numbers.
Unfortunately, when we use a BumpPtrAllocator to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
the APFloat/APInt values will never get freed.
I introduce the class 'APNumericStorage' which uses ASTContext's allocator for memory allocation and is used internally by FloatingLiteral/IntegerLiteral.

Fixes rdar://7637185

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112361 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/AST/Expr.h
lib/AST/ASTImporter.cpp
lib/AST/Expr.cpp
lib/Rewrite/RewriteObjC.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp

index 61159fdc4a65ebaea5ef6a649381563e11f9dbb5..9ec1451e76e65a6452f40f32d0e1b593bdda053b 100644 (file)
@@ -757,28 +757,84 @@ public:
   virtual child_iterator child_end();
 };
 
+/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
+/// leaking memory.
+///
+/// For large floats/integers, APFloat/APInt will allocate memory from the heap
+/// to represent these numbers.  Unfortunately, when we use a BumpPtrAllocator
+/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
+/// the APFloat/APInt values will never get freed. APNumericStorage uses
+/// ASTContext's allocator for memory allocation.
+class APNumericStorage {
+  unsigned BitWidth;
+  union {
+    uint64_t VAL;    ///< Used to store the <= 64 bits integer value.
+    uint64_t *pVal;  ///< Used to store the >64 bits integer value.
+  };
+
+  bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
+
+  APNumericStorage(const APNumericStorage&); // do not implement
+  APNumericStorage& operator=(const APNumericStorage&); // do not implement
+
+protected:
+  APNumericStorage() : BitWidth(0), VAL(0) { }
+
+  llvm::APInt getIntValue() const {
+    unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+    if (NumWords > 1)
+      return llvm::APInt(BitWidth, NumWords, pVal);
+    else
+      return llvm::APInt(BitWidth, VAL);
+  }
+  void setIntValue(ASTContext &C, const llvm::APInt &Val);
+};
+
+class APIntStorage : public APNumericStorage {
+public:  
+  llvm::APInt getValue() const { return getIntValue(); } 
+  void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); }
+};
+
+class APFloatStorage : public APNumericStorage {
+public:  
+  llvm::APFloat getValue() const { return llvm::APFloat(getIntValue()); } 
+  void setValue(ASTContext &C, const llvm::APFloat &Val) {
+    setIntValue(C, Val.bitcastToAPInt());
+  }
+};
+
 class IntegerLiteral : public Expr {
-  llvm::APInt Value;
+  APIntStorage Num;
   SourceLocation Loc;
+
+  /// \brief Construct an empty integer literal.
+  explicit IntegerLiteral(EmptyShell Empty)
+    : Expr(IntegerLiteralClass, Empty) { }
+
 public:
   // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
   // or UnsignedLongLongTy
-  IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l)
-    : Expr(IntegerLiteralClass, type, false, false), Value(V), Loc(l) {
+  IntegerLiteral(ASTContext &C, const llvm::APInt &V,
+                 QualType type, SourceLocation l)
+    : Expr(IntegerLiteralClass, type, false, false), Loc(l) {
     assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
+    setValue(C, V);
   }
 
-  /// \brief Construct an empty integer literal.
-  explicit IntegerLiteral(EmptyShell Empty)
-    : Expr(IntegerLiteralClass, Empty) { }
+  // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+  // or UnsignedLongLongTy
+  static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
+                                QualType type, SourceLocation l);
+  static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
 
-  const llvm::APInt &getValue() const { return Value; }
+  llvm::APInt getValue() const { return Num.getValue(); }
   virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
 
   /// \brief Retrieve the location of the literal.
   SourceLocation getLocation() const { return Loc; }
 
-  void setValue(const llvm::APInt &Val) { Value = Val; }
+  void setValue(ASTContext &C, const llvm::APInt &Val) { Num.setValue(C, Val); }
   void setLocation(SourceLocation Location) { Loc = Location; }
 
   static bool classof(const Stmt *T) {
@@ -827,21 +883,30 @@ public:
 };
 
 class FloatingLiteral : public Expr {
-  llvm::APFloat Value;
+  APFloatStorage Num;
   bool IsExact : 1;
   SourceLocation Loc;
-public:
-  FloatingLiteral(const llvm::APFloat &V, bool isexact,
+
+  FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
                   QualType Type, SourceLocation L)
-    : Expr(FloatingLiteralClass, Type, false, false), Value(V),
-      IsExact(isexact), Loc(L) {}
+    : Expr(FloatingLiteralClass, Type, false, false),
+      IsExact(isexact), Loc(L) {
+    setValue(C, V);
+  }
 
   /// \brief Construct an empty floating-point literal.
   explicit FloatingLiteral(EmptyShell Empty)
-    : Expr(FloatingLiteralClass, Empty), Value(0.0) { }
+    : Expr(FloatingLiteralClass, Empty), IsExact(false) { }
+
+public:
+  static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V,
+                                 bool isexact, QualType Type, SourceLocation L);
+  static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty);
 
-  const llvm::APFloat &getValue() const { return Value; }
-  void setValue(const llvm::APFloat &Val) { Value = Val; }
+  llvm::APFloat getValue() const { return Num.getValue(); }
+  void setValue(ASTContext &C, const llvm::APFloat &Val) {
+    Num.setValue(C, Val);
+  }
 
   bool isExact() const { return IsExact; }
   void setExact(bool E) { IsExact = E; }
index f63df46f5268327100152ce9068430a5ddfe8ad8..eee41a6c2e36433423eb17b8b229fd9d40ebb7bb 100644 (file)
@@ -2818,8 +2818,9 @@ Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
   if (T.isNull())
     return 0;
 
-  return new (Importer.getToContext()) 
-    IntegerLiteral(E->getValue(), T, Importer.Import(E->getLocation()));
+  return IntegerLiteral::Create(Importer.getToContext(), 
+                                E->getValue(), T,
+                                Importer.Import(E->getLocation()));
 }
 
 Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
index d5cf4d67fc03c651d74e70bd56a36a378c99a786..5feef1c803320d25e20734a073cfb9c003131945 100644 (file)
@@ -374,6 +374,44 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
   return "";
 }
 
+void APNumericStorage::setIntValue(ASTContext &C, const llvm::APInt &Val) {
+  if (hasAllocation())
+    C.Deallocate(pVal);
+
+  BitWidth = Val.getBitWidth();
+  unsigned NumWords = Val.getNumWords();
+  const uint64_t* Words = Val.getRawData();
+  if (NumWords > 1) {
+    pVal = new (C) uint64_t[NumWords];
+    std::copy(Words, Words + NumWords, pVal);
+  } else if (NumWords == 1)
+    VAL = Words[0];
+  else
+    VAL = 0;
+}
+
+IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, const llvm::APInt &V,
+                       QualType type, SourceLocation l) {
+  return new (C) IntegerLiteral(C, V, type, l);
+}
+
+IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, EmptyShell Empty) {
+  return new (C) IntegerLiteral(Empty);
+}
+
+FloatingLiteral *
+FloatingLiteral::Create(ASTContext &C, const llvm::APFloat &V,
+                        bool isexact, QualType Type, SourceLocation L) {
+  return new (C) FloatingLiteral(C, V, isexact, Type, L);
+}
+
+FloatingLiteral *
+FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) {
+  return new (C) FloatingLiteral(Empty);
+}
+
 /// getValueAsApproximateDouble - This returns the value as an inaccurate
 /// double.  Note that this may cause loss of precision, but is useful for
 /// debugging dumps, etc.
index 80b9681a7e3030c4968730eb1beb3bc2fcc91b92..4a7de4bed0d691bccda3c07d0011e16c059fef1b 100644 (file)
@@ -3029,9 +3029,10 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
     // is needed to decide what to do.
     unsigned IntSize =
       static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
-    IntegerLiteral *limit = new (Context) IntegerLiteral(llvm::APInt(IntSize, 8),
-                                               Context->IntTy,
-                                               SourceLocation());
+    IntegerLiteral *limit = IntegerLiteral::Create(*Context,
+                                                   llvm::APInt(IntSize, 8),
+                                                   Context->IntTy,
+                                                   SourceLocation());
     BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit,
                                                       BO_LE,
                                                       Context->IntTy,
@@ -5268,8 +5269,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
     int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
     unsigned IntSize = 
       static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
-    Expr *FlagExp = new (Context) IntegerLiteral(llvm::APInt(IntSize, flag), 
-                                             Context->IntTy, SourceLocation());
+    Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 
+                                           Context->IntTy, SourceLocation());
     InitExprs.push_back(FlagExp);
   }
   NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
index 26d4941917438e3b338a2fef1dbd1b2096b6c0ee..6f8d9a92797afdc5101c8372fcc17d005ca313b2 100644 (file)
@@ -6480,8 +6480,7 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl,
   }
   // All conditions are met. Add a new bitfield to the tail end of ivars.
   llvm::APInt Zero(Context.getTypeSize(Context.CharTy), 0);
-  Expr * BW = 
-    new (Context) IntegerLiteral(Zero, Context.CharTy, DeclLoc);
+  Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc);
 
   Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl),
                               DeclLoc, 0,
index 676af80c730af342e3bfcd74fa2592203ffcd612..35920c2792bfa10357efe3d874b0f43823b5dfdb 100644 (file)
@@ -4669,7 +4669,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
   
   // Initialize the iteration variable to zero.
   llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
-  IterationVar->setInit(new (S.Context) IntegerLiteral(Zero, SizeType, Loc));
+  IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));
 
   // Create a reference to the iteration variable; we'll use this several
   // times throughout.
@@ -4685,8 +4685,9 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
   Upper.zextOrTrunc(S.Context.getTypeSize(SizeType));
   Expr *Comparison
     = new (S.Context) BinaryOperator(IterationVarRef->Retain(),
-                           new (S.Context) IntegerLiteral(Upper, SizeType, Loc),
-                                    BO_NE, S.Context.BoolTy, Loc);
+                           IntegerLiteral::Create(S.Context,
+                                                  Upper, SizeType, Loc),
+                                                  BO_NE, S.Context.BoolTy, Loc);
   
   // Create the pre-increment of the iteration variable.
   Expr *Increment
@@ -5135,7 +5136,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
       ASTOwningVector<Expr*> CallArgs(*this);
       CallArgs.push_back(To.takeAs<Expr>());
       CallArgs.push_back(From.takeAs<Expr>());
-      CallArgs.push_back(new (Context) IntegerLiteral(Size, SizeType, Loc));
+      CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
       llvm::SmallVector<SourceLocation, 4> Commas; // FIXME: Silly
       Commas.push_back(Loc);
       Commas.push_back(Loc);
index d0c2b8214a9c82ed5ac3d9c03125c01ef4bf2a78..1a065eb63ced6178e4fa06903eeb59434819a6ec 100644 (file)
@@ -1946,7 +1946,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
   if (Tok.getLength() == 1) {
     const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok);
     unsigned IntSize = Context.Target.getIntWidth();
-    return Owned(new (Context) IntegerLiteral(llvm::APInt(IntSize, Val-'0'),
+    return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val-'0'),
                     Context.IntTy, Tok.getLocation()));
   }
 
@@ -2004,7 +2004,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
     }
 
     bool isExact = (result == APFloat::opOK);
-    Res = new (Context) FloatingLiteral(Val, isExact, Ty, Tok.getLocation());
+    Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation());
 
   } else if (!Literal.isIntegerLiteral()) {
     return ExprError();
@@ -2091,7 +2091,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
       if (ResultVal.getBitWidth() != Width)
         ResultVal.trunc(Width);
     }
-    Res = new (Context) IntegerLiteral(ResultVal, Ty, Tok.getLocation());
+    Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
   }
 
   // If this is an imaginary literal, create the ImaginaryLiteral wrapper.
index 2f8cfe2d2f7ceca871b8325b51406e7712bb0a78..5720d931b66bd6df3c99def363333ee75d0b9051 100644 (file)
@@ -672,9 +672,9 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
   if (!ArraySize) {
     if (const ConstantArrayType *Array
                               = Context.getAsConstantArrayType(AllocType)) {
-      ArraySize = new (Context) IntegerLiteral(Array->getSize(),
-                                               Context.getSizeType(),
-                                               TypeRange.getEnd());
+      ArraySize = IntegerLiteral::Create(Context, Array->getSize(),
+                                         Context.getSizeType(),
+                                         TypeRange.getEnd());
       AllocType = Array->getElementType();
     }
   }
@@ -922,7 +922,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
   // We don't care about the actual value of this argument.
   // FIXME: Should the Sema create the expression and embed it in the syntax
   // tree? Or should the consumer just recalculate the value?
-  IntegerLiteral Size(llvm::APInt::getNullValue(
+  IntegerLiteral Size(Context, llvm::APInt::getNullValue(
                       Context.Target.getPointerWidth(0)),
                       Context.getSizeType(),
                       SourceLocation());
index b5f1e528e4f31f0d6d2d150abcfd1766fcca3b79..11b4bb3b92c600c089d292552431a3407d2af8ee 100644 (file)
@@ -6754,8 +6754,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
   // post-decrement.
   if (Opc == UO_PostInc || Opc == UO_PostDec) {
     llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false);
-    Args[1] = new (Context) IntegerLiteral(Zero, Context.IntTy,
-                                           SourceLocation());
+    Args[1] = IntegerLiteral::Create(Context, Zero, Context.IntTy,
+                                     SourceLocation());
     NumArgs = 2;
   }
 
index e293e9b39cc688bb2e561d0af46855f1040a7455..09656bcd915452d5d948ddb5ed90cee0db0df718 100644 (file)
@@ -3149,7 +3149,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
                                             T,
                                             Loc));
 
-  return Owned(new (Context) IntegerLiteral(*Arg.getAsIntegral(), T, Loc));
+  return Owned(IntegerLiteral::Create(Context, *Arg.getAsIntegral(), T, Loc));
 }
 
 
index dbc02d8727207823013af573cfdd1f06f42f3e35..08cfd68d663e0efa6e8c67da6902785ffad49b4d 100644 (file)
@@ -5332,10 +5332,10 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
     } else if (const ConstantArrayType *ConsArrayT
                                      = dyn_cast<ConstantArrayType>(ArrayT)) {
       ArraySize 
-        = SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
-                                                  ConsArrayT->getSize(), 
-                                                  SemaRef.Context.getSizeType(),
-                                                  /*FIXME:*/E->getLocStart()));
+        = SemaRef.Owned(IntegerLiteral::Create(SemaRef.Context,
+                                               ConsArrayT->getSize(), 
+                                               SemaRef.Context.getSizeType(),
+                                               /*FIXME:*/E->getLocStart()));
       AllocType = ConsArrayT->getElementType();
     } else if (const DependentSizedArrayType *DepArrayT
                               = dyn_cast<DependentSizedArrayType>(ArrayT)) {
@@ -6352,7 +6352,8 @@ TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
       break;
     }
 
-  IntegerLiteral ArraySize(*Size, SizeType, /*FIXME*/BracketsRange.getBegin());
+  IntegerLiteral ArraySize(SemaRef.Context, *Size, SizeType,
+                           /*FIXME*/BracketsRange.getBegin());
   return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize,
                                 IndexTypeQuals, BracketsRange,
                                 getDerived().getBaseEntity());
@@ -6418,8 +6419,8 @@ QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
   llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
                           NumElements, true);
   IntegerLiteral *VectorSize
-    = new (SemaRef.Context) IntegerLiteral(numElements, SemaRef.Context.IntTy,
-                                           AttributeLoc);
+    = IntegerLiteral::Create(SemaRef.Context, numElements, SemaRef.Context.IntTy,
+                             AttributeLoc);
   return SemaRef.BuildExtVectorType(ElementType, VectorSize, AttributeLoc);
 }
 
index ff2d39e6ec7aad7de50355248132ad1b2e8506bb..ec227e2836d82427d6027d505fdc19ebff6ece1f 100644 (file)
@@ -409,12 +409,12 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
 void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
   VisitExpr(E);
   E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  E->setValue(Reader.ReadAPInt(Record, Idx));
+  E->setValue(*Reader.getContext(), Reader.ReadAPInt(Record, Idx));
 }
 
 void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
   VisitExpr(E);
-  E->setValue(Reader.ReadAPFloat(Record, Idx));
+  E->setValue(*Reader.getContext(), Reader.ReadAPFloat(Record, Idx));
   E->setExact(Record[Idx++]);
   E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
@@ -1401,11 +1401,11 @@ Stmt *ASTReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
       break;
 
     case EXPR_INTEGER_LITERAL:
-      S = new (Context) IntegerLiteral(Empty);
+      S = IntegerLiteral::Create(*Context, Empty);
       break;
 
     case EXPR_FLOATING_LITERAL:
-      S = new (Context) FloatingLiteral(Empty);
+      S = FloatingLiteral::Create(*Context, Empty);
       break;
 
     case EXPR_IMAGINARY_LITERAL: