aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/TemplateBase.cpp
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2012-06-07 15:09:51 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2012-06-07 15:09:51 +0000
commit855243789cb44799c03f4c7216d3d6308805f549 (patch)
treeddfaf2e09c5404dd1a1caa9447984cdc7382dd97 /lib/AST/TemplateBase.cpp
parent575b66a8e07984ff21c1d3ed0da704043b9390bd (diff)
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
Diffstat (limited to 'lib/AST/TemplateBase.cpp')
-rw-r--r--lib/AST/TemplateBase.cpp32
1 files changed, 25 insertions, 7 deletions
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 531e03e302..284c1b5baa 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -36,17 +36,17 @@ using namespace clang;
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 @@ static void printIntegral(const TemplateArgument &TemplArg,
// 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 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
}
case Integral:
- getAsIntegral()->Profile(ID);
+ getAsIntegral().Profile(ID);
getIntegralType().Profile(ID);
break;
@@ -275,7 +293,7 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
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 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
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();