Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/core/sys/posix/stdio.d
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,7 @@ unittest
assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0);
assert(fclose(f) == 0);
}


ssize_t getdelim (char** lineptr, size_t* n, int delimiter, FILE* stream);
ssize_t getline (char** lineptr, size_t* n, FILE* stream);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ssize_t getdelim(scope char** lineptr, scope size_t* n, int delimiter, FILE* stream);
ssize_t getline(scope char** lineptr, scope size_t* n, FILE* stream);

Adding scope will allow passing pointers to local variables in @safe code. See also #1740, #1748 and #1749.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's a new one ;-). I'll look into it and add it, thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I obviously need to do a reading on DIP 1000. I've updated the PR, but this question is making me wonder:

void bar(scope char** c, scope int* n) @trusted
{

}

void foo() @safe
{
    char[100] buf;
    char* c = &buf[0];
    int n;

    bar(&c, &n);
}

void main()
{
    foo();
}
test.d(12): Error: cannot take address of scope local c in @safe function foo

Moving char[100] buf ouside of a scope works.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using DMD 2.073.0 and compiling with -dip1000 I got the following results:

void main() @safe
{
    char[100] buf;
    char* c;
    int n;

    bar(&c, &n); // Error
}

void bar(char** c, int* n) @safe
{
}

dip1000.d(7): Error: reference to local variable c assigned to non-scope parameter c calling dip1000.bar
dip1000.d(7): Error: reference to local variable n assigned to non-scope parameter n calling dip1000.bar

void main() @safe
{
    char[100] buf;
    char* c;
    int n;

    bar(&c, &n); // OK
}

void bar(scope char** c, scope int* n) @safe
{
}

[No errors]

void main() @safe
{
    char[100] buf;
    char* c = &buf[0];
    int n;

    bar(&c, &n);
}

void bar(scope char** c, scope int* n) @safe
{
}

dip1000.d(7): Error: cannot take address of scope local c in @safe function main

(same result as yours)

So while DIP1000 is not a 100% solution (yet), using scope is still an improvement for @safe code, because it allows to pass pointers to some local variables.

Copy link
Member

@PetarKirov PetarKirov Jan 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just saw the forum post (thanks for bringing this to Walter's attention) and I was wondering if we should change the declarations to:

ssize_t getdelim(ref scope char* lineptr, scope size_t* n, int delimiter, FILE* stream);
ssize_t getline(ref scope char* lineptr, scope size_t* n, FILE* stream);

relying on the fact that the calling convention should remain the same. @WalterBright do you think this is a good idea?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, scope char** lineptr is correct here, the function doesn't escape the value of the char** pointer passed in. In any case it hardly seems to matter b/c those functions are inherently unsafe, after the call *lineptr will point to some internal buffer of the stream.