Plug a long standing memory leak in TemplateArgument.

The integral APSInt value is now stored in a decomposed form and the backing
store for large values is allocated via the ASTContext. This way its not
leaked as TemplateArguments are never destructed when they are allocated in
the ASTContext. Since the integral data is immutable it is now shared between
instances, making copying TemplateArguments a trivial operation.

Currently getting the integral data out of a TemplateArgument requires creating
a new APSInt object. This is cheap when the value is small but can be expensive
if it's not. If this turns out to be an issue a more efficient accessor could
be added.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158150 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 65f5460..9d3f45f 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -73,7 +73,15 @@
   union {
     uintptr_t TypeOrValue;
     struct {
-      char Value[sizeof(llvm::APSInt)];
+      // We store a decomposed APSInt with the data allocated by ASTContext if
+      // BitWidth > 64. The memory may be shared between multiple
+      // TemplateArgument instances.
+      union {
+        uint64_t VAL;          ///< Used to store the <= 64 bits integer value.
+        const uint64_t *pVal;  ///< Used to store the >64 bits integer value.
+      };
+      unsigned BitWidth : 31;
+      unsigned IsUnsigned : 1;
       void *Type;
     } Integer;
     struct {
@@ -104,11 +112,15 @@
     TypeOrValue = reinterpret_cast<uintptr_t>(D);
   }
 
-  /// \brief Construct an integral constant template argument.
-  TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
-    // FIXME: Large integral values will get leaked. Do something
-    // similar to what we did with IntegerLiteral.
-    new (Integer.Value) llvm::APSInt(Value);
+  /// \brief Construct an integral constant template argument. The memory to
+  /// store the value is allocated with Ctx.
+  TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
+
+  /// \brief Construct an integral constant template argument with the same
+  /// value as Other but a different type.
+  TemplateArgument(const TemplateArgument &Other, QualType Type)
+    : Kind(Integral) {
+    Integer = Other.Integer;
     Integer.Type = Type.getAsOpaquePtr();
   }
 
@@ -165,62 +177,6 @@
     this->Args.NumArgs = NumArgs;
   }
 
-  /// \brief Copy constructor for a template argument.
-  TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
-    // FIXME: Large integral values will get leaked. Do something
-    // similar to what we did with IntegerLiteral.
-    if (Kind == Integral) {
-      new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
-      Integer.Type = Other.Integer.Type;
-    } else if (Kind == Pack) {
-      Args.NumArgs = Other.Args.NumArgs;
-      Args.Args = Other.Args.Args;
-    } else if (Kind == Template || Kind == TemplateExpansion) {
-      TemplateArg.Name = Other.TemplateArg.Name;
-      TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
-    } else
-      TypeOrValue = Other.TypeOrValue;
-  }
-
-  TemplateArgument& operator=(const TemplateArgument& Other) {
-    using llvm::APSInt;
-
-    if (Kind == Other.Kind && Kind == Integral) {
-      // Copy integral values.
-      *this->getAsIntegral() = *Other.getAsIntegral();
-      Integer.Type = Other.Integer.Type;
-      return *this;
-    } 
-
-    // Destroy the current integral value, if that's what we're holding.
-    if (Kind == Integral)
-      getAsIntegral()->~APSInt();
-
-    Kind = Other.Kind;
-
-    if (Other.Kind == Integral) {
-      new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
-      Integer.Type = Other.Integer.Type;
-    } else if (Other.Kind == Pack) {
-      Args.NumArgs = Other.Args.NumArgs;
-      Args.Args = Other.Args.Args;
-    } else if (Kind == Template || Kind == TemplateExpansion) {
-      TemplateArg.Name = Other.TemplateArg.Name;
-      TemplateArg.NumExpansions = Other.TemplateArg.NumExpansions;
-    } else {
-      TypeOrValue = Other.TypeOrValue;
-    }
-
-    return *this;
-  }
-
-  ~TemplateArgument() {
-    using llvm::APSInt;
-
-    if (Kind == Integral)
-      getAsIntegral()->~APSInt();
-  }
-
   /// \brief Create a new template argument pack by copying the given set of
   /// template arguments.
   static TemplateArgument CreatePackCopy(ASTContext &Context,
@@ -286,14 +242,14 @@
   llvm::Optional<unsigned> getNumTemplateExpansions() const;
   
   /// \brief Retrieve the template argument as an integral value.
-  llvm::APSInt *getAsIntegral() {
-    if (Kind != Integral)
-      return 0;
-    return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
-  }
-
-  const llvm::APSInt *getAsIntegral() const {
-    return const_cast<TemplateArgument*>(this)->getAsIntegral();
+  // FIXME: Provide a way to read the integral data without copying the value.
+  llvm::APSInt getAsIntegral() const {
+    if (Integer.BitWidth <= 64)
+      return llvm::APSInt(llvm::APInt(Integer.BitWidth, Integer.VAL),
+                          Integer.IsUnsigned);
+    return llvm::APSInt(llvm::APInt(Integer.BitWidth,
+                        llvm::makeArrayRef(Integer.pVal, Integer.BitWidth / 8)),
+                        Integer.IsUnsigned);
   }
 
   /// \brief Retrieve the type of the integral value.
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
index c16823a..87d71b8 100644
--- a/include/clang/Sema/Template.h
+++ b/include/clang/Sema/Template.h
@@ -152,10 +152,11 @@
 
     /// \brief Construct an integral non-type template argument that
     /// has been deduced, possibly from an array bound.
-    DeducedTemplateArgument(const llvm::APSInt &Value,
+    DeducedTemplateArgument(ASTContext &Ctx,
+                            const llvm::APSInt &Value,
                             QualType ValueType,
                             bool DeducedFromArrayBound)
-      : TemplateArgument(Value, ValueType), 
+      : TemplateArgument(Ctx, Value, ValueType),
         DeducedFromArrayBound(DeducedFromArrayBound) { }
 
     /// \brief For a non-type template argument, determine whether the
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 164813b..bd68d83 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3336,8 +3336,7 @@
                               Arg.getNumTemplateExpansions());
 
     case TemplateArgument::Integral:
-      return TemplateArgument(*Arg.getAsIntegral(),
-                              getCanonicalType(Arg.getIntegralType()));
+      return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType()));
 
     case TemplateArgument::Type:
       return TemplateArgument(getCanonicalType(Arg.getAsType()));
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 417f3cf..9f016fe 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -322,7 +322,7 @@
                                           Arg2.getIntegralType()))
       return false;
     
-    return IsSameValue(*Arg1.getAsIntegral(), *Arg2.getAsIntegral());
+    return IsSameValue(Arg1.getAsIntegral(), Arg2.getAsIntegral());
       
   case TemplateArgument::Declaration:
     if (!Arg1.getAsDecl() || !Arg2.getAsDecl())
@@ -1992,7 +1992,7 @@
     QualType ToType = Importer.Import(From.getIntegralType());
     if (ToType.isNull())
       return TemplateArgument();
-    return TemplateArgument(*From.getAsIntegral(), ToType);
+    return TemplateArgument(From, ToType);
   }
 
   case TemplateArgument::Declaration:
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index 4c7cd8a..4df692d 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -326,7 +326,7 @@
     }
     case TemplateArgument::Integral: {
       push("integer");
-      setInteger("value", *A.getAsIntegral());
+      setInteger("value", A.getAsIntegral());
       completeAttrs();
       pop();
       break;
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index e974ade..7c7a5e5 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -3132,7 +3132,7 @@
     break;
   }
   case TemplateArgument::Integral:
-    mangleIntegerLiteral(A.getIntegralType(), *A.getAsIntegral());
+    mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral());
     break;
   case TemplateArgument::Declaration: {
     assert(P && "Missing template parameter for declaration argument");
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 5984881..b0d9316 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -638,7 +638,7 @@
       mangleType(TA.getAsType());
       break;
     case TemplateArgument::Integral:
-      mangleIntegerLiteral(TA.getIntegralType(), *TA.getAsIntegral());
+      mangleIntegerLiteral(TA.getIntegralType(), TA.getAsIntegral());
       break;
     default: {
     	// Issue a diagnostic.
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 7309e7c..2bd4d76 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1275,7 +1275,7 @@
     const TemplateArgument &Pack = Args->get(0);
     for (TemplateArgument::pack_iterator I = Pack.pack_begin(),
                                          E = Pack.pack_end(); I != E; ++I) {
-      char C = (char)I->getAsIntegral()->getZExtValue();
+      char C = (char)I->getAsIntegral().getZExtValue();
       OS << C;
     }
     break;
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index e6b378e..72b979d 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -1161,7 +1161,7 @@
     break;
 
   case TemplateArgument::Integral:
-    Arg.getAsIntegral()->Profile(ID);
+    Arg.getAsIntegral().Profile(ID);
     VisitType(Arg.getIntegralType());
     break;
 
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 531e03e..284c1b5 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -36,17 +36,17 @@
 static void printIntegral(const TemplateArgument &TemplArg,
                           raw_ostream &Out) {
   const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
-  const llvm::APSInt *Val = TemplArg.getAsIntegral();
+  const llvm::APSInt &Val = TemplArg.getAsIntegral();
 
   if (T->isBooleanType()) {
-    Out << (Val->getBoolValue() ? "true" : "false");
+    Out << (Val.getBoolValue() ? "true" : "false");
   } else if (T->isCharType()) {
-    const char Ch = Val->getZExtValue();
+    const char Ch = Val.getZExtValue();
     Out << ((Ch == '\'') ? "'\\" : "'");
     Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
     Out << "'";
   } else {
-    Out << Val->toString(10);
+    Out << Val;
   }
 }
 
@@ -54,6 +54,24 @@
 // TemplateArgument Implementation
 //===----------------------------------------------------------------------===//
 
+TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
+                                   QualType Type)
+  : Kind(Integral) {
+  // Copy the APSInt value into our decomposed form.
+  Integer.BitWidth = Value.getBitWidth();
+  Integer.IsUnsigned = Value.isUnsigned();
+  // If the value is large, we have to get additional memory from the ASTContext
+  if (Integer.BitWidth > 64) {
+    void *Mem = Ctx.Allocate(Integer.BitWidth / 8);
+    std::memcpy(Mem, Value.getRawData(), Integer.BitWidth / 8);
+    Integer.pVal = static_cast<uint64_t *>(Mem);
+  } else {
+    Integer.VAL = Value.getZExtValue();
+  }
+
+  Integer.Type = Type.getAsOpaquePtr();
+}
+
 TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
                                                   const TemplateArgument *Args,
                                                   unsigned NumArgs) {
@@ -246,7 +264,7 @@
   }
       
   case Integral:
-    getAsIntegral()->Profile(ID);
+    getAsIntegral().Profile(ID);
     getIntegralType().Profile(ID);
     break;
 
@@ -275,7 +293,7 @@
 
   case Integral:
     return getIntegralType() == Other.getIntegralType() &&
-           *getAsIntegral() == *Other.getAsIntegral();
+           getAsIntegral() == Other.getAsIntegral();
 
   case Pack:
     if (Args.NumArgs != Other.Args.NumArgs) return false;
@@ -498,7 +516,7 @@
     return DB << "nullptr";
       
   case TemplateArgument::Integral:
-    return DB << Arg.getAsIntegral()->toString(10);
+    return DB << Arg.getAsIntegral().toString(10);
       
   case TemplateArgument::Template:
     return DB << Arg.getAsTemplate();
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index beea777..8d28322 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1086,7 +1086,7 @@
       llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
       llvm::DITemplateValueParameter TVP =
         DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy,
-                                          TA.getAsIntegral()->getZExtValue());
+                                             TA.getAsIntegral().getZExtValue());
       TemplateParams.push_back(TVP);          
     }
   }
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9f0378a..d2377f5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2605,7 +2605,7 @@
       llvm::APSInt Value(CharBits, CharIsUnsigned);
       for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) {
         Value = ThisTokBegin[I];
-        TemplateArgument Arg(Value, Context.CharTy);
+        TemplateArgument Arg(Context, Value, Context.CharTy);
         TemplateArgumentLocInfo ArgInfo;
         ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
       }
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 002b0b1..dccb4b6 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -4125,7 +4125,8 @@
         IntegerType = Enum->getDecl()->getIntegerType();
       Value = Value.extOrTrunc(Context.getTypeSize(IntegerType));
 
-      Converted = TemplateArgument(Value, Context.getCanonicalType(ParamType));
+      Converted = TemplateArgument(Context, Value,
+                                   Context.getCanonicalType(ParamType));
       return ArgResult;
     }
 
@@ -4251,7 +4252,7 @@
       }
     }
 
-    Converted = TemplateArgument(Value,
+    Converted = TemplateArgument(Context, Value,
                                  ParamType->isEnumeralType() 
                                    ? Context.getCanonicalType(ParamType)
                                    : IntegerType);
@@ -4569,13 +4570,13 @@
       Kind = CharacterLiteral::Ascii;
 
     return Owned(new (Context) CharacterLiteral(
-                                            Arg.getAsIntegral()->getZExtValue(),
+                                            Arg.getAsIntegral().getZExtValue(),
                                             Kind, T, Loc));
   }
 
   if (T->isBooleanType())
     return Owned(new (Context) CXXBoolLiteralExpr(
-                                            Arg.getAsIntegral()->getBoolValue(),
+                                            Arg.getAsIntegral().getBoolValue(),
                                             T, Loc));
 
   if (T->isNullPtrType())
@@ -4590,7 +4591,7 @@
   else
     BT = T;
 
-  Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc);
+  Expr *E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), BT, Loc);
   if (T->isEnumeralType()) {
     // FIXME: This is a hack. We need a better way to handle substituted
     // non-type template parameters.
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index e6f2b2d..78a860c 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -193,7 +193,7 @@
     if (Y.getKind() == TemplateArgument::Expression ||
         Y.getKind() == TemplateArgument::Declaration ||
         (Y.getKind() == TemplateArgument::Integral &&
-         hasSameExtendedValue(*X.getAsIntegral(), *Y.getAsIntegral())))
+         hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral())))
       return DeducedTemplateArgument(X,
                                      X.wasDeducedFromArrayBound() &&
                                      Y.wasDeducedFromArrayBound());
@@ -293,7 +293,8 @@
   assert(NTTP->getDepth() == 0 &&
          "Cannot deduce non-type template argument with depth > 0");
 
-  DeducedTemplateArgument NewDeduced(Value, ValueType, DeducedFromArrayBound);
+  DeducedTemplateArgument NewDeduced(S.Context, Value, ValueType,
+                                     DeducedFromArrayBound);
   DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
                                                      Deduced[NTTP->getIndex()],
                                                                  NewDeduced);
@@ -1595,7 +1596,7 @@
 
   case TemplateArgument::Integral:
     if (Arg.getKind() == TemplateArgument::Integral) {
-      if (hasSameExtendedValue(*Param.getAsIntegral(), *Arg.getAsIntegral()))
+      if (hasSameExtendedValue(Param.getAsIntegral(), Arg.getAsIntegral()))
         return Sema::TDK_Success;
 
       Info.FirstArg = Param;
@@ -1618,7 +1619,7 @@
           = getDeducedParameterFromExpr(Param.getAsExpr())) {
       if (Arg.getKind() == TemplateArgument::Integral)
         return DeduceNonTypeTemplateArgument(S, NTTP,
-                                             *Arg.getAsIntegral(),
+                                             Arg.getAsIntegral(),
                                              Arg.getIntegralType(),
                                              /*ArrayBound=*/false,
                                              Info, Deduced);
@@ -1867,7 +1868,7 @@
                     Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
 
     case TemplateArgument::Integral:
-      return *X.getAsIntegral() == *Y.getAsIntegral();
+      return X.getAsIntegral() == Y.getAsIntegral();
 
     case TemplateArgument::Expression: {
       llvm::FoldingSetNodeID XID, YID;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index a9092a4..3b59163 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -5905,7 +5905,7 @@
   case TemplateArgument::Integral: {
     llvm::APSInt Value = ReadAPSInt(Record, Idx);
     QualType T = readType(F, Record, Idx);
-    return TemplateArgument(Value, T);
+    return TemplateArgument(Context, Value, T);
   }
   case TemplateArgument::Template: 
     return TemplateArgument(ReadTemplateName(F, Record, Idx));
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index edef1c0..0eb2f16 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -4147,7 +4147,7 @@
     AddDeclRef(Arg.getAsDecl(), Record);
     break;
   case TemplateArgument::Integral:
-    AddAPSInt(*Arg.getAsIntegral(), Record);
+    AddAPSInt(Arg.getAsIntegral(), Record);
     AddTypeRef(Arg.getIntegralType(), Record);
     break;
   case TemplateArgument::Template:
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index 7c79b69..c885dd5 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -754,7 +754,7 @@
   case TemplateArgument::Integral:
     Out << 'V';
     VisitType(Arg.getIntegralType());
-    Out << *Arg.getAsIntegral();
+    Out << Arg.getAsIntegral();
     break;
   }
 }