threads / patch / 37187

patchconfig.c: change the function signature of `git_config_string()`

Subject: [PATCH] config.c: change the function signature of `git_config_string()`

## tl;dr

10 messages between Jul 22, 2014 and Jul 23, 2014. Diffs are folded; open one to read it.

replies: 9people: 4as markdown or json

Tanay Abhra· Jul 22, 2014, 10:49 UTC · lore

`git_config_string()` output parameter `dest` is declared as a const which is unnecessary as the caller of the function is given a strduped string which can be modified without causing any harm.

Thus, remove the const from the function signature.
Signed-off-by: Tanay Abhra <tanayabh@gmail.com>
---
 cache.h  | 2 +-
 config.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
Show changes to 2 files +2 −2

cache.h, config.c

diff --git a/cache.h b/cache.h
index 92fc9f1..93d357a 100644
--- a/cache.h
+++ b/cache.h
@@ -1303,7 +1303,7 @@ extern unsigned long git_config_ulong(const char *, const char *);
 extern int git_config_bool_or_int(const char *, const char *, int *);
 extern int git_config_bool(const char *, const char *);
 extern int git_config_maybe_bool(const char *, const char *);
-extern int git_config_string(const char **, const char *, const char *);
+extern int git_config_string(char **, const char *, const char *);
 extern int git_config_pathname(const char **, const char *, const char *);
 extern int git_config_set_in_file(const char *, const char *, const char *);
 extern int git_config_set(const char *, const char *);
diff --git a/config.c b/config.c
index ba882a1..25e28a7 100644
--- a/config.c
+++ b/config.c
@@ -633,7 +633,7 @@ int git_config_bool(const char *name, const char *value)
 	return !!git_config_bool_or_int(name, value, &discard);
 }
 
-int git_config_string(const char **dest, const char *var, const char *value)
+int git_config_string(char **dest, const char *var, const char *value)
 {
 	if (!value)
 		return config_error_nonbool(var);
-- 
1.9.0.GIT
Jeff King· Jul 22, 2014, 11:07 UTC · re: Tanay Abhra · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

On Tue, Jul 22, 2014 at 03:49:56AM -0700, Tanay Abhra wrote:
Show 5 quoted lines
> `git_config_string()` output parameter `dest` is declared as a const
> which is unnecessary as the caller of the function is given a strduped
> string which can be modified without causing any harm.
> 
> Thus, remove the const from the function signature.

You are correct that it is unnecessary. However, this patch alone is not sufficient because of the way const-ness in C works. If I have:

  static const char *some_global;
then with your patch, calling:
  git_config_string(&some_global, var, value);

will complain that we are passing a pointer to "const char *", not a pointer to "char *". And indeed, compiling with your patch introduces a ton of compiler warnings.

We would have to convert each of the variables we pass to it to:
  static char *some_global;
That's not so bad, but:
  static char *some_global = "some_default_value";

is wrong. Such a global sometimes points to const storage (i.e., initially), and sometimes to allocated storage (if it was loaded from config). We simply keep the latter as a const pointer (since we would not bother to free it at the end of the program anyway), and that decision influences git_config_string, which is just a helper for setting such variables anyway.

So I would not mind lifting this unnecessary restriction on git_config_string, but I do not see a way to do it without making the rest of the code much uglier (and I do not see a particular advantage in modifying git_config_string here that would make it worth the trouble).

-Peff
Tanay Abhra· Jul 22, 2014, 11:41 UTC · re: Jeff King · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

On 7/22/2014 4:37 PM, Jeff King wrote:
Show 21 quoted lines
> On Tue, Jul 22, 2014 at 03:49:56AM -0700, Tanay Abhra wrote:
> 
>> `git_config_string()` output parameter `dest` is declared as a const
>> which is unnecessary as the caller of the function is given a strduped
>> string which can be modified without causing any harm.
>>
>> Thus, remove the const from the function signature.
> 
> You are correct that it is unnecessary. However, this patch alone is not
> sufficient because of the way const-ness in C works. If I have:
> 
>   static const char *some_global;
> 
> then with your patch, calling:
> 
>   git_config_string(&some_global, var, value);
> 
> will complain that we are passing a pointer to "const char *", not a
> pointer to "char *". And indeed, compiling with your patch introduces a
> ton of compiler warnings.
>

I had also thought that the compiler would raise lot of warnings but it didn't on the first compile. Now I checked again and now it complains a lot, maybe it because I was tinkering with my config.mak, dunno.

Show 20 quoted lines
> We would have to convert each of the variables we pass to it to:
> 
>   static char *some_global;
> 
> That's not so bad, but:
> 
>   static char *some_global = "some_default_value";
> 
> is wrong. Such a global sometimes points to const storage (i.e.,
> initially), and sometimes to allocated storage (if it was loaded from
> config). We simply keep the latter as a const pointer (since we would
> not bother to free it at the end of the program anyway), and that
> decision influences git_config_string, which is just a helper for
> setting such variables anyway.
> 
> So I would not mind lifting this unnecessary restriction on
> git_config_string, but I do not see a way to do it without making the
> rest of the code much uglier (and I do not see a particular advantage in
> modifying git_config_string here that would make it worth the trouble).
> 

Yes, you are right. This patch is the conclusion of discussion in [1]. I used the same function signature as git_config_string for git_config_get_string() which lead to some ugly casts like

+git_config_get_string("imap.folder", (const char**)&imap_folder);

in imap-send.c patch and others. What should we do about such cases, I used either an intermediate variable or casts but Junio commented that it would be better if the dest parameter was a non-const and that it was a weakness of the config-set API that demanded the dest to be a const pointer.

[1]: http://thread.gmane.org/gmane.comp.version-control.git/253948/
Matthieu Moy· Jul 22, 2014, 11:44 UTC · re: Jeff King · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

Jeff King <peff@peff.net> writes:
> will complain that we are passing a pointer to "const char *", not a
> pointer to "char *". And indeed, compiling with your patch introduces a
> ton of compiler warnings.
Tanay: are you not compiling with gcc -Wall -Werror?
(see my earlier message, just create a file config.mak containing
  CFLAGS += -Wdeclaration-after-statement -Wall -Werror
)
> We would have to convert each of the variables we pass to it to:
>
>   static char *some_global;

OK, it seems I got convinced too quickly by Junio ;-). The function produces a char * that can be modified, but it also receives a value, and the function should keep the "const" to allow passing "const char *".

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
Tanay Abhra· Jul 22, 2014, 11:48 UTC · re: Matthieu Moy · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

On 7/22/2014 5:14 PM, Matthieu Moy wrote:
Show 14 quoted lines
> Jeff King <peff@peff.net> writes:
> 
>> will complain that we are passing a pointer to "const char *", not a
>> pointer to "char *". And indeed, compiling with your patch introduces a
>> ton of compiler warnings.
> 
> Tanay: are you not compiling with gcc -Wall -Werror?
> 
> (see my earlier message, just create a file config.mak containing
> 
>   CFLAGS += -Wdeclaration-after-statement -Wall -Werror
> 
> )
>
Yes, I was. Dunno why it didn't work then.
Junio C Hamano· Jul 22, 2014, 15:53 UTC · re: Matthieu Moy · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
> OK, it seems I got convinced too quickly by Junio ;-). The function
> produces a char * that can be modified, but it also receives a value,
> and the function should keep the "const" to allow passing "const char
> *".

Don't blame me. I never suggested to touch that existing function, with existing call sites.

Matthieu Moy· Jul 22, 2014, 16:03 UTC · re: Junio C Hamano · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

Junio C Hamano <gitster@pobox.com> writes:
Show 9 quoted lines
> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
>
>> OK, it seems I got convinced too quickly by Junio ;-). The function
>> produces a char * that can be modified, but it also receives a value,
>> and the function should keep the "const" to allow passing "const char
>> *".
>
> Don't blame me. I never suggested to touch that existing function,
> with existing call sites.

I don't understand what you mean. The new git_config_get_string() function is meant to be used in essentially every places where git_config_string() is currently used, so removing the const from git_config_get_string() raises the same issue as changing the existing function.

Dropping the const means we won't be able to write

const char *v = "default"; ... git_config_get_string(&v, ...);

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
Junio C Hamano· Jul 22, 2014, 16:47 UTC · re: Jeff King · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

Jeff King <peff@peff.net> writes:
> So I would not mind lifting this unnecessary restriction on
> git_config_string, but I do not see a way to do it without making the
> rest of the code much uglier (and I do not see a particular advantage in
> modifying git_config_string here that would make it worth the trouble).
I do not think changing the existing one is warranted, either.

Given that C's type system does not allow us to pass "const char *" as "char *" without cast (and vice versa), a function that takes an out parameter that points at the location to store the pointer to a string (instead of returning the pointer to a string as value) has to take either one of these forms:

	get_mutable(char **dest);
        get_const(const char **dest);
and half the callers need to pass their variables with a cast, i.e.
        char *mutable_string;
	const char *const_string;
	get_mutable((char **)&const_string);
        get_mutable(&mutable_string);
	get_const(&const_string);
	get_const((const char **)&mutable_string);

If we have to cast some [*1*], I'd prefer to see the type describe what it really is, and I think a function that gives a newly allocated storage for the callers' own use is better described by taking a pointer to non-const "char *" location. So I'd encourage a new function being introduced that does not have existing callers to use that as the criterion to decide which to take.

Changing the existing function with existing calling site needs two other pros-and-cons evaluation, in addition to the above "does the type describe what it really is?", which are "is it worth the churn?" and "does the end result make more sense than the original?"

[Footnote]

*1* We have safe_create_leading_directories_const() that works around this for input parameter around its _const less counterpart, which is ugly but livable solution.

Matthieu Moy· Jul 23, 2014, 08:42 UTC · re: Junio C Hamano · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

Junio C Hamano <gitster@pobox.com> writes:
> *1* We have safe_create_leading_directories_const() that works
> around this for input parameter around its _const less counterpart,
> which is ugly but livable solution.

I think it would actually be a reasonable solution to avoid casting here and there on the caller side.

Another option would be to _return_ a non-const char * instead of outputing it as a by-address parameter. We'd lose the consiseness of

   return git_config_get_string(...)
(but in cases where the return value is ignored, we do not really care)
-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
Junio C Hamano· Jul 23, 2014, 17:25 UTC · re: Matthieu Moy · lore

Re: [PATCH] config.c: change the function signature of `git_config_string()`

Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
Show 8 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
>
>> *1* We have safe_create_leading_directories_const() that works
>> around this for input parameter around its _const less counterpart,
>> which is ugly but livable solution.
>
> I think it would actually be a reasonable solution to avoid casting here
> and there on the caller side.

"Ugly" primarily refers to the fact that we are forced to do this in the first place by the language. I agree with you, especially if we have very many call sites, and I suspect config-get-string actually would.

> Another option would be to _return_ a non-const char * instead of
> outputing it as a by-address parameter.
Here, too, I agree that it is the most C-ish interface.

← back to recent threads