Pages: [1]   Go Down
Author Topic: Why are compiler warnings disabled?  (Read 2575 times)
0 Members and 1 Guest are viewing this topic.
Knivsta,Sweden
Offline Offline
Sr. Member
****
Karma: 0
Posts: 274
Low level's cool
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Knivsta,Sweden
Offline Offline
Sr. Member
****
Karma: 0
Posts: 274
Low level's cool
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#!/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.
« Last Edit: July 10, 2010, 03:29:21 pm by drhex » Logged

North Yorkshire, UK
Offline Offline
Faraday Member
**
Karma: 104
Posts: 5531
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hmm, interesting.
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.  smiley-wink

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.  smiley-wink

Lefty
« Last Edit: July 10, 2010, 02:29:33 pm by retrolefty » Logged

Knivsta,Sweden
Offline Offline
Sr. Member
****
Karma: 0
Posts: 274
Low level's cool
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
typedef prog_uchar PROGMEM const_bytes;

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

North Yorkshire, UK
Offline Offline
Faraday Member
**
Karma: 104
Posts: 5531
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Knivsta,Sweden
Offline Offline
Sr. Member
****
Karma: 0
Posts: 274
Low level's cool
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...
Logged

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
// 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)
« Last Edit: July 11, 2010, 11:52:02 am by davekw7x » Logged

Knivsta,Sweden
Offline Offline
Sr. Member
****
Karma: 0
Posts: 274
Low level's cool
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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   :smiley
« Last Edit: July 11, 2010, 04:15:58 pm by drhex » Logged

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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:
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

« Last Edit: July 11, 2010, 07:53:41 pm by davekw7x » Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 596
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#!/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`;
Logged

East Coast, USA
Offline Offline
Newbie
*
Karma: 0
Posts: 5
Arduino rock salt
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#!/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;
Logged

Pages: [1]   Go Up
Jump to: