diff mbox

[3/3] symbol.c: Set correct size of array from parenthesized string initializer

Message ID 5197387E.5030000@gmail.com (mailing list archive)
State Mainlined, archived
Headers show

Commit Message

Chris Li May 18, 2013, 8:14 a.m. UTC
On 05/18/2013 12:38 AM, Christopher Li wrote:
> I guess the rules is that parenthesized string can appear in
> any place where string was allowed.


I create an incremental patch to address the issue. Please
check if that works for you.

Chris

Comments

Ramsay Jones May 20, 2013, 6:42 p.m. UTC | #1
Chris Li wrote:
> On 05/18/2013 12:38 AM, Christopher Li wrote:
>> I guess the rules is that parenthesized string can appear in
>> any place where string was allowed.
> 
> 
> I create an incremental patch to address the issue. Please
> check if that works for you.

Unfortunately not. :(

In my git repo, I just happen to be on the pu branch:

  $ pwd
  /home/ramsay/git
  $ git describe
  v1.8.3-rc3-347-gac05152
  $ 

Using an older version of sparse (I don't know exactly which version;
although I have had a patch to add --version for some years, I wasn't
actually using a version with it applied!).

  $ make sparse >psp-out0 2>&1
  $ grep warning psp-out0 | wc -l
  7
  $ grep error psp-out0 | wc -l
  0
  $ 

Note that the severn warnings all relate to the glibc headers using
an transparent union for the various sockaddr types, for example:

      SP connect.c
  connect.c:272:40: warning: incorrect type in argument 2 (invalid types)
  connect.c:272:40:    expected union __CONST_SOCKADDR_ARG [usertype] __addr
  connect.c:272:40:    got struct sockaddr *ai_addr

Installing a new version of sparse:

  $ sparse --version
  v0.4.5-rc1
  $ make sparse >psp-out1 2>&1
  $ grep warning psp-out1 | wc -l
  9
  $ grep error psp-out1 | wc -l
  1
  $ diff psp-out0 psp-out1
  77a78
  > notes-merge.c:111:9: warning: too long initializer-string for array of char
  111a113
  > sha1_file.c:54:9: warning: too long initializer-string for array of char
  152a155
  > compat/regex/regex_internal.c:926:1: error: symbol 're_string_context_at' redeclared with different type (originally declared at compat/regex/regex_internal.h:434) - different modifiers
  $ 

Note that the two new warnings are fixed by my first patch and the
error is the second regression that I mentioned.

So, now introduce an "parenthesized string initializer", thus:

  $ vim gettext.h
  $ git diff
  diff --git a/gettext.h b/gettext.h
  index 7671d09..d11a413 100644
  --- a/gettext.h
  +++ b/gettext.h
  @@ -63,6 +63,6 @@ const char *Q_(const char *msgid, const char *plu, unsigned lo
   }
   
   /* Mark msgid for translation but do not translate it. */
  -#define N_(msgid) msgid
  +#define N_(msgid) (msgid)
   
   #endif
  $ make sparse >psp-out2 2>&1
  $ grep warning psp-out2 | wc -l
  31
  $ grep error psp-out2 | wc -l
  2
  $ 

The new warnings all look like this:

  $ grep warning psp-out2 | head -3
  branch.c:216:1: warning: too long initializer-string for array of char
  branch.c:218:1: warning: too long initializer-string for array of char
  branch.c:220:1: warning: too long initializer-string for array of char
  $ 

The additional error is a simple syntax error:

  $ rm builtin/log.o
  $ make builtin/log.o
      CC builtin/log.o
  builtin/log.c:42: error: called object ‘"git log [<options>] [<revision range>] [[--] <path>...]\012"’ is not a function
  make: *** [builtin/log.o] Error 1
  $ make builtin/log.sp
      SP builtin/log.c
  builtin/log.c:42:9: error: not a function <noident>
  $ 

Now install a version of sparse with my three patches applied:

  $ sparse --version
  v0.4.5-rc1-3-g14eceaa
  $ make sparse >psp-out3 2>&1
  $ grep warning psp-out3 | wc -l
  7
  $ grep error psp-out3 | wc -l
  2
  $ 

So, all of the additional "too long initializer-string" warnings
are no longer issued.

Now add your additional patch on top:

  $ sparse --version
  v0.4.5-rc1-4-g5ef4e35
  $ make sparse >psp-out4 2>&1
  $ grep warning psp-out4 | wc -l
  177
  $ grep error psp-out4 | wc -l
  2
  $ 

All of the additional warnings, look like:

  $ grep warning psp-out4 | head -3
  archive.c:14:9: warning: excessive elements in array initializer
  archive.c:221:39: warning: excessive elements in array initializer
  attr.c:327:9: warning: excessive elements in array initializer
  $ 

Note that the warnings don't all involve the use of the gettext
'N_' macro. Also, many (I haven't checked them all) are actually
arrays of 'char *' (_not_ array of char). For example, from the
above list, archive.c:221 looks like this:

        const char *paths[] = { path, NULL };

HTH

ATB,
Ramsay Jones




--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/symbol.c b/symbol.c
index 051a909..a59a4ca 100644
--- a/symbol.c
+++ b/symbol.c
@@ -284,15 +284,6 @@  static int count_array_initializer(struct symbol *t, struct expression *expr)
 	if (t->ctype.base_type == &int_type && t->ctype.modifiers & MOD_CHAR)
 		is_char = 1;
 
-	/* check for a parenthesized string: char x[] = ("string"); */
-	if (is_char && expr->type == EXPR_PREOP && expr->op == '(') {
-		struct expression *e = expr;
-		while (e && e->type == EXPR_PREOP && e->op == '(')
-			e = e->unop;
-		if (e && e->type == EXPR_STRING)
-			expr = e;
-	}
-
 	switch (expr->type) {
 	case EXPR_INITIALIZER: {
 		struct expression *entry;
@@ -305,6 +296,15 @@  static int count_array_initializer(struct symbol *t, struct expression *expr)
 				if (entry->idx_to >= nr)
 					nr = entry->idx_to+1;
 				break;
+			case EXPR_PREOP: {
+				struct expression *e = entry;
+				while (e && e->type == EXPR_PREOP && e->op == '(')
+					e = e->unop;
+				if (!(e && e->type == EXPR_STRING))
+					break;
+				entry = e;
+				/* fall through to strings. */
+			}
 			case EXPR_STRING:
 				if (is_char)
 					str_len = entry->string->length;
@@ -316,6 +316,15 @@  static int count_array_initializer(struct symbol *t, struct expression *expr)
 			nr = str_len;
 		break;
 	}
+	case EXPR_PREOP: {
+		struct expression *e = expr;
+		while (e && e->type == EXPR_PREOP && e->op == '(')
+			e = e->unop;
+		if (!(e && e->type == EXPR_STRING))
+			break;
+		expr = e;
+		/* fall through to strings. */
+	}
 	case EXPR_STRING:
 		if (is_char)
 			nr = expr->string->length;
diff --git a/validation/init-char-array1.c b/validation/init-char-array1.c
index 7427702..24fd8d8 100644
--- a/validation/init-char-array1.c
+++ b/validation/init-char-array1.c
@@ -5,6 +5,7 @@ 
  */
 static const char u[] = ("hello");
 static const char v[] = {"hello"};
+static const char v1[] = {("hello")};
 static const char w[] = "hello";
 static const char x[5] = "hello";
 
@@ -21,5 +22,6 @@  static void f(void)
  *
  * check-error-start
 init-char-array1.c:6:26: warning: array initialized from parenthesized string constant
+init-char-array1.c:8:28: warning: array initialized from parenthesized string constant
  * check-error-end
  */