Go Down

Topic: Why are compiler warnings disabled? (Read 2897 times) previous topic - next topic

drhex

I notice that -w is passed to avr-g++ when compiling a program, which will disable warnings. What is the reason for that?  :-?

I find warnings useful, think about how many problems posted to this forum that would have been easier to solve if the compiler had complained about:
  • using uninitialized variables
  • assigning variables inside an "if" condition
  • assigning values larger than the datatype allows


drhex

#1
Jul 10, 2010, 06:17 pm Last Edit: Jul 10, 2010, 10:29 pm by drhex Reason: 1
Ok.. nobody knows why warnings are disabled.
Well, I found a way of enabling them to catch some bugs early [for Linux]:

1) locate the avr-g++ executable and rename it to avr-g++-orig

2) paste in the following script as avr-g++ (and chmod it to executable)
Code: [Select]
#!/bin/bash
# to be installed as /usr/bin/avr-g++
# with the original executable renamed to avr-g++-orig

ADDWARNINGS=N

while [ $# -ge 1 ]; do
   ARGORIG+=" \""
   ARGORIG+=$1
   ARGORIG+="\""

   if [ "$1" = -w ]; then        # remove this..
       ARGMOD+=" -Wall -Werror"  # ..replace with this
   else
       ARGMOD+=" \""
       ARGMOD+=$1
       ARGMOD+="\""
   fi

   case $1 in
       *.cpp)
           if [ ${1:0:4} = /tmp ]; then
               ADDWARNINGS=Y
           fi
   esac

   shift
done

if [ $ADDWARNINGS = Y ]; then
   # stop on warnings for the user's source files
   eval avr-g++-orig $ARGMOD
else
   # don't stop on warnings when compiling e.g. HardwareSerial.cpp
   eval avr-g++-orig $ARGORIG
fi



This will take out the "-w" argument and replace it with "-Wall" (to warn about everything) and "-Werror" (treat warnings as errors).
This could be useful to try out other compiler options too, like different optimization levels.

mowcius


retrolefty

#3
Jul 10, 2010, 09:29 pm Last Edit: Jul 10, 2010, 09:29 pm by retrolefty Reason: 1
Well if the warning messages are as cryptic as the compiler error messages then I don't think they will help people that are software challenged like me.  ;)

Now if the warnings linked to example or english explanations that were trying to teach better practices then I would be all for it, otherwise it's just more "red text' to suffer through or ignore.  ;)

Lefty

drhex

The compiler gets a lot pickier with warnings of course - e.g it told me I shouldn't store the return value of millis() in a "long", but rather in an "unsigned long" - I'd say program are better when the source causes no warnings.

One little snag, which seems to be caused by a bug in avr-g++:

Code: [Select]
prog_uchar foo[] PROGMEM = {0,1,2,3,4,5,6};

resulted in a spurious warning that data in PROGMEM must be initialized (even though it is!)

I could get around it like so (from a tip in the avr-freaks forum):

Code: [Select]
typedef prog_uchar PROGMEM const_bytes;

const_bytes foo[] = {0,1,2,3,4,5,6};

mowcius

Sounds fun!

I might have to stick them on at some point just to have a look at what it throws up for all my code.

Mowcius

drhex

The "snag" I found above was a bit worse than I expected.

Of the two ways of declaring some static data in progmem, the one-line version in my last post renders the correct code, but issues a compiler warning.
The typedef version gives no warning, but doesn't actually put any data in progmem. I will try to update the script to get around that. My plan is to find out which warning option that warning is connected to and selectively disable those warnings. -Wuninitialized enabled warnings about uninitialized variables, so -Wno-uninitialized takes them out. Not this particular one though ("only initialized variables can be placed into program memory area").

I also tried disabling everything with -w and then enabling every useful warning one by one. No good. As long as -w is on the command line, it seems all warnings are off even if e.g. -Wunused-variable is also present.

I'll have to peek inside the avr-g++ source code for a hint, and that code is probably hairy...

davekw7x

#7
Jul 11, 2010, 06:32 pm Last Edit: Jul 11, 2010, 06:52 pm by davekw7x Reason: 1
Actually there is a sort of workaround (I think) for the compiler bug that gives spurious warnings of this type, but it's kind of hokey (some would say that it's downright butt-ugly).  Maybe that's why the Arduino folks disabled the warnings.   (Or at least one of the reasons.)

Try the following sketch with your avr-gcc script mod that enables warnings.

I haven't actually changed anything associated with avr-gcc or with Arduino itself, but I have compiled (standalone) stuff like this with avr-gcc version 4.3.4 (compiled from source on my Centos 5.5 Linux system) and the warnings disappear with this magical incantation.  See Footnote.

Code: [Select]

// A possible workaround to eliminate spurious warnings
// about "only initialized variables can be placed in program memory"
// when you enable compiler warnings.
//
// Maybe that's why the Arduino folks disabled the warnings.
//
// Note that you do NOT need the TWO foo statements if you are
// not enabling compiler warnings.
//
// You can just use
//
// const prog_uchar foo[7] PROGMEM = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,0x32};
//
// or even
//
// const byte foo[7] PROGMEM = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,0x32};
//
// In other words, those typedefs in <avr/pgmspace.h> don't really buy us much.
//
//
// davekw7x
//
#include <avr/pgmspace.h>

extern const byte foo[] PROGMEM;
const byte foo[7] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,0x32};

void setup()
{
   Serial.begin(9600);
}

void loop()
{
   int i;
   byte n;
   char buffer[10];
   Serial.println("Using pgm_read_byte_near:");
   for (i = 0; i < 7; i++) {
       n = pgm_read_byte_near(&foo[i]);
       sprintf(buffer, "%02X ", n);
       Serial.print(buffer);
   }
   Serial.println(); Serial.println();
   
   Serial.println("Using normal read:");
   for (i = 0; i < 7; i++) {
       n = foo[i];
       sprintf(buffer, "%02X ", n);
       Serial.print(buffer);
   }
   Serial.println();
   while(1)
       ;
}


By using a loop with pgm_read_byte and another with "normal" memory access you can see whether the array is actually in program memory.  Then you can try other magical incantations and see if there is something that suits your style.


Regards,

Dave

Footnote:
"Any sufficiently advanced technology is indistinguishable from magic."
---Arthur C. Clarke (1917--2008)

drhex

#8
Jul 11, 2010, 11:08 pm Last Edit: Jul 11, 2010, 11:15 pm by drhex Reason: 1
Quote
Actually there is a sort of workaround


Great, thank you!   Peeking at the avr-g++ source code turned out to be a dead end: the progmem warning is coded as some kind of general warning that doesn't have its own -Wwhatever option to turn it on/off.

I tried your version, made less ugly by employing this resusable define

Code: [Select]
#define PROGBYTES(var) extern const byte var[] PROGMEM; \
   const byte var[]

..

PROGBYTES(mydata) = {0,1,2,3,4,5,6};


There was no warning!  I'll have to wait until tomorrow to see if the data ends up in progmem, as I don't have any Arduino hardware myself   ::)

davekw7x

#9
Jul 11, 2010, 11:21 pm Last Edit: Jul 12, 2010, 02:53 am by davekw7x Reason: 1
Quote
I'll have to wait...


I couldn't stand the suspense.  

So...

I plugged your #define into my little sketch and changed the declaration so it looks like
Code: [Select]

#define PROGBYTES(var) extern const byte var[] PROGMEM; \
   const byte var[]

PROGBYTES(foo) = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,0x32};


I ran this with unmodified Arduino/avr-gcc (so mine still suppresses warnings, but I can determine whether it ended up in PROGMEM).

Output:
Code: [Select]

Using pgm_read_byte_near:
FE DC BA 98 76 54 32

Using normal read:
----Irrelevant data here---


Quote
made less ugly...


Well, "less ugly" may or may not mean "prettier" but, as my old granny used to say, "Pretty is as pretty does."

It looks good to me.


Old-time hard-line (non-Arduino) C/C++ programmers might not like it because it doesn't look like a "real" array declaration.

Oh, well---Chacun à son goût!





Regards,

Dave


mromani

Hi,
I've tried to use the script to have warnings enabled, but could not make the bash script work.

Being more familiar with Perl than with Bash, I've made a Perl version of it:

Code: [Select]

#!/usr/bin/perl

use strict;
use warnings;

my $args = "@ARGV";

# debug
#print "Args before: '$args'\n";

if (($args =~ /HardwareSerial.cpp/) || ($args =~ /Tone.cpp/)) {
}
else {
   $args =~ s/-w/-Wall -Werror/;
}

# debug
#print "Args after: '$args'\n";

`/usr/bin/avr-g++-orig $args`;

nasukaren

How about send all the compiler warnings into a logfile as an option? I'm happy opening /Users/moi/Documents/Arduino/logfiles/compiler.txt  

Karen

jmckim

I ran into this issue. We are incorporating some arduinos into a system at work. Testing took a lot longer than anticipated because of some trivial errors that would have been detected much earlier in the development cycle if only -Wall and -Wextra could have been enabled.

This thread was helpful in figuring out a work-around. Here's a modified version of the perl avr-g++ replacement. It logs the unmodified compiler diagnostic output to a separate file (/tmp/arduino_log).

Code: [Select]

#!/usr/bin/env perl

use strict;
use warnings;

my $args = "@ARGV";
if ($args !~ /(HardwareSerial|Tone)\.cpp/) {
   # FIXME - work around a couple warnings in arduino supplied code
   # by supressing warnings for these files:
   # In file included from .../arduino-0018/hardware/arduino/cores/arduino/wiring_private.h:30,
   # from .../arduino-0018/hardware/arduino/cores/arduino/HardwareSerial.cpp:26:
   # /usr/lib/gcc/avr/4.3.4/../../../avr/include/avr/delay.h:36:2: warning: #warning "This file has been moved to <util/delay.h>."
   # .../arduino-0018/hardware/arduino/cores/arduino/Tone.cpp:101: warning: only initialized variables can be placed into program memory area
   $args =~ s/-w/-Wall -Wextra/;
}
my $source_file = '';
if ($args =~ /\w+\.cpp/) {
   $source_file = $&;
}
my $instance_diagnostics = '/tmp/arduino_instance';
my $arduino_logfile = '/tmp/arduino_log';
system <<EOD;
echo '\n'`date`, $source_file >>$arduino_logfile
/usr/bin/avr-g++-orig $args 2>$instance_diagnostics
cat $instance_diagnostics >>$arduino_logfile
EOD
print STDERR `cat $instance_diagnostics`;
unlink $instance_diagnostics;

Go Up