[m-users.] Compiler warning in my readdir.m

Julian Fondren jfondren at minimaltype.com
Mon Oct 14 15:30:37 AEDT 2019


On 2019-10-13 23:08, Volker Wysk wrote:
> Hi
> 
> There might be an issue in my fixed version of readdir.m. When building
> the module, I get a compiler warning:
> 
> Making Mercury/os/readdir.o
> readdir.m: In function ‘readdir_module0’:
> readdir.m:70:18: warning: assignment discards ‘const’ qualifier from
> pointer target type [-Wdiscarded-qualifiers]
> readdir.m: In function ‘readdir_module1’:
> readdir.m:70:18: warning: assignment discards ‘const’ qualifier from
> pointer target type [-Wdiscarded-qualifiers]
> 
> This is in the C code at this place (the line in the middle):
> 
>         if (errno == 0) {
>            Entry = \"\";
>            Result = 0;
> 
> I've attached the complete file.
> 
> Changing the 'Entry =' line to 'Entry = (char*) \"\"' avoids the
> warning message. I guess it's not an error, but I'm not completely
> sure. I'm not experienced with the foreign language interface (yet).
> Maybe it's the type of "Entry" should be "char * const", rahter than
> "char *".
> 

A string literal like "" is going to be in read-only memory, so the
const stuff helps slightly to prevent accidental writing to it.
What you're doing though is pretty weird: returning a string just
so that Mercury can test for that string.

Probably you arrived at this design because per the pred
declaration you're obliged to return a string even when there's no
useful string to return. What you can do though, is just not set
Entry at all (untested):

:- type low_readdir_result
     --->    ok
     ;       eod
     ;       error.
:- pragma foreign_export_enum("C",
     low_readdir_result/0, [prefix("LRR_"), uppercase]).

readdir(Dir, Result, !IO) :-
     readdir0(Dir, Entry, Res, !IO),
     (
         Res = ok,
         Result = ok(yes(Entry))
     ;
         Res = eod,
         % !!
         % what is Entry in this case?
         % ... let's just promise not to look at it.
         % !!
         Result = ok(no)
     ;
         Res = error,
         % !!
         errno(Err, !IO),
         Result = error(Err),
     ).

:- pred readdir0(dir::in, string::out, low_readdir_result::out, io::di, 
io::uo) is det.
:- pragma foreign_proc("C",
     readdir0(Dir::in, Entry::out, Result::out, _IO0::di, _IO::uo),
     [will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
"
     struct dirent *ent = NULL;
     errno = 0;
     ent = readdir(Dir);
     if (ent != NULL) {
         MR_make_aligned_string_copy(Entry, ent->d_name);
         Result = LRR_OK;
     } else if (errno == 0) {
        Result = LRR_EOD;
     else {
        Result = LRR_ERROR;
     }
").

I've wondered if predicates like this should just be impure, so
that callers at least have to explicitly opt in, but it's only
come up in small libraries, in unexported code.


More information about the users mailing list