From c563475a9f0565b56fb97ab7c6f7ea96eac34ad2 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 13 Feb 2016 18:11:49 +0000 Subject: [PATCH] Fix a leak in the generated code for attributes with strings. Storing std::strings in attributes simply doesn't work, we never call the destructor. Use an array of StringRefs instead of std::strings and copy the data into memory taken from the ASTContext. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@260831 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclAttr.cpp | 6 +++--- utils/TableGen/ClangAttrEmitter.cpp | 21 +++++++++++++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index e95e4b70e8..9351c52afb 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4952,7 +4952,7 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return; - std::vector Sanitizers; + std::vector Sanitizers; for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) { StringRef SanitizerName; @@ -4976,8 +4976,8 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, const AttributeList &Attr) { StringRef AttrName = Attr.getName()->getName(); normalizeName(AttrName); - std::string SanitizerName = - llvm::StringSwitch(AttrName) + StringRef SanitizerName = + llvm::StringSwitch(AttrName) .Case("no_address_safety_analysis", "address") .Case("no_sanitize_address", "address") .Case("no_sanitize_thread", "thread") diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index c0574449ac..4a272d6bb7 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -81,7 +81,7 @@ static std::string ReadPCHRecord(StringRef type) { .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)") .Case("Expr *", "ReadExpr(F)") .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)") - .Case("std::string", "ReadString(Record, Idx)") + .Case("StringRef", "ReadString(Record, Idx)") .Default("Record[Idx++]"); } @@ -95,7 +95,7 @@ static std::string WritePCHRecord(StringRef type, StringRef name) { .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") .Case("IdentifierInfo *", "AddIdentifierRef(" + std::string(name) + ", Record);\n") - .Case("std::string", "AddString(" + std::string(name) + ", Record);\n") + .Case("StringRef", "AddString(" + std::string(name) + ", Record);\n") .Default("Record.push_back(" + std::string(name) + ");\n"); } @@ -528,7 +528,9 @@ namespace { : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"), ArgSizeName(ArgName + "Size"), RangeName(getLowerName()) {} - std::string getType() const { return Type; } + const std::string &getType() const { return Type; } + const std::string &getArgName() const { return ArgName; } + const std::string &getArgSizeName() const { return ArgSizeName; } bool isVariadic() const override { return true; } void writeAccessors(raw_ostream &OS) const override { @@ -993,8 +995,19 @@ namespace { class VariadicStringArgument : public VariadicArgument { public: VariadicStringArgument(const Record &Arg, StringRef Attr) - : VariadicArgument(Arg, Attr, "std::string") + : VariadicArgument(Arg, Attr, "StringRef") {} + void writeCtorBody(raw_ostream &OS) const override { + OS << " for (size_t I = 0, E = " << getArgSizeName() << "; I != E;\n" + " ++I) {\n" + " StringRef Ref = " << getUpperName() << "[I];\n" + " if (!Ref.empty()) {\n" + " char *Mem = new (Ctx, 1) char[Ref.size()];\n" + " std::memcpy(Mem, Ref.data(), Ref.size());\n" + " " << getArgName() << "[I] = StringRef(Mem, Ref.size());\n" + " }\n" + " }"; + } void writeValueImpl(raw_ostream &OS) const override { OS << " OS << \"\\\"\" << Val << \"\\\"\";\n"; } -- 2.50.1