void clang_remap_getFilenames(CXRemapping map, unsigned index,
CXString *original, CXString *transformed) {
if (original)
- *original = cxstring::createCXString(
- static_cast<Remap *>(map)->Vec[index].first,
- /*DupString =*/ true);
+ *original = cxstring::createDup(
+ static_cast<Remap *>(map)->Vec[index].first);
if (transformed)
- *transformed = cxstring::createCXString(
- static_cast<Remap *>(map)->Vec[index].second,
- /*DupString =*/ true);
+ *transformed = cxstring::createDup(
+ static_cast<Remap *>(map)->Vec[index].second);
}
void clang_remap_dispose(CXRemapping map) {
return cxstring::createEmpty();
ASTUnit *CXXUnit = cxtu::getASTUnit(CTUnit);
- return createCXString(CXXUnit->getOriginalSourceFileName(), true);
+ return cxstring::createDup(CXXUnit->getOriginalSourceFileName());
}
CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
if (const ObjCPropertyImplDecl *PropImpl =
dyn_cast<ObjCPropertyImplDecl>(D))
if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl())
- return createCXString(Property->getIdentifier()->getName());
+ return cxstring::createDup(Property->getIdentifier()->getName());
if (const ImportDecl *ImportD = dyn_cast<ImportDecl>(D))
if (Module *Mod = ImportD->getImportedModule())
- return createCXString(Mod->getFullModuleName());
+ return cxstring::createDup(Mod->getFullModuleName());
return cxstring::createEmpty();
}
if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
- return createCXString(OMD->getSelector().getAsString());
+ return cxstring::createDup(OMD->getSelector().getAsString());
if (const ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
// No, this isn't the same as the code below. getIdentifier() is non-virtual
llvm::raw_svector_ostream os(S);
ND->printName(os);
- return createCXString(os.str());
+ return cxstring::createDup(os.str());
}
CXString clang_getCursorSpelling(CXCursor C) {
}
case CXCursor_CXXBaseSpecifier: {
const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
- return createCXString(B->getType().getAsString());
+ return cxstring::createDup(B->getType().getAsString());
}
case CXCursor_TypeRef: {
const TypeDecl *Type = getCursorTypeRef(C).first;
assert(Type && "Missing type decl");
- return createCXString(getCursorContext(C).getTypeDeclType(Type).
+ return cxstring::createDup(getCursorContext(C).getTypeDeclType(Type).
getAsString());
}
case CXCursor_TemplateRef: {
const TemplateDecl *Template = getCursorTemplateRef(C).first;
assert(Template && "Missing template decl");
- return createCXString(Template->getNameAsString());
+ return cxstring::createDup(Template->getNameAsString());
}
case CXCursor_NamespaceRef: {
const NamedDecl *NS = getCursorNamespaceRef(C).first;
assert(NS && "Missing namespace decl");
- return createCXString(NS->getNameAsString());
+ return cxstring::createDup(NS->getNameAsString());
}
case CXCursor_MemberRef: {
const FieldDecl *Field = getCursorMemberRef(C).first;
assert(Field && "Missing member decl");
- return createCXString(Field->getNameAsString());
+ return cxstring::createDup(Field->getNameAsString());
}
case CXCursor_LabelRef: {
OverloadedDeclRefStorage Storage = getCursorOverloadedDeclRef(C).first;
if (const Decl *D = Storage.dyn_cast<const Decl *>()) {
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
- return createCXString(ND->getNameAsString());
+ return cxstring::createDup(ND->getNameAsString());
return cxstring::createEmpty();
}
if (const OverloadExpr *E = Storage.dyn_cast<const OverloadExpr *>())
- return createCXString(E->getName().getAsString());
+ return cxstring::createDup(E->getName().getAsString());
OverloadedTemplateStorage *Ovl
= Storage.get<OverloadedTemplateStorage*>();
if (Ovl->size() == 0)
return cxstring::createEmpty();
- return createCXString((*Ovl->begin())->getNameAsString());
+ return cxstring::createDup((*Ovl->begin())->getNameAsString());
}
case CXCursor_VariableRef: {
const VarDecl *Var = getCursorVariableRef(C).first;
assert(Var && "Missing variable decl");
- return createCXString(Var->getNameAsString());
+ return cxstring::createDup(Var->getNameAsString());
}
default:
->getNameStart());
if (C.kind == CXCursor_InclusionDirective)
- return createCXString(getCursorInclusionDirective(C)->getFileName());
+ return cxstring::createDup(getCursorInclusionDirective(C)->getFileName());
if (clang_isDeclaration(C.kind))
return getDeclSpelling(getCursorDecl(C));
if (C.kind == CXCursor_AnnotateAttr) {
const AnnotateAttr *AA = cast<AnnotateAttr>(cxcursor::getCursorAttr(C));
- return createCXString(AA->getAnnotation());
+ return cxstring::createDup(AA->getAnnotation());
}
if (C.kind == CXCursor_AsmLabelAttr) {
const AsmLabelAttr *AA = cast<AsmLabelAttr>(cxcursor::getCursorAttr(C));
- return createCXString(AA->getLabel());
+ return cxstring::createDup(AA->getLabel());
}
return cxstring::createEmpty();
OS << "...";
}
OS << ")";
- return createCXString(OS.str());
+ return cxstring::createDup(OS.str());
}
if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) {
}
OS << ">";
- return createCXString(OS.str());
+ return cxstring::createDup(OS.str());
}
if (const ClassTemplateSpecializationDecl *ClassSpec
= dyn_cast<ClassTemplateSpecializationDecl>(D)) {
// If the type was explicitly written, use that.
if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten())
- return createCXString(TSInfo->getType().getAsString(Policy));
+ return cxstring::createDup(TSInfo->getType().getAsString(Policy));
SmallString<64> Str;
llvm::raw_svector_ostream OS(Str);
ClassSpec->getTemplateArgs().data(),
ClassSpec->getTemplateArgs().size(),
Policy);
- return createCXString(OS.str());
+ return cxstring::createDup(OS.str());
}
return clang_getCursorSpelling(C);
case CXToken_Literal: {
// We have stashed the starting pointer in the ptr_data field. Use it.
const char *Text = static_cast<const char *>(CXTok.ptr_data);
- return createCXString(StringRef(Text, CXTok.int_data[2]));
+ return cxstring::createDup(StringRef(Text, CXTok.int_data[2]));
}
case CXToken_Punctuation:
if (Invalid)
return cxstring::createEmpty();
- return createCXString(Buffer.substr(LocInfo.second, CXTok.int_data[2]));
+ return cxstring::createDup(Buffer.substr(LocInfo.second, CXTok.int_data[2]));
}
CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
if (always_deprecated)
*always_deprecated = 1;
if (deprecated_message)
- *deprecated_message = cxstring::createCXString(Deprecated->getMessage());
+ *deprecated_message = cxstring::createDup(Deprecated->getMessage());
continue;
}
if (always_unavailable)
*always_unavailable = 1;
if (unavailable_message) {
- *unavailable_message
- = cxstring::createCXString(Unavailable->getMessage());
+ *unavailable_message = cxstring::createDup(Unavailable->getMessage());
}
continue;
}
if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(*A)) {
if (N < availability_size) {
availability[N].Platform
- = cxstring::createCXString(Avail->getPlatform()->getName());
+ = cxstring::createDup(Avail->getPlatform()->getName());
availability[N].Introduced = convertVersion(Avail->getIntroduced());
availability[N].Deprecated = convertVersion(Avail->getDeprecated());
availability[N].Obsoleted = convertVersion(Avail->getObsoleted());
availability[N].Unavailable = Avail->getUnavailable();
- availability[N].Message = cxstring::createCXString(Avail->getMessage());
+ availability[N].Message = cxstring::createDup(Avail->getMessage());
}
++N;
}
// Don't duplicate the string because RawText points directly into source
// code.
- return createCXString(RawText, false);
+ return cxstring::createRef(RawText);
}
CXString clang_Cursor_getBriefCommentText(CXCursor C) {
// Don't duplicate the string because RawComment ensures that this memory
// will not go away.
- return createCXString(BriefText, false);
+ return cxstring::createRef(BriefText);
}
return cxstring::createNull();
if (!CXMod)
return cxstring::createEmpty();
Module *Mod = static_cast<Module*>(CXMod);
- return createCXString(Mod->Name);
+ return cxstring::createDup(Mod->Name);
}
CXString clang_Module_getFullName(CXModule CXMod) {
if (!CXMod)
return cxstring::createEmpty();
Module *Mod = static_cast<Module*>(CXMod);
- return createCXString(Mod->getFullModuleName());
+ return cxstring::createDup(Mod->getFullModuleName());
}
unsigned clang_Module_getNumTopLevelHeaders(CXModule CXMod) {
extern "C" {
CXString clang_getClangVersion() {
- return createCXString(getClangFullVersion());
+ return cxstring::createDup(getClangFullVersion());
}
} // end: extern "C"
if (!CCStr)
return cxstring::createNull();
- return createCXString(CCStr->getParentContextName(), /*DupString=*/false);
+ return cxstring::createRef(CCStr->getParentContextName());
}
CXString
if (!Results)
return cxstring::createEmpty();
- return createCXString(Results->Selector);
+ return cxstring::createDup(Results->Selector);
}
} // end extern "C"
}
CXString getSpelling() const {
- return createCXString(StringRef(Message), false);
+ return cxstring::createRef(Message.c_str());
}
CXString getDiagnosticOption(CXString *Disable) const {
Out << "]";
}
- return createCXString(Out.str(), true);
+ return cxstring::createDup(Out.str());
}
unsigned clang_defaultDiagnosticDisplayOptions() {
CXString clang_getDiagnosticCategoryName(unsigned Category) {
// Kept for backwards compatibility.
- return createCXString(DiagnosticIDs::getCategoryNameFromID(Category));
+ return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category));
}
CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
USRGenerator UG;
UG << extractUSRSuffix(clang_getCString(classUSR));
UG->GenObjCIvar(name);
- return createCXString(UG.str(), true);
+ return cxstring::createDup(UG.str());
}
CXString clang_constructUSR_ObjCMethod(const char *name,
USRGenerator UG;
UG << extractUSRSuffix(clang_getCString(classUSR));
UG->GenObjCMethod(name, isInstanceMethod);
- return createCXString(UG.str(), true);
+ return cxstring::createDup(UG.str());
}
CXString clang_constructUSR_ObjCClass(const char *name) {
USRGenerator UG;
UG->GenObjCClass(name);
- return createCXString(UG.str(), true);
+ return cxstring::createDup(UG.str());
}
CXString clang_constructUSR_ObjCProtocol(const char *name) {
USRGenerator UG;
UG->GenObjCProtocol(name);
- return createCXString(UG.str(), true);
+ return cxstring::createDup(UG.str());
}
CXString clang_constructUSR_ObjCCategory(const char *class_name,
const char *category_name) {
USRGenerator UG;
UG->GenObjCCategory(class_name, category_name);
- return createCXString(UG.str(), true);
+ return cxstring::createDup(UG.str());
}
CXString clang_constructUSR_ObjCProperty(const char *property,
USRGenerator UG;
UG << extractUSRSuffix(clang_getCString(classUSR));
UG->GenObjCProperty(property);
- return createCXString(UG.str(), true);
+ return cxstring::createDup(UG.str());
}
} // end extern "C"
if (!TC)
return cxstring::createNull();
- return createCXString(TC->getText(), /*DupString=*/ false);
+ return cxstring::createRef(TC->getText());
}
CXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
return cxstring::createNull();
const CommandTraits &Traits = getCommandTraits(CXC);
- return createCXString(ICC->getCommandName(Traits), /*DupString=*/ false);
+ return cxstring::createRef(ICC->getCommandName(Traits));
}
enum CXCommentInlineCommandRenderKind
if (!ICC || ArgIdx >= ICC->getNumArgs())
return cxstring::createNull();
- return createCXString(ICC->getArgText(ArgIdx), /*DupString=*/ false);
+ return cxstring::createRef(ICC->getArgText(ArgIdx));
}
CXString clang_HTMLTagComment_getTagName(CXComment CXC) {
if (!HTC)
return cxstring::createNull();
- return createCXString(HTC->getTagName(), /*DupString=*/ false);
+ return cxstring::createRef(HTC->getTagName());
}
unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment CXC) {
if (!HST || AttrIdx >= HST->getNumAttrs())
return cxstring::createNull();
- return createCXString(HST->getAttr(AttrIdx).Name, /*DupString=*/ false);
+ return cxstring::createRef(HST->getAttr(AttrIdx).Name);
}
CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
if (!HST || AttrIdx >= HST->getNumAttrs())
return cxstring::createNull();
- return createCXString(HST->getAttr(AttrIdx).Value, /*DupString=*/ false);
+ return cxstring::createRef(HST->getAttr(AttrIdx).Value);
}
CXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
return cxstring::createNull();
const CommandTraits &Traits = getCommandTraits(CXC);
- return createCXString(BCC->getCommandName(Traits), /*DupString=*/ false);
+ return cxstring::createRef(BCC->getCommandName(Traits));
}
unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) {
if (!BCC || ArgIdx >= BCC->getNumArgs())
return cxstring::createNull();
- return createCXString(BCC->getArgText(ArgIdx), /*DupString=*/ false);
+ return cxstring::createRef(BCC->getArgText(ArgIdx));
}
CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
if (!PCC || !PCC->hasParamName())
return cxstring::createNull();
- return createCXString(PCC->getParamNameAsWritten(), /*DupString=*/ false);
+ return cxstring::createRef(PCC->getParamNameAsWritten());
}
unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) {
if (!TPCC || !TPCC->hasParamName())
return cxstring::createNull();
- return createCXString(TPCC->getParamNameAsWritten(), /*DupString=*/ false);
+ return cxstring::createRef(TPCC->getParamNameAsWritten());
}
unsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) {
if (!VBL)
return cxstring::createNull();
- return createCXString(VBL->getText(), /*DupString=*/ false);
+ return cxstring::createRef(VBL->getText());
}
CXString clang_VerbatimLineComment_getText(CXComment CXC) {
if (!VLC)
return cxstring::createNull();
- return createCXString(VLC->getText(), /*DupString=*/ false);
+ return cxstring::createRef(VLC->getText());
}
} // end extern "C"
SmallString<128> HTML;
CommentASTToHTMLConverter Converter(0, HTML, getCommandTraits(CXC));
Converter.visit(HTC);
- return createCXString(HTML.str(), /* DupString = */ true);
+ return cxstring::createDup(HTML.str());
}
CXString clang_FullComment_getAsHTML(CXComment CXC) {
SmallString<1024> HTML;
CommentASTToHTMLConverter Converter(FC, HTML, getCommandTraits(CXC));
Converter.visit(FC);
- return createCXString(HTML.str(), /* DupString = */ true);
+ return cxstring::createDup(HTML.str());
}
} // end extern "C"
*TU->FormatContext,
TU->FormatInMemoryUniqueId++);
Converter.visit(FC);
- return createCXString(XML.str(), /* DupString = */ true);
+ return cxstring::createDup(XML.str());
}
} // end extern "C"
}
CXString CXLoadedDiagnostic::getSpelling() const {
- return cxstring::createCXString(Spelling, false);
+ return cxstring::createRef(Spelling);
}
CXString CXLoadedDiagnostic::getDiagnosticOption(CXString *Disable) const {
// FIXME: possibly refactor with logic in CXStoredDiagnostic.
if (Disable)
- *Disable = createCXString((Twine("-Wno-") + DiagOption).str());
- return createCXString((Twine("-W") + DiagOption).str());
+ *Disable = cxstring::createDup((Twine("-Wno-") + DiagOption).str());
+ return cxstring::createDup((Twine("-W") + DiagOption).str());
}
unsigned CXLoadedDiagnostic::getCategory() const {
}
CXString CXLoadedDiagnostic::getCategoryText() const {
- return cxstring::createCXString(CategoryText);
+ return cxstring::createDup(CategoryText);
}
unsigned CXLoadedDiagnostic::getNumRanges() const {
if (error)
*error = code;
if (errorString)
- *errorString = createCXString(err);
+ *errorString = cxstring::createDup(err);
}
void reportInvalidFile(llvm::StringRef err) {
if (readString(TopDiags, RetStr, "FIXIT", Record, Blob,
/* allowEmptyString */ true))
return Failure;
- D->FixIts.push_back(std::make_pair(SR, createCXString(RetStr, false)));
+ D->FixIts.push_back(std::make_pair(SR, cxstring::createRef(RetStr)));
continue;
}
}
CXString CXStoredDiagnostic::getSpelling() const {
- return createCXString(Diag.getMessage(), false);
+ return cxstring::createRef(Diag.getMessage());
}
CXString CXStoredDiagnostic::getDiagnosticOption(CXString *Disable) const {
StringRef Option = DiagnosticIDs::getWarningOptionForDiag(ID);
if (!Option.empty()) {
if (Disable)
- *Disable = createCXString((Twine("-Wno-") + Option).str());
- return createCXString((Twine("-W") + Option).str());
+ *Disable = cxstring::createDup((Twine("-Wno-") + Option).str());
+ return cxstring::createDup((Twine("-W") + Option).str());
}
if (ID == diag::fatal_too_many_errors) {
CXString CXStoredDiagnostic::getCategoryText() const {
unsigned catID = DiagnosticIDs::getCategoryNumberForDiag(Diag.getID());
- return createCXString(DiagnosticIDs::getCategoryNameFromID(catID));
+ return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(catID));
}
unsigned CXStoredDiagnostic::getNumRanges() const {
*ReplacementRange = translateSourceRange(Diag.getLocation().getManager(),
LangOpts, Hint.RemoveRange);
}
- return createCXString(Hint.CodeToInsert);
+ return cxstring::createDup(Hint.CodeToInsert);
}
return Str;
}
-CXString cxstring::createCXString(StringRef String, bool DupString) {
+CXString cxstring::createRef(StringRef String) {
+ // If the string is not nul-terminated, we have to make a copy.
+ // This is doing a one past end read, and should be removed!
+ if (!String.empty() && String.data()[String.size()] != 0)
+ return cxstring::createDup(String);
+
CXString Result;
- if (DupString || (!String.empty() && String.data()[String.size()] != 0)) {
- char *Spelling = static_cast<char *>(malloc(String.size() + 1));
- memmove(Spelling, String.data(), String.size());
- Spelling[String.size()] = 0;
- Result.data = Spelling;
- Result.private_flags = (unsigned) CXS_Malloc;
- } else {
- Result.data = String.data();
- Result.private_flags = (unsigned) CXS_Unmanaged;
- }
+ Result.data = String.data();
+ Result.private_flags = (unsigned) CXS_Unmanaged;
+ return Result;
+}
+
+CXString cxstring::createDup(StringRef String) {
+ CXString Result;
+ char *Spelling = static_cast<char *>(malloc(String.size() + 1));
+ memmove(Spelling, String.data(), String.size());
+ Spelling[String.size()] = 0;
+ Result.data = Spelling;
+ Result.private_flags = (unsigned) CXS_Malloc;
return Result;
}
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
#include <vector>
+#include <string>
namespace clang {
namespace cxstring {
/// \p String can be changed or freed by the caller.
CXString createDup(const char *String);
-/// \brief Create a CXString object from a StringRef.
-CXString createCXString(StringRef String, bool DupString = true);
+/// \brief Create a CXString object from a StringRef. New CXString may
+/// contain a pointer to the undrelying data of \p String.
+///
+/// \p String should not be changed by the caller afterwards.
+CXString createRef(StringRef String);
+
+/// \brief Create a CXString object from a StringRef. New CXString will
+/// contain a copy of \p String.
+///
+/// \p String can be changed or freed by the caller.
+CXString createDup(StringRef String);
+
+// Usually std::string is intended to be used as backing storage for CXString.
+// In this case, call \c createRef(String.c_str()).
+//
+// If you need to make a copy, call \c createDup(StringRef(String)).
+CXString createRef(std::string String) LLVM_DELETED_FUNCTION;
/// \brief Create a CXString object that is backed by a string buffer.
CXString createCXString(CXStringBuf *buf);
Ctx.getObjCEncodingForType(Ty, encoding);
}
- return cxstring::createCXString(encoding);
+ return cxstring::createDup(encoding);
}
} // end: extern "C"