[Bug c++/52103] need a finer control over -Woverloaded-virtual

2012-02-04 Thread mlg7 at yandex dot ru
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52103

--- Comment #3 from mlg  2012-02-04 09:50:39 UTC ---
> You can use C++11 explicit override control

Since it is a lot of existing code, I'm afraid I'd have to
have _them_ used override 5 or 10 or so years ago.


[Bug c++/52103] need a finer control over -Woverloaded-virtual

2012-02-03 Thread mlg7 at yandex dot ru
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52103

--- Comment #1 from mlg  2012-02-03 09:14:36 UTC ---
$ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
Copyright (C) 2010 Free Software Foundation, Inc. [...]


[Bug c++/52103] New: need a finer control over -Woverloaded-virtual

2012-02-03 Thread mlg7 at yandex dot ru
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52103

 Bug #: 52103
   Summary: need a finer control over -Woverloaded-virtual
Classification: Unclassified
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: m...@yandex.ru


Let me first explain my use case.
I have a large existing non-gcc source which I am porting to a platform
supported by gcc. Due to the difference in dialects, I have to insert const
modifiers for the function parameters. But when I change the signature of a
base class by inserting const, it does not affect the derived classes --
instead, it just breaks inheritance. This is where -Woverloaded-virtual comes
to play.

Unfortunately, it generates too much noise, rendering the feature almost
unusable for this case. Indeed, the best place to hide an important message is
a hundred of useless messages of the same sort. (So this is a usability issue.)

Considering that -Woverloaded-virtual is rather doing what its name suggests, I
propose to implement two finer-tuned options.

-Woverloaded-modifiers
gives a warning when the two signatures differ only in modifiers like const.
(Consider also volatile and restrict.)
struct Base{ void f(Base& x){} };
struct Derived: public Base{ void f(const Base& x){} };

-Woverloaded-compatible
gives a warning when the two signatures differ in parameter classes, but one of
the classes is a descendant of the other.
struct First{ void g(Base&x){} };
struct Second{ void g(Derived&x){} };

I underline that -Woverloaded-modifiers and -Woverloaded-compatible should not
be limited to virtual functions: virtual could be implied if the function is
virtual in the base class. (You may disagree with me here, in this case I want
to hear your arguments.)

(I do not insist on namely these names, maybe you have some better
suggestion(s), but I insist on the functionality.)

As to -Woverloaded-virtual, I think, it should be left as it is.

Now some code example. Note that with -Woverloaded-modifiers
-Woverloaded-compatible there should be no warning for struct ThereIsNoProblem
because the argument types are unrelated.

$cat inher4.cpp 
#include 

struct Base{ void f(const Base& x){printf("Base.f()\n");} };
struct Derived: public Base{ void f(Base& x){printf("Derived.f()\n");} };

struct First{ virtual void g(Base&x){printf("First.g()\n");} };
struct Second:public First{ virtual void g(Derived&x){printf("Second.g()\n");}
};
struct ThereIsNoProblem:public First{ virtual void g(int
x){printf("ShouldBeValid.g()");} };

int main()
{
Base x;
Derived y;
Base*py=&y;
y.f(x);
py->f(Base());
Second z;
First*pz=&z;
//z.g(x); // error: no matching function for call to ‘Second::g(Base&)’
z.g(y);
pz->g(x);
pz->g(y);
}
$g++ -Woverloaded-virtual inher4.cpp 
inher4.cpp:6:28: warning: ‘virtual void First::g(Base&)’ was hidden
inher4.cpp:7:42: warning:   by ‘virtual void Second::g(Derived&)’
inher4.cpp:6:28: warning: ‘virtual void First::g(Base&)’ was hidden
inher4.cpp:8:52: warning:   by ‘virtual void ThereIsNoProblem::g(int)’
$./a.out 
Derived.f()
Base.f()
Second.g()
First.g()
First.g()
$


[Bug c++/47940] warn about calls to a pure virtual from a constructor/destructor

2011-03-01 Thread mlg7 at yandex dot ru
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47940

--- Comment #6 from mlg  2011-03-01 17:23:41 UTC ---
(In reply to comment #4)
> (In reply to comment #0)
> > 
> > Functions that call pure virtual functions cannot
> > be called from constructors and destructors.
> > This may be discovered at compile-time, and the above
> > text makes a good error/warning message.
> 
> I'm not sure it makes a good diagnostic, consider:
> 
> struct abc {
>   abc(bool nasal_demons) { if (nasal_demons) fly(); }
>   void fly() { doFly(); }
>   virtual void doFly() = 0;
> };
>

That is the most dangerous situation: the crashing call is
buried [deep] in the control flow.
The deeper it is buried, the more valuable a warning/error
message would be.

Ok, "a pure virtual function may be called indirectly 
from a constructor/destructor"

> Ideally the diagnostic for this would say "may call a pure virtual" for cases
> where it can't be determined.

Probably you are right, a kind of "I know what I'm doing"
pragma would be useful as well.

I also want to note that the top-level function may be virtual:
[NOTE: usefunc() is virtual here]
==byebug2.cpp==
#include 
class Base {
public:
~Base() { usefunc(); }
virtual void func()=0;
virtual void usefunc() { func(); }
};

class Derived: public Base {
public:
virtual void func() {}
};

int main() {
Derived d;
printf("life is good\n");
return 0;
}
==eof==
$ g++ -Wall -Wextra byebug2.cpp
$ ./a.out 
life is good
pure virtual method called
terminate called without an active exception
Aborted


[Bug c++/47940] can call a pure virtual from a constructor/destructor

2011-03-01 Thread mlg7 at yandex dot ru
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47940

--- Comment #2 from mlg  2011-03-01 11:34:30 UTC ---
Yes it _is_ hard to detect. My colleague was suspecting
a build system bug/feature at first (hours for a full rebuild).
If it was a direct call, there would be a linker error.

>If the call was direct to func instead,
>it would be better.

Unfortunately or fortunately, refactoring a huge 
real world application to make bugs easier 
for the compiler to detect is not an option.


[Bug c++/47940] New: can call a pure virtual from a constructor/destructor

2011-03-01 Thread mlg7 at yandex dot ru
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47940

   Summary: can call a pure virtual from a constructor/destructor
   Product: gcc
   Version: 4.4.5
Status: UNCONFIRMED
  Severity: enhancement
  Priority: P3
 Component: c++
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: m...@yandex.ru


A colleague of mine have been examining a crash that
boils down to the following:
--hellobug.cpp--
class Base {
public:
Base() { usefunc(); }
virtual void func()=0;
void usefunc() { func(); }
};

class Derived: public Base {
public:
virtual void func() {}
};

int main() {
Derived d;
return 0;
}
--eof--

$ g++ -Wall -Wextra hellobug.cpp
{just nothing}
$ ./a.out 
pure virtual method called
terminate called without an active exception
Aborted

That is, "you asked for it, you got it" [1].
==
[1] from "Real Programmers Don't"
==

A variation:

==byebug.cpp==
#include 
class Base {
public:
~Base() { usefunc(); }
virtual void func()=0;
void usefunc() { func(); }
};

class Derived: public Base {
public:
virtual void func() {}
};

int main() {
Derived d;
printf("life is good\n");
return 0;
}
==eof==

$ g++ -Wall -Wextra byebug.cpp
{again nothing}
$ ./a.out 
life is good
pure virtual method called
terminate called without an active exception
Aborted


I have to note that in a big software project, 
the mistake is not so obvious.
But what can be done?


Functions that call pure virtual functions cannot
be called from constructors and destructors.
This may be discovered at compile-time, and the above
text makes a good error/warning message.



WHAT I GET: no warning
WHAT I WOULD EXPECT: a warning or an error message:
"Functions that call pure virtual functions cannot
be called from constructors and destructors"


$ gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro
4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.4 --enable-shared --enable-multiarch
--enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib
--without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls
--with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc
--disable-werror --with-arch-32=i686 --with-tune=generic
--enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu
--target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)


[Bug preprocessor/38179] need a warning: macro parameter is not a whole expression within macro body

2008-11-21 Thread mlg7 at yandex dot ru


--- Comment #2 from mlg7 at yandex dot ru  2008-11-21 08:44 ---
(In reply to comment #1)
> The expanded text for the first one is:
> int t = 1|2 & 0xFF00 ? dothis(1|2) : dothat(1|2);
> 
> Maybe I am missing something here. 
> 
the human who is writing
int t = MYMACRO(FLAGA|FLAGB);
obviously means
int t = (1|2) & 0xFF00 ? dothis(1|2) : dothat(1|2); // #1
while the compiler treats this as
int t = 1|(2 & 0xFF00) ? dothis(1|2) : dothat(1|2); // #2

(google for "C Operator Precedence" if you need to check it)

This is a well-known preprocessor gotcha. I propose to add a warning for such
cases.

PS

That is, there are two gotchas: the problem with expressions as macro
parameters and the same problem with expressions in generated text. The Clever
Books tell folks to enclose all macro parameters in parens and enclose the
whole macro body in parens.

So, the recommended way for writing
#define MYMACRO(x) x & 0xFF00 ? dothis(x) : dothat(x)
is
#define MYMACRO(x) ((x) & 0xFF00 ? dothis((x)) : dothat((x)))

It looks like LISP but it works. But practice shows that not everybody reads
The Clever Books...


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38179



[Bug c/38179] New: need a warning: macro parameter is not a whole expression within macro body

2008-11-19 Thread mlg7 at yandex dot ru
This affects both C and C++ (and probably Objective C that I never used)

(In fact, I propose two warnings:
1. macro parameter is not a whole expression within macro body
2. expanded macro body is not a whole expression within macro use context
)

I propose to add a warning (and include it in -Wall) for the following sort of
bugs:

#define FLAGA 1
#define FLAGB 2

#define MYMACRO(x) x & 0xFF00 ? dothis(x) : dothat(x)

int t = MYMACRO(FLAGA|FLAGB);

The expanded text is

int t = FLAGA|FLAGB & 0xFF00 ? dothis(FLAGA|FLAGB) : dothat(FLAGA|FLAGB);

and it is obvious that due to the bug the conditional expression is evaluated
to true while it should have been false, and the right branch will not be
chosen.
(this would produce the "macro parameter is not a whole expression within macro
body" warning)


The same applies to
int t = 10 + MYMACRO(FLAGA|FLAGB);
where 10 will be a part of the conditional expression.
(this would produce the "expanded macro body is not a whole expression within
macro use context" warning)

But: it is important not to produce such warnings when the macro parameter or
body in principle cannot be a whole expression, for example, contains ";" or
"{".

-

AN APPROACH TO IMPLEMENTATION

I would suggest something like "weak parens", say, #( and #)

int t = MYMACRO(FLAGA|FLAGB);

would expand to

int t = #( FLAGA|FLAGB #) & 0xFF00 ? dothis( #( FLAGA|FLAGB #) ) : dothat(
#( FLAGA|FLAGB #) );

Here we can issue a warning because when we compare the tree parsed as "weak
parens as parens" vs the tree parsed as "weak parens are spaces", we get
different results.

Surrounding the whole expression with weak parens #{ and #} would solve the
problem of expanded macro text broken by higher-priority operators:

int t = 10 + MYMACRO(FLAGA|FLAGB);

would expand to

int t = 10 + #{ #( FLAGA|FLAGB #) & 0xFF00 ? dothis( #( FLAGA|FLAGB #) ) :
dothat( #( FLAGA|FLAGB #) ) #} ;

and, again, replacing #{ #} with parens or spaces we get different trees.

And what about

#define OH_MY_GOD 20; y=
x = OH_MY_GOD 10;

?
It expands to

x = #{ 20; y = #} 10;

We must just ignore weak parens that are not balanced (both #{ #} and #( #) ).

At least, options enabled via -Wall and -Wextra *MUST_NOT* produce warnings for
such cases.

The same about SOME_MACRO(x();y(), z();t()), weak parens cannot be replaced by
parens here.

I do not think that checking possible replacement of weak parens by braces { }
is that important, we can live without it.

Example of a case that is not so important:
#define SOME_MACRO(x,y)if(my_boolean)x;else y;
SOME_MACRO(x();y(), z();t())


-- 
   Summary: need a warning: macro parameter is not a whole
expression within macro body
   Product: gcc
   Version: 4.3.3
Status: UNCONFIRMED
  Severity: enhancement
  Priority: P3
 Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: mlg7 at yandex dot ru


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38179



[Bug c++/38053] New: add a warning for b/c*d

2008-11-07 Thread mlg7 at yandex dot ru
If the compiler generates a warning for x&&y||z, it should also generate a
warning for a*b/c*d. The problem is that the programmer probably meant
a*b/(c*d), that is, a*b/c/d.

This relates to both C and C++.


-- 
   Summary: add a warning for b/c*d
   Product: gcc
   Version: 4.3.3
Status: UNCONFIRMED
  Severity: enhancement
  Priority: P3
 Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: mlg7 at yandex dot ru


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38053