Bug 13428 - gcc-avr doesn't work non-constant array references
Summary: gcc-avr doesn't work non-constant array references
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 3.3.1
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
: 13427 (view as bug list)
Depends on:
Blocks:
 
Reported: 2003-12-18 06:45 UTC by Ken
Modified: 2005-07-23 22:49 UTC (History)
2 users (show)

See Also:
Host:
Target: avr
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ken 2003-12-18 06:45:47 UTC
gcc version as:
Configured with: ../configure --prefix=/e/avrdev/install --target=avr --enable-
languages=c,c++ --disable-nls --enable-win32-registry=WinAVR
Thread model: single
gcc version 3.3.1

demo program as:

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <string.h>

const char foo[] PROGMEM = "foo";
const char bar[] PROGMEM = "bar";

PGM_P  Langs[2] PROGMEM = {foo, bar};

int main(void)
{
  unsigned char i;
  char buf[2][5];
  
  //strcpy_P works fine with constant index
  strcpy_P(buf[0], Langs[0]);  //correctly copy 'foo'
  strcpy_P(buf[1], Langs[1]);  //correctly copy 'bar'
  
  //but strcpy_P copy char from wrong address if use variable indexing
  for (i=0; i<2; i++)
    strcpy_P(buf[i], Langs[i]);  //copy garbages!!!

  return 1;
}
Comment 1 Andrew Pinski 2003-12-18 06:47:58 UTC
*** Bug 13427 has been marked as a duplicate of this bug. ***
Comment 2 Andrew Pinski 2003-12-19 14:44:45 UTC
Can you provide the preprocessed source?
Comment 3 Ken 2003-12-20 02:53:24 UTC
(In reply to comment #2)
> Can you provide the preprocessed source?

# 1 "pgmbug.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "pgmbug.c"
# 1 "C:/WinAVR/avr/include/avr/io.h" 1 3
# 81 "C:/WinAVR/avr/include/avr/io.h" 3
# 1 "C:/WinAVR/avr/include/avr/sfr_defs.h" 1 3
# 82 "C:/WinAVR/avr/include/avr/io.h" 2 3
# 167 "C:/WinAVR/avr/include/avr/io.h" 3
# 1 "C:/WinAVR/avr/include/avr/iom103.h" 1 3
# 168 "C:/WinAVR/avr/include/avr/io.h" 2 3
# 2 "pgmbug.c" 2
# 1 "C:/WinAVR/avr/include/avr/pgmspace.h" 1 3
# 67 "C:/WinAVR/avr/include/avr/pgmspace.h" 3
# 1 "C:/WinAVR/avr/include/inttypes.h" 1 3
# 60 "C:/WinAVR/avr/include/inttypes.h" 3
typedef signed char int8_t;




typedef unsigned char uint8_t;
# 83 "C:/WinAVR/avr/include/inttypes.h" 3
typedef int int16_t;




typedef unsigned int uint16_t;
# 99 "C:/WinAVR/avr/include/inttypes.h" 3
typedef long int32_t;




typedef unsigned long uint32_t;
# 117 "C:/WinAVR/avr/include/inttypes.h" 3
typedef long long int64_t;




typedef unsigned long long uint64_t;
# 134 "C:/WinAVR/avr/include/inttypes.h" 3
typedef int16_t intptr_t;




typedef uint16_t uintptr_t;
# 68 "C:/WinAVR/avr/include/avr/pgmspace.h" 2 3
# 1 "C:/WinAVR/lib/gcc-lib/avr/3.3.1/include/stddef.h" 1 3 4
# 213 "C:/WinAVR/lib/gcc-lib/avr/3.3.1/include/stddef.h" 3 4
typedef unsigned int size_t;
# 69 "C:/WinAVR/avr/include/avr/pgmspace.h" 2 3
# 89 "C:/WinAVR/avr/include/avr/pgmspace.h" 3
typedef void prog_void __attribute__((__progmem__));
typedef char prog_char __attribute__((__progmem__));
typedef unsigned char prog_uchar __attribute__((__progmem__));
typedef int prog_int __attribute__((__progmem__));
typedef long prog_long __attribute__((__progmem__));
typedef long long prog_long_long __attribute__((__progmem__));
# 347 "C:/WinAVR/avr/include/avr/pgmspace.h" 3
extern void *memcpy_P(void *, const prog_void *, size_t);
extern char *strcat_P(char *, const prog_char *);
extern int strcmp_P(const char *, const prog_char *) __attribute__((__pure__));
extern char *strcpy_P(char *, const prog_char *);
extern int strcasecmp_P(const char *, const prog_char *) __attribute__
((__pure__));
extern size_t strlcat_P (char *, const prog_char *, size_t );
extern size_t strlcpy_P (char *, const prog_char *, size_t );
extern size_t strlen_P(const prog_char *) __attribute__((__const__));
extern int strncmp_P(const char *, const prog_char *, size_t) __attribute__
((__pure__));
extern int strncasecmp_P(const char *, const prog_char *, size_t) __attribute__
((__pure__));
extern char *strncat_P(char *, const prog_char *, size_t);
extern char *strncpy_P(char *, const prog_char *, size_t);
# 3 "pgmbug.c" 2
# 1 "C:/WinAVR/avr/include/string.h" 1 3
# 40 "C:/WinAVR/avr/include/string.h" 3
# 1 "C:/WinAVR/lib/gcc-lib/avr/3.3.1/include/stddef.h" 1 3 4
# 41 "C:/WinAVR/avr/include/string.h" 2 3
# 59 "C:/WinAVR/avr/include/string.h" 3
extern void *memccpy(void *, const void *, int, size_t);
extern void *memchr(const void *, int, size_t) __attribute__((__pure__));
extern int memcmp(const void *, const void *, size_t) __attribute__
((__pure__));
extern void *memcpy(void *, const void *, size_t);
extern void *memmove(void *, const void *, size_t);
extern void *memset(void *, int, size_t);
extern char *strcat(char *, const char *);
extern char *strchr(const char *, int) __attribute__((__pure__));
extern int strcmp(const char *, const char *) __attribute__((__pure__));
extern char *strcpy(char *, const char *);
extern int strcasecmp(const char *, const char *) __attribute__((__pure__));
extern size_t strlcat(char *, const char *, size_t);
extern size_t strlcpy(char *, const char *, size_t);
extern size_t strlen(const char *) __attribute__((__pure__));
extern char *strlwr(char *);
extern char *strncat(char *, const char *, size_t);
extern int strncmp(const char *, const char *, size_t);
extern char *strncpy(char *, const char *, size_t);
extern int strncasecmp(const char *, const char *, size_t) __attribute__
((__pure__));
extern size_t strnlen(const char *, size_t) __attribute__((__pure__));
extern char *strrchr(const char *, int) __attribute__((__pure__));
extern char *strrev(char *);
extern char *strsep(char **, const char *) __attribute__((__pure__));
extern char *strstr(const char *, const char *) __attribute__((__pure__));
extern char *strtok_r(char *, const char *, char **) __attribute__((__pure__));
extern char *strupr(char *);
# 4 "pgmbug.c" 2

const char foo[] __attribute__((__progmem__)) = "foo";
const char bar[] __attribute__((__progmem__)) = "bar";

const prog_char * Langs[2] __attribute__((__progmem__)) = {foo, bar};

int main(void)
{
  unsigned char i;
  char buf[2][5];


  strcpy_P(buf[0], Langs[0]);
  strcpy_P(buf[1], Langs[1]);


  for (i=0; i<2; i++)
    strcpy_P(buf[i], Langs[i]);

  return 1;
}
Comment 4 Andrew Pinski 2003-12-20 02:58:28 UTC
Marking as invalid to mark it as ...
Comment 5 Andrew Pinski 2003-12-20 02:59:32 UTC
Unconfirmed.
Comment 6 Kazu Hirata 2003-12-24 21:12:07 UTC
What is your compiler options?
Could you explain the bug a little more and/or provide a shorter testcase?
Does your testcase expose a bug even if you remove the first two strcpy_P?
Which address is wrong?  The destination or the source?
What if you get 'i' from some function call instead of a for loop like so?
 
  i = baz ();
  strcpy_P(buf[i], Langs[i]);
Comment 7 Andrew Pinski 2003-12-24 22:23:17 UTC
Does this work without PROGMEM at all, make sure that you remove the const?
Because the attribute only sets the section different so the attribute cannot be doing 
anything to change the asm.
Comment 8 Ken 2003-12-25 05:30:59 UTC
(In reply to comment #6)
> What is your compiler options?
> Could you explain the bug a little more and/or provide a shorter testcase?
> Does your testcase expose a bug even if you remove the first two strcpy_P?
> Which address is wrong?  The destination or the source?
> What if you get 'i' from some function call instead of a for loop like so?
>  
>   i = baz ();
>   strcpy_P(buf[i], Langs[i]);


My complier options are as follows:

avr-gcc -MM -mmcu=atmega103 -I. -g -Os -funsigned-char -funsigned-bitfields -
fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=pgmbug.lst  -
std=gnu99 pgmbug.c \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > pgmbug.d; \

The bug still exposes even if I remove the firs 2 constant indexed strcpy_P.
However, I found that if I supress optimization, even constant indexed 
strcpy_P does NOT work at all. It seems that the source address pass to 
strcpy_P was wrong, the destination address was correct in any case. I tried 
to get i from a fuction call like i = baz (), the bug still exposes.
Comment 9 Ken 2003-12-25 05:51:51 UTC
(In reply to comment #2)
> Can you provide the preprocessed source?

(In reply to comment #7)
> Does this work without PROGMEM at all, make sure that you remove the const?
> Because the attribute only sets the section different so the attribute 
cannot be doing 
> anything to change the asm.

When I remove the PROGMEM directive from Langs likes below:

  const char foo[] PROGMEM  = "foo";
  const char bar[] PROGMEM  = "bar";
  PGM_P Langs[2] = {foo, bar};

strcpy_P() works well with constant or variable index array. The source 
address is correct now. Therefore, Langs cannot be put in program memory.
Comment 10 Andrew Pinski 2003-12-25 15:56:31 UTC
> When I remove the PROGMEM directive from Langs likes below:
> 
>   const char foo[] PROGMEM  = "foo";
>   const char bar[] PROGMEM  = "bar";
>   PGM_P Langs[2] = {foo, bar};
> 
> strcpy_P() works well with constant or variable index array. The source 
> address is correct now. Therefore, Langs cannot be put in program memory.

Then it is a problem with GCC at all because the attribute only puts an extra line in the asm.