[PATCH] A new ADT: StringRefNulTerminated

Dmitri Gribenko gribozavr at gmail.com
Sat Feb 23 16:06:33 PST 2013


On Sun, Feb 24, 2013 at 1:55 AM, David Blaikie <dblaikie at gmail.com> wrote:
>> I don't follow - any user passing a char* to a function without a length
>> alongside it knows that they'd have to be null terminated. StringRef(const
>> char*) makes no more sense than StringRefNulTerminated(const char*) does it?
>> Except the former "forgets" about the null terminator, the latter does not.

So your point is that we already have this issue.  I agree, no need
for a special constructor then.  But should the
StringRefNulTerminated(const char*) constructor be implicit then?  See
discussion below.

> Could you provide an example of the bug someone could write if we had
> StringRefNulTerminated(const char*) that you couldn't write otherwise? (of
> course an API that needs to take a null terminated string that might not be
> a string literal would have to use a StringRef instead... which does have a
> (const char*) ctor - so where did that get us?)

I was thinking of something like:

StringRef bar();

StringRefNulTerminated foo(Foo Val) {
  switch(Val) {
  case Foo_A: return "aaa";
  case Foo_B: return "bbb";
  case Foo_C: return bar().data(); // bug, did not compile in v3 of the patch
  }
}

If the programmer wants to force it to compile, the line with the bug
will stand out.  Since there's an explicit constructor call, it sounds
like a promise 'I know it is nul-terminated'.

StringRefNulTerminated foo(Foo Val) {
  switch(Val) {
  case Foo_A: return "aaa";
  case Foo_B: return "bbb";
  case Foo_C: return StringRefNulTerminated(bar().data()); // bug
  }
}

After removing the templated constructor, it would be written like this:

StringRefNulTerminated foo(Foo Val) {
  switch(Val) {
  case Foo_A: return StringRefNulTerminated("aaa");
  case Foo_B: return StringRefNulTerminated("bbb");
  case Foo_C: return StringRefNulTerminated(bar().data()); // bug
  }
}

which is ugly, and provokes such bugs.

If we make the 'const char *' constructor implicit, the syntactic
noise would be reduced, though.

Dmitri

-- 
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/



More information about the llvm-commits mailing list