Incorrect generated code for conditional

2014-03-16 Thread Arthur Schwarz


Win7 - 64bit
gcc (GCC) 4.8.2
g++ -w -DYYDEBUG=1 -DDEBUG_IO   -c -g -MMD -MP -MF 
"build/Debug/Cygwin-Windows/SlipRegister.o.d" -o 
build/Debug/Cygwin-Windows/SlipRegister.o SlipRegister.cpp

There is no generated code for "retval = true;" in the conditional block. I am 
including the code fragment and disassembled code. 


If the issue seems to be a bug then I will include whatever additional data is 
required to help gcc identify the error. If it is not a bug then I truly 
apologize for wasting your time.

What happens is that the conditional is executed but there is no required code. 

art


- source code --

  bool SlipRegister::post(const string& name, SlipHeader& head) {
  bool retval = false;
  if (!head.isHeader()) {
 postError(SlipErr::E4002, "SlipRegister::post", "", "", head);   
  } else {   // attempt to insert a new entry
 SlipAsciiEntry entry(name, &head, SlipHashEntry::DEFINED);
 SlipHash::ReturnTuple tuple = hashTable->insert(entry);
 if (tuple.condition == SlipHash::ReturnTuple::INSERTED) {
    retval == true; // skipped 
over
 } else if (tuple.condition == SlipHash::ReturnTuple::FOUND) {
    if (fsm(*tuple.entry, SlipHashEntry::DEFINED)) {
   
((SlipHeader*)((tuple.entry)->getBinaryKey()))->moveListRight(head);
   head.deleteList();
   retval = true;
    } else if ((tuple.entry)->getType() == SlipHashEntry::USERDATA) {
   postError(SlipErr::E4001, "SlipRegister::post", "", "", head);   
    } else {
   postError(SlipErr::E4015, "SlipRegister::post", "", "", head);   
    };
 }
  }
  DEBUG(debugFlag,
 cout << sFlag[retval] << "post(" << name << ", " << head.toString() 
  << ") " << endl;)
  return retval;
   }; // bool SlipRegister::post(const string& name, SlipHeader& head, bool 
defineFlag)




--- disassembled code fragment 

   ! SlipHash::ReturnTuple tuple = hashTable->insert(entry);
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+337: mov    
0xb0(%rbp),%rax
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+344: mov    
(%rax),%rdx
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+347: lea    
-0x20(%rbp),%rax
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+351: lea    
-0x50(%rbp),%rcx
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+355: mov    
%rcx,%r8
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+358: mov    
%rax,%rcx
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+361: callq  
0x10042d316 
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+987: lea    
-0x20(%rbp),%rax
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+991: mov    
%rax,%rcx
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+994: callq  
0x1004e6c60 
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+1509: lea    
-0x20(%rbp),%rax
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+1513: mov    
%rax,%rcx
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+1516: callq  
0x1004e6c60 
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+1521: jmp    
0x10045c4e4 
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+1523: mov    
%rax,%rbx
! if (tuple.condition == SlipHash::ReturnTuple::INSERTED) {
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+366: mov    
-0x14(%rbp),%eax
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+369: cmp    
$0x4,%eax
slip::SlipRegister::post(std::string const&, slip::SlipHeader&)+372: je 
0x10045c2c9 
!    retval == true;
! } else if (tuple.condition == SlipHash::ReturnTuple::FOUND) {


Possible issue with integer promotion for << and >> in gcc.4.5.3

2012-12-18 Thread Arthur Schwarz
Cygwin gcc 4.5.3

I have run some tests to determine the gcc 4.5.3 integer promotion policies. 
The 
tests show that for 'char' input, "char << long" and "char >> long" promote to 
INT while other operations using a long promote to" long", and that  "char << 
ulong" and "char >> ulong" promote to INT while other operations using ulong 
promote to "ulong". In similar fashion, "long << long" and "long >> long" 
promote to INT while other promotions are to long, and that "long << ulong" and 
"long >> ulong" promote to long while other operations promote to ulong. The 
code used and the  output are included below. 


The code is not production code. 

I think the code is correct and that my interpretation is also correct. I 
realize that gcc 4.5.3 is no longer supported so if my guess is correct do I 
have to switch to mingw (for precompiled later compilers)?

 output 

func0(char 1)
!x 0 0x BOOL
~x-2 0xfffe INT
+x 1 0x0001 INT
-x-1 0x INT

++x3 0x0002 CHAR
--x   -1 0x CHAR
x++2 0x0001 CHAR
x--0 0x0001 CHAR

func1(char -1, bool true)
x  + y0 0x INT
x  - y   -2 0xfffe INT
x  * y   -1 0x INT
x  / y   -1 0x INT
x %  y1 0x0001 INT
x << y   -2 0xfffe INT
x >> y   -1 0x INT
x  & y1 0x0001 INT
x  | y   -1 0x INT
x  ^ x   -2 0xfffe INT

func1(char -1, char 1)
x  + y0 0x INT
x  - y   -2 0xfffe INT
x  * y   -1 0x INT
x  / y   -1 0x INT
x %  y1 0x0001 INT
x << y   -2 0xfffe INT
x >> y   -1 0x INT
x  & y1 0x0001 INT
x  | y   -1 0x INT
x  ^ x   -2 0xfffe INT

func1(char -1, uchar 1)
x  + y0 0x INT
x  - y   -2 0xfffe INT
x  * y   -1 0x INT
x  / y   -1 0x INT
x %  y1 0x0001 INT
x << y   -2 0xfffe INT
x >> y   -1 0x INT
x  & y1 0x0001 INT
x  | y   -1 0x INT
x  ^ x   -2 0xfffe INT

func1(char -1, long 1)
x  + y0 0x LONG
x  - y   -2 0xfffe LONG
x  * y   -1 0x LONG
x  / y   -1 0x LONG
x %  y1 0x0001 LONG
x << y   -2 0xfffe INT
x >> y   -1 0x INT
x  & y1 0x0001 LONG
x  | y   -1 0x LONG
x  ^ x   -2 0xfffe LONG

func1(char -1, ulong 1)
x  + y0 0x ULONG
x  - y   4294967294 0xfffe ULONG
x  * y   4294967295 0x ULONG
x  / y   4294967295 0x ULONG
x %  y1 0x0001 ULONG
x << y   -2 0xfffe INT
x >> y   -1 0x INT
x  & y1 0x0001 ULONG
x  | y   4294967295 0x ULONG
x  ^ x   4294967294 0xfffe ULONG

func0(long 1)
!x 0 0x BOOL
~x-2 0xfffe LONG
+x 1 0x0001 LONG
-x-1 0x LONG

++x3 0x0003 LONG
--x   -1 0x LONG
x++2 0x0001 LONG
x--0 0x0001 LONG

func1(long -1, bool true)
x  + y0 0x LONG
x  - y   -2 0xfffe LONG
x  * y   -1 0x LONG
x  / y   -1 0x LONG
x %  y1 0x0001 LONG
x << y   -2 0xfffe LONG
x >> y   -1 0x LONG
x  & y1 0x0001 LONG
x  | y   -1 0x LONG
x  ^ x   -2 0xfffe LONG

func1(long -1, char 1)
x  + y0 0x LONG
x  - y   -2 0xfffe LONG
x  * y   -1 0x LONG
x  / y   -1 0x LONG
x %  y1 0x0001 LONG
x << y   -2 0xfffe LONG
x >> y   -1 0x LONG
x  & y1 0x0001 LONG
x  | y   -1 0x LONG
x  ^ x   -2 0xfffe LONG

func1(long -1, uchar 1)
x  + y0 0x LONG
x  - y   -2 0xfffe LONG
x  * y   -1 0x LONG
x  / y   -1 0x LONG
x %  y1 0x0001 LONG
x << y   -2 0xfffe LONG
x >> y   -1 0x LONG
x  & y1 0x0001 LONG
x  | y   -1 0x LONG
x  ^ x   -2 0xfffe LONG

func1(long -1, long 1)
x  + y0 0x LONG
x  - y   -2 0xfffe LONG
x  * y   -1 0x LONG
x  / y   -1 0x LONG
x %  y1 0x0001 LONG
x << y   -2 0xfffe LONG
x >> y   -1 0x LONG
x  & y1 0x0001 LONG
x  | y   -1 0x LONG
x  ^ x   -2 0xfffe LONG

func1(long -1, ulong 1)
x  + y0 0x ULONG
x  - y   4294967294 0xf

Diagnostic Messaging Suggestion

2009-04-09 Thread Arthur Schwarz


Please take the comments as constructive and not adversarial. I use GCC
and have hopes of sending it a Valentine's Day gift.

1: Any thought to including column numbers with line numbers on 
   ERROR messages? Looking at a diagnostic message for a complex
   statement  without a column number has lead to making an 
   incorrect assumption as to what in the line is faulty. A 
   column number would help to identify the fault.

2: Stream errors are tortuous to decode to find the cause of  
   error..Any thought to simplification? 

   In particular: 'stream << something_wrong;' can produce a 
   multiline message with copious use of the templates used - 
   but no simple statement as what the error is.

3: A simple error:
   'ifstream istream;'
   Leads to an diagnostic message which seems remote from
   the problem.

Most diagnostic messages contain some indication of what the failure 
is and what to do to repair them. Some messages are outstanding. 
But then again, some could probably use a little tweaking. Any thoughts?

art



Re: Diagnostic Messaging Suggestion

2009-04-09 Thread Arthur Schwarz

I didn't mean to volunteer. I'm retired and therefor am both unhireable and 
hove no free time. But if you really (really) want ... I'd be glad to 
contribute in any way that I can. Provide what you need that I can do, and a 
means to give you feedback and I'm yours.

(I've already provided an indication of a willingness to do something to Robert 
Dewar).

art



Possible messaging changes

2009-04-10 Thread Arthur Schwarz

In  light of the foolhardy commitment I made, here are some reprehensible 
diagnostic messages and the superb recanting of the obvious. As always, the 
messaging and comments are gratuitously provided and I hope accepted in the 
same manner.

Two notes (made before):
1: Some messages are needlessly garrulous. You have noted this previously.
2: The length of some diagnostic messages extend beyond reason. You have
   noted this previously.
3: In a general environment with many classes, structures, typedef's, etc.
   the clear association of a diagnostic message with the offending object,
   type, etc. ads clarity. The messages included below have no clear
   association (although we might argue that garrulity adds clarity).
4: Code is not self-documenting, sic COBOL, and diagnostic messages aren't
   either. A document with messaging guidelines, message descriptions, or
   anything else might be useful. Sigh, I can probably help with this.

As a suggestion, since all headers (and included symbols) are known prior to 
compilation it might be possible to put all the 'names' into a symbol table for 
use during error generation. This allows gcc to (perhaps) publish candidate 
solutions when type errors are detected (see m3). 

As (yet another) suggestion, since user headers can be processed independently 
of code (without considering edge conditions) ya' might as well augment the 
first suggestion with user symbols.

And yet again, while processing a given code file, symbols contained in the 
code file can be used to (yet again) augment the symbol table for use in 
diagnostic generation.

And NOW for the failures!


/*
 * m1.cpp
*/

# include 
# include 

using namespace std;

ifstream  x;
ifstream& y = x;

int main(int argc, char** argv) {
  y = x;
  return 0;
}

g++.3.4.4 output
m1.cpp: In member function `std::basic_ios >& 
std::basic_ios >::operator=(const 
std::basic_ios >&)':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ios_base.h:784: error: 
`std::ios_base& std::ios_base::operator=(const std::ios_base&)' is private
m1.cpp:10: error: within this context
m1.cpp: In member function `std::basic_filebuf >& 
std::basic_filebuf >::operator=(const 
std::basic_fil
ebuf >&)':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/streambuf:776: error: 
`std::basic_streambuf<_CharT, _Traits>& std::basic_streambuf<_CharT, 
_Traits>::operator=(con
st std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char, _Traits = 
std::char_traits]' is private
m1.cpp:10: error: within this context

Almost indecipherable. The error is that operator=() is private.
"error: assignment illegal, operator '=' private in ifstream"

/*
 * m2.cpp
*/


using namespace std;

ifstream  x;
ifstream  y();

int main(int argc, char** argv) {
  return 0;
}

g++.3.4.4 output
m2.cpp:4: error: `ifstream' does not name a type
m2.cpp:5: error: `ifstream' does not name a type

Succint and clear message, however it might be clearer 
to say that "'ifstream' not found" since the message
says that 'ifstream' may be something other than a
type.

"error: ifstream not found"
"note:  candidates are in #include "

/*
 * m3.cpp
*/

# include 
# include 

using namespace std;

ifstream  x;
ifstream  y();

int main(int argc, char** argv) {
  return 0;
}

g++3.4.4 messaging
m3.cpp:6: error: aggregate `std::ifstream x' has incomplete type and cannot be 
defined
m3.cpp:6: error: storage size of `x' isn't known

Messaging not clear. The naive issue is the 'ifstream' not found. 
'std::ifstream' not
found. 'std::ifstream x' is confusing. 

If 'std::ifstream' not found, why is 'std::ifstream y();' legal?

"error: ifstream incomplete in 'istream'.


Redirecting I/O

2009-04-10 Thread Arthur Schwarz

This isn't a compiler question and I apologize for that. I'm having a devil of 
a time getting an answer to my issues on the C/C++ forums I'm using and, sigh, 
perhaps someone can direct me to a forum where the questions can be better 
addressed.

I'm trying to redirect I/O in my C++ application and am having some 
difficulty. I am trying to use cout or a file for output based on some 
condition. cout is an ostream object and file is an ofstream object. 
The types are incompatible, as in:

bool condition;
ofstream x;
ofstream out = (condition)?cout: x;   // won't work because of cout

int main(..){
  out = cout;// won't work
}

In addition I would like to redirect an ofstream object to be the same as 
out, as in;

void fn() { object = out; } // won't work because '=' is private.

Anyone know how to solve these two issues?



operator=() issue

2009-04-10 Thread Arthur Schwarz

operator=() is private in ios_base. Using private inheritance of ios_base the 
program below fails in the constructor when '=' is used (but not during memory 
initialization). I don't understand why assignment is prohibited.

art

Program 1 fails
# include 

using namespace std;

class thing : private ios_base {
ostream& xo;
public:
thing(ostream& y) : xo(y) { xo = y; }
};

gcc.3.4.4 messaging
x.cpp: In member function `std::basic_ios >& 
std::basic_ios >::operator=(const 
std::basic_ios >&)':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ios_base.h:784: error: 
`std::ios_base& std::ios_base::operator=(const std::ios_base&)' is private
x.cpp:9: error: within this context


Program 2 succeeds

# include 

using namespace std;

class thing : private ios_base {
ostream*  yo;
public:
thing(ostream& y) { yo = &y; }
thing(ostream  y) { yo = &y; }
};

Program 4 fails

# include 

using namespace std;

class thing : private ios_base {
ios_base&  xo;
public:
thing(ios_base& y) { xo = y; }
};

gcc.3.4.4 messaging
x.cpp: In constructor `thing::thing(std::ios_base&)':
x.cpp:9: error: uninitialized reference member `thing::xo'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ios_base.h:784: error: 
`std::ios_base& std::ios_base::operator=(const std::ios_base&)' is private
x.cpp:9: error: within this context



Re: operator=() issue

2009-04-10 Thread Arthur Schwarz

You understood me correctly. My (mis?)understanding comes from:

  The Complete Reference,Fourth Edition
  Herbert Schildt
  Copyright 2003
  ISBN 0-07-222680-3

  Page 420 (And I Quote - don't you just love the phrase)

"Remember: When a base class' access specifier is private, public and protected 
members of the base become private members of the derived class. This means 
that they are still accessible by members of the derived class but cannot be 
accessed by parts of your program that are not members of either the base or 
derived class."

If you can, could you please provide a citation which contradicts Schildt?

The examples have a derived class with a private access specifier to a base 
class which should allow access to base class private members, and I assume, 
functions - there is no privacy when you are so derived. Given the above quote 
the behavior seen by gcc is unexpected. Given your statement it appears that an 
access specifier of 'private' has no effect.


art


--- On Fri, 4/10/09, Ian Lance Taylor  wrote:

> From: Ian Lance Taylor 
> Subject: Re: operator=() issue
> To: "Arthur Schwarz" 
> Cc: gcc@gcc.gnu.org
> Date: Friday, April 10, 2009, 4:48 PM
> Arthur Schwarz 
> writes:
> 
> > operator=() is private in ios_base. Using private
> inheritance of
> > ios_base the program below fails in the constructor
> when '=' is used
> > (but not during memory initialization). I don't
> understand why
> > assignment is prohibited.
> 
> Perhaps I misunderstand your question, but private
> inheritance does not
> grant access to private methods in the parent class. 
> It merely
> prohibits access to the parent class by users of the
> class.
> 
> Ian
>


Re: operator=() issue

2009-04-10 Thread Arthur Schwarz

To all, I stand abashed - don't try this without a trained instructor. I 
misread the Schildt quote and (I think) wasted your time(s). 

Thank you
art

--- On Fri, 4/10/09, David Fang  wrote:

> From: David Fang 
> Subject: Re: operator=() issue
> To: "Arthur Schwarz" 
> Cc: gcc@gcc.gnu.org
> Date: Friday, April 10, 2009, 5:45 PM
> One more thing to add ...
> 
> >> Program 1 fails
> >> # include 
> >> 
> >> using namespace std;
> >> 
> >> class thing : private ios_base {
> >>    ostream& xo;
> >> public:
> >>    thing(ostream& y) : xo(y) { xo =
> y; }
> >> };
> >> 
> >> gcc.3.4.4 messaging
> >> x.cpp: In member function `std::basic_ios std::char_traits >&
> std::basic_ios
> >::operator=(const std::basic_ios std::char_traits >&)':
> >>
> /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ios_base.h:784:
> error: `std::ios_base& std::ios_base::operator=(const
> std::ios_base&)' is private
> >> x.cpp:9: error: within this context
> > 
> > std::ios_base was never meant to be
> copy-able/assign-able, this has nothing to do with
> public/private *inheritance*, since it is the members of the
> base that are private, and thus inaccessible to any derived
> classes.
> > 
> > In your thing::thing ctor:
> > 
> > "xo(y)" initializes the member *reference*
> (essentially taking the address of y), whereas "xo = y;" is
> assigning the *object* referenced by 'ox', which is not the
> same.  This is why you hit the inaccessible assignment
> error.
> 
> The real problem is that you are assigning an ostream to an
> ostream, which is not allowed *in any context* because
> ostream ultimately derives from ios_base, which privatizes
> assignment.  You are seeing this message about ios_base
> (misleading you to think it has to do with your thing class
> inheriting from ios_base) because the default assignment of
> class ostream (not explicitly defined) is invoking the
> default assignments of its base classes, including
> ios_base.  This is more an issue of mis-using the
> standard ostream class.
> 
> Fang
> 
> David Fang
> http://www.csl.cornell.edu/~fang/
> http://www.achronix.com/
> 
>


messaging

2009-04-13 Thread Arthur Schwarz

In the following code fragment:

# include 
# include 
# include 

using namespace std;
void CommandLine(int argc, char** argv);
int main(int argc, char** argv) {
   CommandLine(argc, argv[]);
   ifstream x.open(argv[1], ios:in);
   ofstream y.open(argv[1], ios::in);
   
   return 0;
};

g++-4 messaging is:
>> g++-4 x.cpp
x.cpp: In function 'int main(int, char**)':
x.cpp:8: error: expected primary-expression before ']' token
x.cpp:10: error: expected primary-expression before ':' token

A recommendation and reason for change is:
1: x.cpp:8 error: illegal to pass an array without subscript value as an 
   argument
   The given message is accurate but non-expressive of the reason
   for failure.
3: cpp:10 error: illegal scope resolution operator ':'
   From memory, there are three uses of ':' in C++
   ':'   label terminator, :
   ':'   case in a switch statement, case :
   ':'   scope resolution operator, "::"
   The given diagnostic message is deceptive. 

art



messages

2009-04-13 Thread Arthur Schwarz

Some messaging observations for the input code (below).

# include 
# include 
# include 

using namespace std;
void CommandLine(int argc, char** argv);
int main(int argc, char** argv) {
   string  a = "output.txt";
   string* b = &a;
   ofstream y;
   y.open("output.txt",   ios::in);
   y.open( a, ios::in);
   y.open( a.c_str(), ios::in);
   y.open((*b).c_str(),   ios::in);
   y.open( a.c_str,   ios::in);
   return 0;
};

g++-4 x.cpp with suggested error messages and reasoning
x.cpp: In function 'int main(int, char**)':
x.cpp:12: error: no matching function for call to 'std::basic_ofstream >::open(std::string&, const std::_Ios_Openmode&)'
/usr/lib/gcc/i686-pc-cygwin/4.3.2/include/c++/fstream:626: note: candidates 
are: void std::basic_ofstream<_CharT, _Traits>::open(const char*, 
std::_Ios_Openmode
) [with _CharT = char, _Traits = std::char_traits]
x.cpp:15: error: no matching function for call to 'std::basic_ofstream >::open(, const 
std::_I
os_Openmode&)'
/usr/lib/gcc/i686-pc-cygwin/4.3.2/include/c++/fstream:626: note: candidates 
are: void std::basic_ofstream<_CharT, _Traits>::open(const char*, 
std::_Ios_Openmode
) [with _CharT = char, _Traits = std::char_traits]
>>

1: error: open(arg1, ...) must be a C-string.
   The existing message is indecisive in it's resolution. It might be 
   an acceptable idea to analyze expected input arguments and compare
   them with actual arguments and then state a reason for failure based
   on the actual argument(s) that failed. This is a labor since for 
   (example) if arg1 is valid for some overloaded functions but arg2 is
   invalid for any functions, and then arg2 is valid for some functions
   but arg1 is invalid for any function then there is a processing 
   overhead at diagnostic generation time. My argument is that one 
   function of a compiler is show the cause of failure in unambiguous
   and clear terms.
2: error: open(arg1, ...) must be a C-string, and
   error: a.c_str not a member of 'a'
   The first failure is the inability to find a valid member of 'a'. This
   leads to the second failure of being unable to find an overloaded open.
   Nowhere is this clear from the messaging.

We have discussed the undue length of messaging before.

art



Re: messages

2009-04-13 Thread Arthur Schwarz

Thanks Dave;'

Acerbic comments below.

--- On Mon, 4/13/09, Dave Korn  wrote:

> > using namespace std;
> > void CommandLine(int argc, char** argv);
> > int main(int argc, char** argv) {
> >    string  a = "output.txt";
> >    string* b = &a;
> >    ofstream y;
> >   
> y.open("output.txt",   ios::in);
> >    y.open( a,       
>      ios::in);
> >    y.open( a.c_str(), 
>    ios::in);
> >   
> y.open((*b).c_str(),   ios::in);
> >    y.open( a.c_str,   
>    ios::in);
> >    return 0;
> > };
> 
> > 1: error: open(arg1, ...) must be a C-string.
> >    The existing message is indecisive in
> it's resolution. It might be 
> >    an acceptable idea to analyze expected
> input arguments and compare
> >    them with actual arguments and then state
> a reason for failure based
> >    on the actual argument(s) that failed. 
> 
>   Isn't that exactly what the compiler IS doing, as
> indicated by "candidates
> are ... "?

  I don't think so. The compiler is directing the user to a given solution 
  and specifying what the problem is, the compiler is essentially saying
  that it found something it couldn't resolve and for the user to find out
  where and what is wrong. A clear message that arg is wrong I think
  is a better approach. The compiler provides candidate solutions, without
  guidance, and the user must search the candidates (and arguments) to
  determine where the fault lies.
> 
> >    overhead at diagnostic generation time.
> My argument is that one 
> >    function of a compiler is show the cause
> of failure in unambiguous
> >    and clear terms.
> 
>   It's not always possible for the compiler to do
> that.  How can it know if
> the problem is that you gave the wrong argument type in the
> function call,
> rather than that you got the type wrong in the definition
> of the overloaded
> function that was supposed to match?

  Even accepting your statements as accurate some of the time I think it
  a good diagnostic tool for the user for the compiler to do what it can
  when it can. If the judicious answer is that the cases where such a
  tool could be provided is an edge condition where there is small chance
  of occurrence, why then (to be forceful - ahem - needlessly vehement)
  let the user suffer. 

> 
> > x.cpp:15: error: no matching function for call to
> > 'std::basic_ofstream std::char_traits >::open( overloaded function type>, const
> std::_I
> > os_Openmode&)'
> /usr/lib/gcc/i686-pc-cygwin/4.3.2/include/c++/fstream:626:
> > note: candidates
> are: void std::basic_ofstream<_CharT,
> _Traits>::open(const char*,
> std::_Ios_Openmode
> > ) [with _CharT = char, _Traits =
> std::char_traits]
> 
> > 2: error: open(arg1, ...) must be a C-string, and
> >    error: a.c_str not a member of 'a'
> >    The first failure is the inability to
> find a valid member of 'a'. 
> 
>   Err,  are you sure?  I think 'c_str'
> absolutely is a member of a, see two
> lines earlier.  The actual problem is that without the
> brackets, that's a
> function pointer that you're trying to pass when y.open()
> expects a string.

  And I agree. My analysis is faulty in that the member function is seen,
  but the diagnostic message doesn't say what's wrong. The determination
  of what the error is is left to the casual observer.

> 
>   BTW, have you ever tried STLfilt?  It's highly
> relevant to your interests:

  No I haven't but now that I know something exists I probably will.

  Before I toodle off, let me put some kinder words around what I'm doing. I'm 
not pointing fingers or poking fun. As a result of my own lacks it was 
suggested that I volunteer to provide alternatives to diagnostic messaging for 
the gcc to consider. They are apparently directly addressing the issues 
involved with constructing user oriented diagnostic messages and asked me to 
volunteer to send what I thought could be changed for their consideration. The 
examples given are designed only to illustrate messaging and alternative 
wording for consideration. Each day I address my 'skills' in software and find 
they are more modest than first thought. There is no thought to impose myself 
on the organization or criticize anything in this product. Anything at all. 
Nada. Nothing. 

In brief, the examples are not meant to display what I don't know or seek 
resolution of my lack of skill.
> 
> http://www.bdsoft.com/tools/stlfilt.html
> 
>     cheers,
>       DaveK
> 

Thanks again. 

art


> 
>


Re: messages

2009-04-13 Thread Arthur Schwarz



> > Thanks Dave;'
> > 
> > Acerbic comments below.
> 
> >>   Isn't that exactly what the
> compiler IS doing, as
> >> indicated by "candidates are ... "?
> > 
> >   I don't think so. [ ... ] A clear
> message that arg is wrong I think
> >   is a better approach. 
> 
>   But maybe arg is right and it's something
> else that is wrong?
> 
> >>   It's not always possible for the
> compiler to do
> >> that.
> 

> 
>   Nonono; I didn't mean to impugn anything you're
> doing, just trying to point
> out that it's not easy.  

  Impugn away. I am terribly thin-skinned and the barbs wake me up.
> 

> Should the compiler always assume the function prototypes
> are correct and the
> choice of argument in the function call is wrong?  It
> occurs to me that that
> might be a good rule of thumb for system headers, but
> probably not for headers
> within the user's application.

  In this case the compiler detected an error and provided the correct 
  answer, but the answer lacked clarity for (really) a non-compiler
  writer. Before I say another word (let's see you deal with that one),
  if we look at the statement you have made then, I think, we are left
  nowhere. In particular your caveat on when my suggested reporting
  algorithm is inapplicable. To tear into the statement and bring you to
  a proper state of receptiveness, in absurdum you are saying that even
  though the compiler has detected an error and reported (what it thinks)
  is an error, the compiler is unable to determine that the error occurred
  in arg - the nub of the suggested diagnostic message. I would say
  that given the existing compiler message, if the compiler can't draw this
  conclusion then the message is wrong. I would then say if the compiler
  is clever enough to provide a function template as a candidate for
  correcting the fault, then the compiler has all of the information
  needed to do a comparison, argument by argument, to determine which
  argument(s) are at fault, and can do this recursively (or iteratively
  if you're going to get picky) with all candidate function solutions. 
  I believe your caveat is then moot. The existing diagnostic message
  should be sufficient to allow the compiler to perform the analysis
  necessary to provide a more 'user friendly' (according to 'art') fault
  indication.

  I would go further by saying that (especially) any time the compiler
  is able to provide a candidate solution then the compiler should be
  able to analyze it's own solution against the fault to provide a more
  meaningful message.

  I assert that in those cases where compiler fault analysis fails, then
  under the stated conditions above the compiler has provided a faulty
  initial analysis of the problem and that is a 'bug'.

  Conventional wisdom, in my youth when the Sun shone brighter, was
  that error analysis was O(n**3), so I acknowledge that this is not
  easy. My argument is that the compiler has already done the analysis
  and just fails on the messaging. 

  I believe that it is possible to generalize the analysis tool and 
  avoid case-by-case special purpose code for each 'nasty'. If not 
  completely for all cases and forever, at least for enough cases to 
  make the effort worthwhile. My reasoning is that most semnatic errors 
  fall into broad categories, call it a 'failure in semantics', and
  these broad categories can be leveraged into a generic toolset. The
  pragmatic difficulty is that that existing diagnostic messages would
  have to be reworked into a standardized framework, and I view this
  as a hard problem. (Mind you, this is all without doing a lick of
  work or seeing a line of code - obviously I'm an expert.)

  Now, whew, I may be all wrong and if so, please be gentle.

art



Re: messages

2009-04-13 Thread Arthur Schwarz



--- On Mon, 4/13/09, Joe Buck  wrote:

 them all.
> 
> Consider
> 
> #include 
> struct Foo { int bar;};
> int main() {
>   std::cerr << Foo();
> }
> 
> Try it, the result is ugly, and I often encounter this one

  (Personal opinion - not to be construed as wisdom).
  The issue with the result is:
  1: There is no end-of-line between candidates (or anywhere).
  2: The candidate template is a large, untamed, and unruly beast.
  3: The diagnostic message is not clear. I think it should say
 that the compiler can't find something because of something.
  4: Providing a full template for each candidate is (indeed)
 something of an overkill.

And so in substance I agree, in detail there are some mitigating things that 
can be done. 

art


Re: messages

2009-04-14 Thread Arthur Schwarz


> 
>   So I guess, yes, I'm asking Arthur to suggest rules
> of relevance that would
> enable the compiler to decide what kind of user error is
> implied by a given
> syntax error.
> 
>     cheers,
>       DaveK
> 
You're asking for a lot. I've never been accused of being smart (the quip 
being, 'I've always been admired for it'.)

In one of my previous e-mails I mentioned a criteria of selection. Do nothing. 
The compiler already provides adequate analysis. What is missing is an analysis 
of the analysis to produce more 'user friendly' diagnostic messages. What I 
think we get is a compiler writers' version of a suitable diagnostic. The 
messages seem to indicate what a compiler writer needs to determine what is at 
fault, and perhaps with sufficient detail to determine that the fault (message) 
is at fault. What I suggested is that a separate subsystem be created to 
extract 'meaning' from the compiler writers' message, and present a user 
version of the message. I do not believe that the compiler writers' messaging 
should be removed - it is useful for compiler writers - just that it be 
optioned-out for the user.

Taking the approach that the existing messages are satisfactory the dialog on 
relevance moves a tad to the right. The issue becomes one of comparing the 
detailed messaging to the textual fault. In the original case, one of pointing 
out that arg is at error because is doesn't match known overloads (and some 
other name for templates I suppose). In that way, the user is told that arg 
is at fault rather than having to discover that fact.

The error analysis subsystem, in the case of not finding a suitable overloaded 
function, is one of identifying user provided arguments again found potential 
overload. Essentially something like:

function()  overload()
  arg<1> arg<1>
  arg2<> arg<2> o o o
  o o o  o o o
  arg arg

and finding which arguments fail. There may be more than one answer and some 
heuristic is needed to determine which or how many messages to provide for a 
given failure. To throw an answer of relevancy on the mud-pile, suppose we 
choose to message the cases where there is the least number of failures. Using 
this heuristic for this failure the overloads which contain only 1 argument 
which fails takes precedence over overloads with 2 argument failures and so on. 
This is a mud-pile heuristic, sufficient to start a discussion but probably not 
suitable for ending one.

In most cases I would find it a daunting task to provide an algorithm to decide 
which error, among many, is the 'most important' and should be addressed while 
the others are left unaddressed. The easy answer is to provide an option which 
details the 'depth' of fault diagnostics to provide - avoiding the problem of 
finding the best diagnostic but, again, introducing the notion of fault 
ranking. I also think that for some cases it might be possible to actually 
establish the 'best' wrong answer. Again, ideas are cheap, work is hard.

In one of my previous e-mails I suggested that it might be possible to 
characterize semantic errors and to standardize  existing diagnostic messaging 
to fit the characterization. The process for many 'user friendly' messages then 
becomes one of analysis of the cause of faults against the detailed messaging 
to extract some user oriented messaging. I said that the pragmatics of the 
approach may be hard. 

Now I know that this is all hand-waving and random bits of wisdom. There is a 
wide area for investigation, discussion, and debate. 

Now that I've ended up confusing myself

art


Re: messaging

2009-04-14 Thread Arthur Schwarz

The issues grow ever more complex. Suppose that we're dealing with macro's, 
some similarly named, and there's a typo. Suppose  several layers of template 
expansion are involved and nested deep within one there is some error. Suppose, 
suppose ... .

The motivation is not to expand the problem domain to the point were even 
stating the problem is a problem, but to creep up carefully and gradually on 
some consensus option as to what to do and then to go forward. All the points 
made are valid. At a certain time either the diagnostic message can not 
perceive nor report on the original cause of error, or the report is convoluted 
enough to be unreadable by all but the most diligent.

Let me address some general principles, which, of course, are both mine and may 
be wrong.
1: The purpose of compiler diagnostics is to present faults to a user
   in the most economic way possible.
2: The presentation should be a pointed as possible as to the detected
   fault.
3: The user should be required to understand as little as possible in
   order to understand the faulting message.

The details of specific messaging are not as important as the guidelines.

What I have seen in this thread and in a companion thread, messages, are these 
viewpoints.
1: The user should have some minimal capability to understand the 
   diagnostic messages as they are now.
2: The user is being overwhelmed with information and has difficulty
   sifting through it.
3: The messages show the fix but not the problem.

Clearly I am biased to 2: and 3:. But let me turn to 1; for a moment. 

In order to develop software in most languages, C++ being only one, it is not 
necessary to read nor understand the syntax equations for the language. The 
notion that developers should be compelled to acquire a knowledge of syntax 
equations won't work in practice. There is no authority to compell this 
knowledge nor to deny employment (or hobby work) for someone who doesn't have 
it. It might be nice but ... . So we are left with compiler users with minimal 
or none of the assumed pre-requisite knowledge.

The notion that these unknowledgeable users should be abandoned in provided 
diagnostic messages eventually translates into the compiler being abandoned by 
the users. In the small, probably fine. In the large I would think it 
unacceptable.

And there are competitive compilers. Some with better messaging and better 
messaging resources at the very point where g++ is weakest. You might argue 
that they are 'better in what way?', but I think the real argument is in what 
ways can these other products be a model for g++ to improve itself. Unless the 
notion is that g++ needs no improvement.

A reasoned attitude (I think) is to address each item without prejudice and see 
if there is some common ground, and then to proceed to see what is possible in 
general and what edge cases can't be simply solved. 

I think that there is a way to creep upon a general consensus which may not 
give everyone everything, but will give most something. And I believe the 
solution is not a 'camel by committee' but a more useable product. 

art


Diagnostic Messaging Suggestion

2009-04-16 Thread Arthur Schwarz



Suggested Messaging: Messaging seems redundant in indicating that function has 
been redifined twice. One of the messages should be removed. More to the point, 
I think the messaging may be erroneous - code fragment follows.


g++-4 Diagnostic Messaging

In file included from partition.cpp:66:
irange.h: In function 'std::ostream& operator<<(std::ostream&, 
ciRange_2::sRange_2&)':
irange.h:102: error: redefinition of 'std::ostream& operator<<(std::ostream&, 
ciRange_2::sRange_2&)'
irange.h:102: error: 'std::ostream& operator<<(std::ostream&, 
ciRange_2::sRange_2&)' previously defined here


 Code Fragment 
class ciRange_2 : public iRange_List {   // 
public:
struct sRange_2 { double RLo;// Low  range value
  double RHi; }; // High range value

friend istream& operator>>(istream& stream, ciRange_2::sRange_2& Range);
friend ostream& operator<<(ostream& stream, ciRange_2::sRange_2& Range);
}; // class ciRange_2

istream& operator>>(istream& stream, ciRange_2::sRange_2& Range);

ostream& operator<<(ostream& stream, ciRange_2::sRange_2& Range) {
   stream << setw(9) << Range.RLo << " " << setw(9) << Range.RHi;
}



Re: Diagnostic Messaging Suggestion

2009-04-16 Thread Arthur Schwarz

> 
> Can you show code that reproduces the issue?  My best
> guess is that a
> header file is included twice, and lacks guards, hence the
> message is
> correct: the function is being defined twice, from the same
> source
> location.
> 
> -- James
> 

 Code (unadulterated and full of original lacerations) -

/* 
 * File:   irange.h
 * Author: Arthur Schwarz
 *
 * Created on April 13, 2009, 1:23 PM
 */

#ifndef _IRANGE_H
#define _IRANGE_H
# include 
# include 
# include 
# include 
# include 
# include 
# include "common.h"

class iRange_List : public cDebug{   // input ranges
private:
// Processing of range buffer: 
//  Ranges[Ndx] : Ndx<0..BufferSize-1>
//  if (Ndx == BufferSize) TempStream.write(Ranges[Ndx]; Size += 
BufferSize; Ndx = 0;
fstream TempStream;  // Temporary Stream
static
long const  BufferSize;  // Input buffer size
longNdx; // Index in Ranges buffer
longSize;// Total number ranges used
cRange  ErrorRange;
protected:
cRange* Ranges;  // All input ranges
longErrorCount;  // Number of errors found
protected:
//double Atod(string& Range, long id);
virtual
void DData () { string str(80, ' ');
ostringstream stream(str);
stream << "iRange_List<"
   << setw(9) << Ndx  << ", "
   << setw(9) << Size << ", "
   << setw(9) << ErrorCount << ">" << endl;
cDebug::DData(str);
};
long Next() { if ( ++Ndx < BufferSize) return Ndx;
  TempStream.write((char*)Ranges, sizeof(Ranges));
  Size += BufferSize;
  return (Ndx = 0);
};
void Flush();
public:
iRange_List();
iRange_List(const iRange_List& orig);
virtual ~iRange_List();

long GetSize()  { return Size; }
void PrintRange() { for(long i = 0; i < Ndx; i++) Stdout << setw(9) << i << 
": "
  << Ranges[i]
  << endl;
}; // PrintRange()
virtual
bool Read() = 0;
cRange& operator[](long Ndx) { return ((Ndx >=0 ) && (Ndx < Size))? 
Ranges[Ndx]: ErrorRange; }
}; // class iRange_List

class ciRange_2 : public iRange_List {   // 
public:
struct sRange_2 { double RLo;// Low  range value
  double RHi; }; // High range value

ciRange_2() : iRange_List() { }
virtual
bool Read();
friend istream& operator>>(istream& stream, ciRange_2::sRange_2& Range);
friend ostream& operator<<(ostream& stream, ciRange_2::sRange_2& Range);
}; // class ciRange_2

class ciRange_3 : public iRange_List {   // 
public:
struct sRange_3 { double  RLo;   // Low  range value
  double  RHi;   // High range value
  longDatum; };  // User supplied datum
ciRange_3() : iRange_List() { }
virtual
bool Read();
friend istream& operator>>(istream& stream, sRange_3& Range);
friend ostream& operator<<(ostream& stream, ciRange_3::sRange_3& Range);
}; // class ciRange_3

#endif  /* _IRANGE_H */


//
//Debug Streams
//

istream& operator>>(istream& stream, ciRange_2::sRange_2& Range);
istream& operator>>(istream& stream, ciRange_3::sRange_3& Range);

ostream& operator<<(ostream& stream, ciRange_2::sRange_2& Range) {
   stream << setw(9) << Range.RLo << " " << setw(9) << Range.RHi;
}

ostream& operator<<(ostream& stream, ciRange_3::sRange_3& Range) {
   stream << setw(9) << Range.RLo << " " << setw(9) << Range.RHi << " " << 
setw(9) << Range.Datum;
}




Re: Diagnostic Messaging Suggestion

2009-04-16 Thread Arthur Schwarz

I forgot to say 'thanks James', thanks.

Well, spurred on by the whimsy that I need a solution to the problem (however 
dolorous), I experimented. I've commented most everything at least once and the 
net effect is that only the 'operator<<' gets a nasty message. I've checked the 
include files that I've written and they all seem clean of heresies. The 
'operator>>' files are unaffected, and with them gone, I still get an error on 
the 'operator<<' function.

The only thing that I can think of, and I think it remote, is that the 
functions refer to a public structure internal to a class. The 'operator>>' 
functions refer to their respective classes. Again, I've removed all of my 
friends but one 'operator<<' and this gets the error.

Now I think I know C++ (although, to be honest, I have strong, personal, 
doubts) and I can't think what I missed.

However, the initial statement still holds, the second diagnostic messages adds 
no clarity and seems redundant. Further, if there was a cause of conflict with 
a redefinition, it would be useful to include the original conflicting 
declaration. Perhaps something like:

<>: error: redefinition of function at <> illegal.
 note: istream& operator>> (bool& val );
   istream& operator>> (short& val );
o o o

the note: stuff is from cplusplus.com @ 
 http://cplusplus.com/reference/iostream/istream/operator%3E%3E/

So, a concrete suggestion at to messaging and an individual first, a puzzler. I 
really need help on the puzzler.

thanks
art



Re: Diagnostic Messaging Suggestion

2009-04-16 Thread Arthur Schwarz

Thanks to everyone. 

The rock has dropped. The answer is quoted below:

"My best guess is that a header file is included twice, and lacks guards, hence 
the message is correct: the function is being defined twice, from the same 
source location."

I had put my friends following my 'include guard'. As we all know, when your 
guard is down you can get sucker-punched.

Although you should never try to teach an old dog new tricks, with luck and a 
good tail wind this will never happen again.

thanks
art

PS: You are now all my best friend. Sorry.


cout Issue

2009-05-11 Thread Arthur Schwarz

Program and particulars below.

When line 27 is commented out, line 26 is output. When line 27 is not 
commented, line 26 is not output except that if x.file contains a line feed the 
null line line 26 & line 27 are output. If x.file does not contain a line feed, 
only line 27 is output.

Does the line feed have an effect on the 'cout <<' of line 26 of the program?

Note. The code is awful and this is an example.

art

g++-4 (GCC) 4.3.2 20080827 (beta) 2


x.cpp

  1 # include 
  2 # include 
  3 # include 
  4 # include 
  5 # include 
  6
  7 using namespace std;
  8
  9 ifstream  x("x.file", ios::in);
 10
 11 struct y {
 12   double a;
 13   double b;
 14 } yNot;
 15
 16 int main(int argc, char** argv) {
 17   char  Line[512];
 18   long  LineNo = 0;
 19   while ( !x.eof() ) {
 20  LineNo++;
 21  x.getline(Line, 512);
 22  istringstream Phfft(Line);
 23yNot.a = -1;
 24yNot.b = -2;
 25Phfft >> yNot.a >> yNot.b;
 26cout << setw(4) << LineNo << ": " << Line;
 27cout << "   a:" << yNot.a << "  b:" << yNot.b;
 28  cout << endl;
 29   }
 30   return 0;
 31 }

x.file
1 2