]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/d/dmd/doc.c
ipa-param-manip: Be careful about a reallocating hash_map
[thirdparty/gcc.git] / gcc / d / dmd / doc.c
index eaae8c3b6537489fc7471c3c437ed12836098d24..5d2da1ccdb91f974c10b1312135716a1037a9123 100644 (file)
@@ -1,6 +1,6 @@
 
 /* Compiler implementation of the D programming language
- * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
+ * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
  * written by Walter Bright
  * http://www.digitalmars.com
  * Distributed under the Boost Software License, Version 1.0.
@@ -124,10 +124,10 @@ int utfStride(const utf8_t *p);
 // Workaround for missing Parameter instance for variadic params. (it's unnecessary to instantiate one).
 bool isCVariadicParameter(Dsymbols *a, const utf8_t *p, size_t len)
 {
-    for (size_t i = 0; i < a->dim; i++)
+    for (size_t i = 0; i < a->length; i++)
     {
         TypeFunction *tf = isTypeFunction((*a)[i]);
-        if (tf && tf->varargs == 1 && cmp("...", p, len) == 0)
+        if (tf && tf->parameterList.varargs == VARARGvariadic && cmp("...", p, len) == 0)
             return true;
     }
     return false;
@@ -138,11 +138,11 @@ bool isCVariadicParameter(Dsymbols *a, const utf8_t *p, size_t len)
 static Parameter *isFunctionParameter(Dsymbol *s, const utf8_t *p, size_t len)
 {
     TypeFunction *tf = isTypeFunction(s);
-    if (tf && tf->parameters)
+    if (tf && tf->parameterList.parameters)
     {
-        for (size_t k = 0; k < tf->parameters->dim; k++)
+        for (size_t k = 0; k < tf->parameterList.parameters->length; k++)
         {
-            Parameter *fparam = (*tf->parameters)[k];
+            Parameter *fparam = (*tf->parameterList.parameters)[k];
             if (fparam->ident && cmp(fparam->ident->toChars(), p, len) == 0)
             {
                 return fparam;
@@ -173,7 +173,7 @@ static Dsymbol *getEponymousMember(TemplateDeclaration *td)
  */
 static Parameter *isEponymousFunctionParameter(Dsymbols *a, const utf8_t *p, size_t len)
 {
-    for (size_t i = 0; i < a->dim; i++)
+    for (size_t i = 0; i < a->length; i++)
     {
         TemplateDeclaration *td = (*a)[i]->isTemplateDeclaration();
         if (td && td->onemember)
@@ -351,12 +351,12 @@ void gendocfile(Module *m)
         // Override with DDOCFILE specified in the sc.ini file
         char *p = getenv("DDOCFILE");
         if (p)
-            global.params.ddocfiles->shift(p);
+            global.params.ddocfiles.shift(p);
 
         // Override with the ddoc macro files from the command line
-        for (size_t i = 0; i < global.params.ddocfiles->dim; i++)
+        for (size_t i = 0; i < global.params.ddocfiles.length; i++)
         {
-            FileName f((*global.params.ddocfiles)[i]);
+            FileName f(global.params.ddocfiles[i]);
             File file(&f);
             readFile(m->loc, &file);
             // BUG: convert file contents to UTF-8 before use
@@ -365,7 +365,7 @@ void gendocfile(Module *m)
             mbuf.write(file.buffer, file.len);
         }
     }
-    DocComment::parseMacros(&m->escapetable, &m->macrotable, (utf8_t *)mbuf.data, mbuf.offset);
+    DocComment::parseMacros(&m->escapetable, &m->macrotable, (utf8_t *)mbuf.slice().ptr, mbuf.length());
 
     Scope *sc = Scope::createGlobal(m);      // create root scope
 
@@ -427,12 +427,12 @@ void gendocfile(Module *m)
         emitMemberComments(m, &buf, sc);
     }
 
-    //printf("BODY= '%.*s'\n", buf.offset, buf.data);
-    Macro::define(&m->macrotable, (const utf8_t *)"BODY", 4, (const utf8_t *)buf.data, buf.offset);
+    //printf("BODY= '%.*s'\n", buf.length(), buf.slice().ptr);
+    Macro::define(&m->macrotable, (const utf8_t *)"BODY", 4, (const utf8_t *)buf.slice().ptr, buf.length());
 
     OutBuffer buf2;
     buf2.writestring("$(DDOC)\n");
-    size_t end = buf2.offset;
+    size_t end = buf2.length();
     m->macrotable->expand(&buf2, 0, &end, NULL, 0);
 
     /* Remove all the escape sequences from buf2,
@@ -440,12 +440,12 @@ void gendocfile(Module *m)
      */
     {
         buf.setsize(0);
-        buf.reserve(buf2.offset);
-        utf8_t *p = (utf8_t *)buf2.data;
-        for (size_t j = 0; j < buf2.offset; j++)
+        buf.reserve(buf2.length());
+        utf8_t *p = (utf8_t *)buf2.slice().ptr;
+        for (size_t j = 0; j < buf2.length(); j++)
         {
             utf8_t c = p[j];
-            if (c == 0xFF && j + 1 < buf2.offset)
+            if (c == 0xFF && j + 1 < buf2.length())
             {
                 j++;
                 continue;
@@ -455,7 +455,7 @@ void gendocfile(Module *m)
             else if (c == '\r')
             {
                 buf.writestring("\r\n");
-                if (j + 1 < buf2.offset && p[j + 1] == '\n')
+                if (j + 1 < buf2.length() && p[j + 1] == '\n')
                 {
                     j++;
                 }
@@ -467,7 +467,7 @@ void gendocfile(Module *m)
 
     // Transfer image to file
     assert(m->docfile);
-    m->docfile->setbuffer(buf.data, buf.offset);
+    m->docfile->setbuffer(buf.slice().ptr, buf.length());
     m->docfile->ref = 1;
     ensurePathToNameExists(Loc(), m->docfile->toChars());
     writeFile(m->loc, m->docfile);
@@ -482,9 +482,9 @@ void gendocfile(Module *m)
  */
 void escapeDdocString(OutBuffer *buf, size_t start)
 {
-    for (size_t u = start; u < buf->offset; u++)
+    for (size_t u = start; u < buf->length(); u++)
     {
-        utf8_t c = buf->data[u];
+        utf8_t c = buf->slice().ptr[u];
         switch(c)
         {
             case '$':
@@ -518,9 +518,9 @@ void escapeStrayParenthesis(Loc loc, OutBuffer *buf, size_t start)
 {
     unsigned par_open = 0;
 
-    for (size_t u = start; u < buf->offset; u++)
+    for (size_t u = start; u < buf->length(); u++)
     {
-        utf8_t c = buf->data[u];
+        utf8_t c = buf->slice().ptr[u];
         switch(c)
         {
             case '(':
@@ -546,10 +546,10 @@ void escapeStrayParenthesis(Loc loc, OutBuffer *buf, size_t start)
     if (par_open)                       // if any unmatched lparens
     {
         par_open = 0;
-        for (size_t u = buf->offset; u > start;)
+        for (size_t u = buf->length(); u > start;)
         {
             u--;
-            utf8_t c = buf->data[u];
+            utf8_t c = buf->slice().ptr[u];
             switch(c)
             {
                 case ')':
@@ -622,7 +622,7 @@ static void emitAnchor(OutBuffer *buf, Dsymbol *s, Scope *sc)
     {
         OutBuffer anc;
         emitAnchorName(&anc, s, skipNonQualScopes(sc));
-        ident = Identifier::idPool(anc.peekString());
+        ident = Identifier::idPool(anc.peekChars());
     }
     size_t *count = (size_t*)dmd_aaGet(&sc->anchorCounts, (void *)ident);
     TemplateDeclaration *td = getEponymousParent(s);
@@ -663,12 +663,13 @@ static size_t getCodeIndent(const char *src)
 /** Recursively expand template mixin member docs into the scope. */
 static void expandTemplateMixinComments(TemplateMixin *tm, OutBuffer *buf, Scope *sc)
 {
-    if (!tm->semanticRun) tm->semantic(sc);
+    if (!tm->semanticRun)
+        dsymbolSemantic(tm, sc);
     TemplateDeclaration *td = (tm && tm->tempdecl) ?
         tm->tempdecl->isTemplateDeclaration() : NULL;
     if (td && td->members)
     {
-        for (size_t i = 0; i < td->members->dim; i++)
+        for (size_t i = 0; i < td->members->length; i++)
         {
             Dsymbol *sm = (*td->members)[i];
             TemplateMixin *tmc = sm->isTemplateMixin();
@@ -699,13 +700,13 @@ void emitMemberComments(ScopeDsymbol *sds, OutBuffer *buf, Scope *sc)
     else if (sds->isModule())
         m = "$(DDOC_MODULE_MEMBERS ";
 
-    size_t offset1 = buf->offset;         // save starting offset
+    size_t offset1 = buf->length();         // save starting offset
     buf->writestring(m);
-    size_t offset2 = buf->offset;         // to see if we write anything
+    size_t offset2 = buf->length();         // to see if we write anything
 
     sc = sc->push(sds);
 
-    for (size_t i = 0; i < sds->members->dim; i++)
+    for (size_t i = 0; i < sds->members->length; i++)
     {
         Dsymbol *s = (*sds->members)[i];
         //printf("\ts = '%s'\n", s->toChars());
@@ -720,11 +721,11 @@ void emitMemberComments(ScopeDsymbol *sds, OutBuffer *buf, Scope *sc)
 
     sc->pop();
 
-    if (buf->offset == offset2)
+    if (buf->length() == offset2)
     {
         /* Didn't write out any members, so back out last write
          */
-        buf->offset = offset1;
+        buf->setsize(offset1);
     }
     else
         buf->writestring(")\n");
@@ -732,7 +733,7 @@ void emitMemberComments(ScopeDsymbol *sds, OutBuffer *buf, Scope *sc)
 
 void emitProtection(OutBuffer *buf, Prot prot)
 {
-    if (prot.kind != PROTundefined && prot.kind != PROTpublic)
+    if (prot.kind != Prot::undefined && prot.kind != Prot::public_)
     {
         protectionToBuffer(buf, prot);
         buf->writeByte(' ');
@@ -774,13 +775,13 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
             {
                 // Put the declaration signatures as the document 'title'
                 buf->writestring(ddoc_decl_s);
-                for (size_t i = 0; i < dc->a.dim; i++)
+                for (size_t i = 0; i < dc->a.length; i++)
                 {
                     Dsymbol *sx = dc->a[i];
 
                     if (i == 0)
                     {
-                        size_t o = buf->offset;
+                        size_t o = buf->length();
                         toDocBuffer(sx, buf, sc);
                         highlightCode(sc, sx, buf, o);
                         continue;
@@ -788,7 +789,7 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
 
                     buf->writestring("$(DDOC_DITTO ");
                     {
-                        size_t o = buf->offset;
+                        size_t o = buf->length();
                         toDocBuffer(sx, buf, sc);
                         highlightCode(sc, sx, buf, o);
                     }
@@ -804,7 +805,7 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
                         emitMemberComments(sds, buf, sc);
                 }
                 buf->writestring(ddoc_decl_dd_e);
-                //printf("buf.2 = [[%.*s]]\n", buf->offset - o0, buf->data + o0);
+                //printf("buf.2 = [[%.*s]]\n", buf->length() - o0, buf->slice().ptr + o0);
             }
 
             if (s)
@@ -833,7 +834,7 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
                     return;
                 if (!d->type && !d->isCtorDeclaration() && !d->isAliasDeclaration())
                     return;
-                if (d->protection.kind == PROTprivate || sc->protection.kind == PROTprivate)
+                if (d->protection.kind == Prot::private_ || sc->protection.kind == Prot::private_)
                     return;
             }
             if (!com)
@@ -855,7 +856,7 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
             }
             else
             {
-                if (ad->prot().kind == PROTprivate || sc->protection.kind == PROTprivate)
+                if (ad->prot().kind == Prot::private_ || sc->protection.kind == Prot::private_)
                     return;
                 if (!ad->comment)
                     return;
@@ -869,7 +870,7 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
         void visit(TemplateDeclaration *td)
         {
             //printf("TemplateDeclaration::emitComment() '%s', kind = %s\n", td->toChars(), td->kind());
-            if (td->prot().kind == PROTprivate || sc->protection.kind == PROTprivate)
+            if (td->prot().kind == Prot::private_ || sc->protection.kind == Prot::private_)
                 return;
             if (!td->comment)
                 return;
@@ -884,11 +885,11 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
 
         void visit(EnumDeclaration *ed)
         {
-            if (ed->prot().kind == PROTprivate || sc->protection.kind == PROTprivate)
+            if (ed->prot().kind == Prot::private_ || sc->protection.kind == Prot::private_)
                 return;
             if (ed->isAnonymous() && ed->members)
             {
-                for (size_t i = 0; i < ed->members->dim; i++)
+                for (size_t i = 0; i < ed->members->length; i++)
                 {
                     Dsymbol *s = (*ed->members)[i];
                     emitComment(s, buf, sc);
@@ -906,7 +907,7 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
         void visit(EnumMember *em)
         {
             //printf("EnumMember::emitComment(%p '%s'), comment = '%s'\n", em, em->toChars(), em->comment);
-            if (em->prot().kind == PROTprivate || sc->protection.kind == PROTprivate)
+            if (em->prot().kind == Prot::private_ || sc->protection.kind == Prot::private_)
                 return;
             if (!em->comment)
                 return;
@@ -926,11 +927,11 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
              * Hence, Ddoc omits attributes from template members.
              */
 
-            Dsymbols *d = ad->include(NULL, NULL);
+            Dsymbols *d = ad->include(NULL);
 
             if (d)
             {
-                for (size_t i = 0; i < d->dim; i++)
+                for (size_t i = 0; i < d->length; i++)
                 {
                     Dsymbol *s = (*d)[i];
                     //printf("AttribDeclaration::emitComment %s\n", s->toChars());
@@ -962,10 +963,10 @@ void emitComment(Dsymbol *s, OutBuffer *buf, Scope *sc)
             }
 
             /* If generating doc comment, be careful because if we're inside
-             * a template, then include(NULL, NULL) will fail.
+             * a template, then include(NULL) will fail.
              */
             Dsymbols *d = cd->decl ? cd->decl : cd->elsedecl;
-            for (size_t i = 0; i < d->dim; i++)
+            for (size_t i = 0; i < d->length; i++)
             {
                 Dsymbol *s = (*d)[i];
                 emitComment(s, buf, sc);
@@ -1067,9 +1068,9 @@ void toDocBuffer(Dsymbol *s, OutBuffer *buf, Scope *sc)
             if (d->isVarDeclaration() && td)
             {
                 buf->writeByte('(');
-                if (td->origParameters && td->origParameters->dim)
+                if (td->origParameters && td->origParameters->length)
                 {
-                    for (size_t i = 0; i < td->origParameters->dim; i++)
+                    for (size_t i = 0; i < td->origParameters->length; i++)
                     {
                         if (i)
                             buf->writestring(", ");
@@ -1105,9 +1106,9 @@ void toDocBuffer(Dsymbol *s, OutBuffer *buf, Scope *sc)
             emitProtection(buf, ad->protection);
             buf->printf("alias %s = ", ad->toChars());
 
-            if (Dsymbol *s = ad->aliassym)  // ident alias
+            if (Dsymbol *sa = ad->aliassym)  // ident alias
             {
-                prettyPrintDsymbol(s, ad->parent);
+                prettyPrintDsymbol(sa, ad->parent);
             }
             else if (Type *type = ad->getType())  // type alias
             {
@@ -1219,7 +1220,7 @@ void toDocBuffer(Dsymbol *s, OutBuffer *buf, Scope *sc)
                 buf->printf("%s %s", cd->kind(), cd->toChars());
             }
             int any = 0;
-            for (size_t i = 0; i < cd->baseclasses->dim; i++)
+            for (size_t i = 0; i < cd->baseclasses->length; i++)
             {
                 BaseClass *bc = (*cd->baseclasses)[i];
 
@@ -1233,7 +1234,7 @@ void toDocBuffer(Dsymbol *s, OutBuffer *buf, Scope *sc)
                     buf->writestring(": ");
                     any = 1;
                 }
-                emitProtection(buf, Prot(PROTpublic));
+                emitProtection(buf, Prot(Prot::public_));
                 if (bc->sym)
                 {
                     buf->printf("$(DDOC_PSUPER_SYMBOL %s)", bc->sym->toPrettyChars());
@@ -1288,7 +1289,7 @@ DocComment *DocComment::parse(Dsymbol *s, const utf8_t *comment)
 
     dc->parseSections(comment);
 
-    for (size_t i = 0; i < dc->sections.dim; i++)
+    for (size_t i = 0; i < dc->sections.length; i++)
     {
         Section *sec = dc->sections[i];
 
@@ -1444,7 +1445,7 @@ void DocComment::parseSections(const utf8_t *comment)
 
 void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
 {
-    assert(a->dim);
+    assert(a->length);
 
     //printf("DocComment::writeSections()\n");
     Loc loc = (*a)[0]->loc;
@@ -1454,11 +1455,11 @@ void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
             loc = m->md->loc;
     }
 
-    size_t offset1 = buf->offset;
+    size_t offset1 = buf->length();
     buf->writestring("$(DDOC_SECTIONS ");
-    size_t offset2 = buf->offset;
+    size_t offset2 = buf->length();
 
-    for (size_t i = 0; i < sections.dim; i++)
+    for (size_t i = 0; i < sections.length; i++)
     {
         Section *sec = sections[i];
         if (sec->nooutput)
@@ -1468,7 +1469,7 @@ void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
         if (!sec->namelen && i == 0)
         {
             buf->writestring("$(DDOC_SUMMARY ");
-            size_t o = buf->offset;
+            size_t o = buf->length();
             buf->write(sec->body, sec->bodylen);
             escapeStrayParenthesis(loc, buf, o);
             highlightText(sc, a, buf, o);
@@ -1478,7 +1479,7 @@ void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
             sec->write(loc, this, sc, a, buf);
     }
 
-    for (size_t i = 0; i < a->dim; i++)
+    for (size_t i = 0; i < a->length; i++)
     {
         Dsymbol *s = (*a)[i];
         if (Dsymbol *td = getEponymousParent(s))
@@ -1486,7 +1487,7 @@ void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
 
         for (UnitTestDeclaration *utd = s->ddocUnittest; utd; utd = utd->ddocUnittest)
         {
-            if (utd->protection.kind == PROTprivate || !utd->comment || !utd->fbody)
+            if (utd->protection.kind == Prot::private_ || !utd->comment || !utd->fbody)
                 continue;
 
             // Strip whitespaces to avoid showing empty summary
@@ -1495,7 +1496,7 @@ void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
 
             buf->writestring("$(DDOC_EXAMPLES ");
 
-            size_t o = buf->offset;
+            size_t o = buf->length();
             buf->writestring((const char *)c);
 
             if (utd->codedoc)
@@ -1512,11 +1513,11 @@ void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
         }
     }
 
-    if (buf->offset == offset2)
+    if (buf->length() == offset2)
     {
         /* Didn't write out any sections, so back out last write
          */
-        buf->offset = offset1;
+        buf->setsize(offset1);
         buf->writestring("$(DDOC_BLANKLINE)\n");
     }
     else
@@ -1528,7 +1529,7 @@ void DocComment::writeSections(Scope *sc, Dsymbols *a, OutBuffer *buf)
 
 void Section::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffer *buf)
 {
-    assert(a->dim);
+    assert(a->length);
 
     if (namelen)
     {
@@ -1553,7 +1554,7 @@ void Section::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffer *bu
 
             // Replace _ characters with spaces
             buf->writestring("$(DDOC_SECTION_H ");
-            size_t o = buf->offset;
+            size_t o = buf->length();
             for (size_t u = 0; u < namelen; u++)
             {
                 utf8_t c = name[u];
@@ -1567,7 +1568,7 @@ void Section::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffer *bu
         buf->writestring("$(DDOC_DESCRIPTION ");
     }
   L1:
-    size_t o = buf->offset;
+    size_t o = buf->length();
     buf->write(body, bodylen);
     escapeStrayParenthesis(loc, buf, o);
     highlightText(sc, a, buf, o);
@@ -1579,7 +1580,7 @@ void Section::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffer *bu
 
 void ParamSection::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffer *buf)
 {
-    assert(a->dim);
+    assert(a->length);
     Dsymbol *s = (*a)[0];   // test
 
     const utf8_t *p = body;
@@ -1655,7 +1656,7 @@ void ParamSection::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffe
             {
                 buf->writestring("$(DDOC_PARAM_ID ");
                 {
-                    size_t o = buf->offset;
+                    size_t o = buf->length();
                     Parameter *fparam = isFunctionParameter(a, namestart, namelen);
                     if (!fparam)
                     {
@@ -1692,7 +1693,7 @@ void ParamSection::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffe
 
                 buf->writestring("$(DDOC_PARAM_DESC ");
                 {
-                    size_t o = buf->offset;
+                    size_t o = buf->length();
                     buf->write(textstart, textlen);
                     escapeStrayParenthesis(loc, buf, o);
                     highlightText(sc, a, buf, o);
@@ -1730,10 +1731,11 @@ void ParamSection::write(Loc loc, DocComment *, Scope *sc, Dsymbols *a, OutBuffe
         goto L1;                // write out last one
     buf->writestring(")\n");
 
-    TypeFunction *tf = a->dim == 1 ? isTypeFunction(s) : NULL;
+    TypeFunction *tf = a->length == 1 ? isTypeFunction(s) : NULL;
     if (tf)
     {
-        size_t pcount = (tf->parameters ? tf->parameters->dim : 0) + (int)(tf->varargs == 1);
+        size_t pcount = (tf->parameterList.parameters ? tf->parameterList.parameters->length : 0) +
+                        (int)(tf->parameterList.varargs == VARARGvariadic);
         if (pcount != paramcount)
         {
             warning(s->loc, "Ddoc: parameter count mismatch");
@@ -1998,12 +2000,12 @@ const utf8_t *skipwhitespace(const utf8_t *p)
 
 size_t skiptoident(OutBuffer *buf, size_t i)
 {
-    while (i < buf->offset)
+    while (i < buf->length())
     {
         dchar_t c;
 
         size_t oi = i;
-        if (utf_decodeChar((utf8_t *)buf->data, buf->offset, &i, &c))
+        if (utf_decodeChar((utf8_t *)buf->slice().ptr, buf->length(), &i, &c))
         {
             /* Ignore UTF errors, but still consume input
              */
@@ -2028,12 +2030,12 @@ size_t skiptoident(OutBuffer *buf, size_t i)
 
 size_t skippastident(OutBuffer *buf, size_t i)
 {
-    while (i < buf->offset)
+    while (i < buf->length())
     {
         dchar_t c;
 
         size_t oi = i;
-        if (utf_decodeChar((utf8_t *)buf->data, buf->offset, &i, &c))
+        if (utf_decodeChar((utf8_t *)buf->slice().ptr, buf->length(), &i, &c))
         {
             /* Ignore UTF errors, but still consume input
              */
@@ -2063,8 +2065,8 @@ size_t skippastident(OutBuffer *buf, size_t i)
 
 size_t skippastURL(OutBuffer *buf, size_t i)
 {
-    size_t length = buf->offset - i;
-    utf8_t *p = (utf8_t *)&buf->data[i];
+    size_t length = buf->length() - i;
+    utf8_t *p = (utf8_t *)&buf->slice().ptr[i];
     size_t j;
     unsigned sawdot = 0;
 
@@ -2109,7 +2111,7 @@ Lno:
 
 bool isIdentifier(Dsymbols *a, const utf8_t *p, size_t len)
 {
-    for (size_t i = 0; i < a->dim; i++)
+    for (size_t i = 0; i < a->length; i++)
     {
         const char *s = (*a)[i]->ident->toChars();
         if (cmp(s, p, len) == 0)
@@ -2156,7 +2158,7 @@ TypeFunction *isTypeFunction(Dsymbol *s)
 
 Parameter *isFunctionParameter(Dsymbols *a, const utf8_t *p, size_t len)
 {
-    for (size_t i = 0; i < a->dim; i++)
+    for (size_t i = 0; i < a->length; i++)
     {
         Parameter *fparam = isFunctionParameter((*a)[i], p, len);
         if (fparam)
@@ -2172,7 +2174,7 @@ Parameter *isFunctionParameter(Dsymbols *a, const utf8_t *p, size_t len)
 
 TemplateParameter *isTemplateParameter(Dsymbols *a, const utf8_t *p, size_t len)
 {
-    for (size_t i = 0; i < a->dim; i++)
+    for (size_t i = 0; i < a->length; i++)
     {
         TemplateDeclaration *td = (*a)[i]->isTemplateDeclaration();
         // Check for the parent, if the current symbol is not a template declaration.
@@ -2180,7 +2182,7 @@ TemplateParameter *isTemplateParameter(Dsymbols *a, const utf8_t *p, size_t len)
             td = getEponymousParent((*a)[i]);
         if (td && td->origParameters)
         {
-            for (size_t k = 0; k < td->origParameters->dim; k++)
+            for (size_t k = 0; k < td->origParameters->length; k++)
             {
                 TemplateParameter *tp = (*td->origParameters)[k];
                 if (tp->ident && cmp(tp->ident->toChars(), p, len) == 0)
@@ -2222,7 +2224,7 @@ bool isReservedName(utf8_t *str, size_t len)
 
 void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 {
-    Dsymbol *s = a->dim ? (*a)[0] : NULL;   // test
+    Dsymbol *s = a->length ? (*a)[0] : NULL;   // test
 
     //printf("highlightText()\n");
 
@@ -2235,9 +2237,9 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 
     size_t iLineStart = offset;
 
-    for (size_t i = offset; i < buf->offset; i++)
+    for (size_t i = offset; i < buf->length(); i++)
     {
-        utf8_t c = buf->data[i];
+        utf8_t c = buf->slice().ptr[i];
 
      Lcont:
         switch (c)
@@ -2264,7 +2266,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                 }
 
                 if (!sc->_module->isDocFile &&
-                    !inCode && i == iLineStart && i + 1 < buf->offset)    // if "\n\n"
+                    !inCode && i == iLineStart && i + 1 < buf->length())    // if "\n\n"
                 {
                     static const char blankline[] = "$(DDOC_BLANKLINE)\n";
 
@@ -2279,7 +2281,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                 leadingBlank = 0;
                 if (inCode)
                     break;
-                utf8_t *p = (utf8_t *)&buf->data[i];
+                utf8_t *p = (utf8_t *)&buf->slice().ptr[i];
                 const char *se = sc->_module->escapetable->escapeChar('<');
                 if (se && strcmp(se, "&lt;") == 0)
                 {
@@ -2291,7 +2293,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                         p += 4;
                         while (1)
                         {
-                            if (j == buf->offset)
+                            if (j == buf->length())
                                 goto L1;
                             if (p[0] == '-' && p[1] == '-' && p[2] == '>')
                             {
@@ -2311,7 +2313,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                         p += 2;
                         while (1)
                         {
-                            if (j == buf->offset)
+                            if (j == buf->length())
                                 break;
                             if (p[0] == '>')
                             {
@@ -2356,7 +2358,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                 leadingBlank = 0;
                 if (inCode)
                     break;
-                utf8_t *p = (utf8_t *)&buf->data[i];
+                utf8_t *p = (utf8_t *)&buf->slice().ptr[i];
                 if (p[1] == '#' || isalpha(p[1]))
                     break;                      // already a character entity
                 // Replace '&' with '&amp;' character entity
@@ -2379,7 +2381,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 
                     OutBuffer codebuf;
 
-                    codebuf.write(buf->data + iCodeStart + 1, i - (iCodeStart + 1));
+                    codebuf.write(buf->slice().ptr + iCodeStart + 1, i - (iCodeStart + 1));
 
                     // escape the contents, but do not perform highlighting except for DDOC_PSYMBOL
                     highlightCode(sc, a, &codebuf, 0);
@@ -2388,7 +2390,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 
                     static const char pre[] = "$(DDOC_BACKQUOTED ";
                     i = buf->insert(iCodeStart, pre, strlen(pre));
-                    i = buf->insert(i, (char *)codebuf.data, codebuf.offset);
+                    i = buf->insert(i, (char *)codebuf.slice().ptr, codebuf.length());
                     i = buf->insert(i, ")", 1);
 
                     i--; // point to the ending ) so when the for loop does i++, it will see the next character
@@ -2424,9 +2426,9 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                     while (1)
                     {
                         ++i;
-                        if (i >= buf->offset)
+                        if (i >= buf->length())
                             break;
-                        c = buf->data[i];
+                        c = buf->slice().ptr[i];
                         if (c == '\n')
                         {
                             eollen = 1;
@@ -2435,9 +2437,9 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                         if (c == '\r')
                         {
                             eollen = 1;
-                            if (i + 1 >= buf->offset)
+                            if (i + 1 >= buf->length())
                                 break;
-                            if (buf->data[i + 1] == '\n')
+                            if (buf->slice().ptr[i + 1] == '\n')
                             {
                                 eollen = 2;
                                 break;
@@ -2469,13 +2471,13 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                         // The code section is from iCodeStart to i
                         OutBuffer codebuf;
 
-                        codebuf.write(buf->data + iCodeStart, i - iCodeStart);
+                        codebuf.write(buf->slice().ptr + iCodeStart, i - iCodeStart);
                         codebuf.writeByte(0);
 
                         // Remove leading indentations from all lines
                         bool lineStart = true;
-                        utf8_t *endp = (utf8_t *)codebuf.data + codebuf.offset;
-                        for (utf8_t *p = (utf8_t *)codebuf.data; p < endp; )
+                        utf8_t *endp = (utf8_t *)codebuf.slice().ptr + codebuf.length();
+                        for (utf8_t *p = (utf8_t *)codebuf.slice().ptr; p < endp; )
                         {
                             if (lineStart)
                             {
@@ -2483,11 +2485,11 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                                 utf8_t *q = p;
                                 while (j-- > 0 && q < endp && isIndentWS(q))
                                     ++q;
-                                codebuf.remove(p - (utf8_t *)codebuf.data, q - p);
-                                assert((utf8_t *)codebuf.data <= p);
-                                assert(p < (utf8_t *)codebuf.data + codebuf.offset);
+                                codebuf.remove(p - (utf8_t *)codebuf.slice().ptr, q - p);
+                                assert((utf8_t *)codebuf.slice().ptr <= p);
+                                assert(p < (utf8_t *)codebuf.slice().ptr + codebuf.length());
                                 lineStart = false;
-                                endp = (utf8_t *)codebuf.data + codebuf.offset; // update
+                                endp = (utf8_t *)codebuf.slice().ptr + codebuf.length(); // update
                                 continue;
                             }
                             if (*p == '\n')
@@ -2497,7 +2499,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 
                         highlightCode2(sc, a, &codebuf, 0);
                         buf->remove(iCodeStart, i - iCodeStart);
-                        i = buf->insert(iCodeStart, codebuf.data, codebuf.offset);
+                        i = buf->insert(iCodeStart, codebuf.slice().ptr, codebuf.length());
                         i = buf->insert(i, (const char *)")\n", 2);
                         i -= 2; // in next loop, c should be '\n'
                     }
@@ -2520,7 +2522,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                 if (sc->_module->isDocFile || inCode)
                     break;
 
-                utf8_t *start = (utf8_t *)buf->data + i;
+                utf8_t *start = (utf8_t *)buf->slice().ptr + i;
                 if (isIdStart(start))
                 {
                     size_t j = skippastident(buf, i);
@@ -2540,7 +2542,7 @@ void highlightText(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
                     // leading '_' means no highlight unless it's a reserved symbol name
                     if (c == '_' &&
                         (i == 0 || !isdigit(*(start - 1))) &&
-                        (i == buf->offset - 1 || !isReservedName(start, len)))
+                        (i == buf->length() - 1 || !isReservedName(start, len)))
                     {
                         buf->remove(i, 1);
                         i = j - 1;
@@ -2581,8 +2583,8 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset)
     //printf("highlightCode(s = %s '%s')\n", s->kind(), s->toChars());
     OutBuffer ancbuf;
     emitAnchor(&ancbuf, s, sc);
-    buf->insert(offset, (char *)ancbuf.data, ancbuf.offset);
-    offset += ancbuf.offset;
+    buf->insert(offset, (char *)ancbuf.slice().ptr, ancbuf.length());
+    offset += ancbuf.length();
 
     Dsymbols a;
     a.push(s);
@@ -2596,9 +2598,9 @@ void highlightCode(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 {
     //printf("highlightCode(a = '%s')\n", a->toChars());
 
-    for (size_t i = offset; i < buf->offset; i++)
+    for (size_t i = offset; i < buf->length(); i++)
     {
-        utf8_t c = buf->data[i];
+        utf8_t c = buf->slice().ptr[i];
         const char *se = sc->_module->escapetable->escapeChar(c);
         if (se)
         {
@@ -2609,7 +2611,7 @@ void highlightCode(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
             continue;
         }
 
-        utf8_t *start = (utf8_t *)buf->data + i;
+        utf8_t *start = (utf8_t *)buf->slice().ptr + i;
         if (isIdStart(start))
         {
             size_t j = skippastident(buf, i);
@@ -2655,12 +2657,12 @@ void highlightCode3(Scope *sc, OutBuffer *buf, const utf8_t *p, const utf8_t *pe
 void highlightCode2(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
 {
     unsigned errorsave = global.errors;
-    Lexer lex(NULL, (utf8_t *)buf->data, 0, buf->offset - 1, 0, 1);
+    Lexer lex(NULL, (utf8_t *)buf->slice().ptr, 0, buf->length() - 1, 0, 1);
     OutBuffer res;
-    const utf8_t *lastp = (utf8_t *)buf->data;
+    const utf8_t *lastp = (utf8_t *)buf->slice().ptr;
 
-    //printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data);
-    res.reserve(buf->offset);
+    //printf("highlightCode2('%.*s')\n", buf->length() - 1, buf->slice().ptr);
+    res.reserve(buf->length());
     while (1)
     {
         Token tok;
@@ -2704,7 +2706,7 @@ void highlightCode2(Scope *sc, Dsymbols *a, OutBuffer *buf, size_t offset)
         if (highlight)
         {
             res.writestring(highlight);
-            size_t o = res.offset;
+            size_t o = res.length();
             highlightCode3(sc, &res, tok.ptr, lex.p);
             if (tok.value == TOKcomment || tok.value == TOKstring)
                 escapeDdocString(&res, o);  // Bugzilla 7656, 7715, and 10519