Internal Compiler Error // Stupid Standards?

M

Matthew Del Buono

Don't try to solve the problem. I've found a way -- around or fixing it. I'm
just curious as to whether this is Microsoft's problem in their compiler or
if there's a standard saying this is to be true (not necessarily an internal
compiler error, but still an error)

This may just a bit OT, but I decided to post it here instead of Microsoft
because my question is more directed towards standards...

Of course, any other day I would have been on my Linux computer with GCC,
but today I didn't have that option. I have the following function. I tried
to standarize it (CList => vector) but just about every function is
different. Basically, type T and A are about the same (the type of the
vector). The functions are somewhat self explanatory... A POSITION is
basically an index; not exactly, but for our purposes we will say that it
is...

template <class T, class A>
CList<T, A>& copyList(CList<T, A>& mod, const CList<T, A>& orig)
{
POSITION curpos;

// Make sure mod is empty
while (!mod.IsEmpty())
mod.RemoveHead();


#pragma warning(disable:4706)
if (!(curpos = orig.GetHeadPosition()))

return mod;
else
mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));

orig.GetNext(curpos);
while (curpos)
{
mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));
orig.GetNext(curpos);
};

// Do one more...
mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));
orig.GetNext(curpos);


return mod;
}

I get the following error:
fatal error C1001: INTERNAL COMPILER ERROR

Trying to compile with option /Bd (which is supposed to help you locate
where the internal error occurs) ends up crashing the compiler, instead of
yielding a C1001. I've found out that the problem lies in the #pragma
warning(disable:4706).

By placing the #pragma warning(disable:4706) outside of the template, the
template works fine. Is there a practical reason for this? Or is it just one
of the many bugs that M$ produces every year...

Microsoft Visual C++ 6.0 using MFC
------------------------------------------

On an unrelated note, actually, I have one more question about ANSI
standards. In the same block of code, there is a messy line (which you
probably all yelled at when you read it) which reads

mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));

(similar ones follow)

Of course nobody likes to use a const_cast. The problem was that I was
getting a warning, stating that a non-standard extention was being used. I
try to make my programs as standard as possible. When compiling the (I
thought) pratical line:

mod.AddHead(orig.GetAt(curpos));

I got the following warning:

c:\program files\microsoft visual
studio\myprojects\digitaldarkroom\stdafx.h(53) : warning C4239: nonstandard
extension used : 'argument' : conversion from 'class CFilter' to 'class
CFilter &'
A reference that is not to 'const' cannot be bound to a non-lvalue

That line struck me: "A reference that is not to 'const' cannot be bound to
a non-lvalue." Why exactly is that? It seems like it's just another
compilcation in the midst of C++... I don't see any practical purpose for
not being able to bind a non-lvalue to reference to a non-const. In fact, it
almost makes more sense. Obviously the line a = 4 is legal, but taking out
the reference, it is exactly the same thing. A non-const (but not a
reference) is being bound by a non-lvalue (obviously you can't write 4 = a).
Thus, I was forced to "de-const" the paramter to make it standardized.
Surely, the line

mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));

is much uglier, but at least it's standardized. Certainly nobody ever likes
to run with const_casts in their programs. It's almost as bad as a
reinterpret_cast and completely oversteps the point of a type-strict
language. Of course there are other ways around it, too, but this was the
easiest to code, in my opinion.

So why exactly is it there? Makes absolutely no sense to me...

-- Matt
 
J

John Harrison

Matthew Del Buono said:
Don't try to solve the problem. I've found a way -- around or fixing it. I'm
just curious as to whether this is Microsoft's problem in their compiler or
if there's a standard saying this is to be true (not necessarily an internal
compiler error, but still an error)

This may just a bit OT, but I decided to post it here instead of Microsoft
because my question is more directed towards standards...

Of course, any other day I would have been on my Linux computer with GCC,
but today I didn't have that option. I have the following function. I tried
to standarize it (CList => vector) but just about every function is
different. Basically, type T and A are about the same (the type of the
vector). The functions are somewhat self explanatory... A POSITION is
basically an index; not exactly, but for our purposes we will say that it
is...

template <class T, class A>
CList<T, A>& copyList(CList<T, A>& mod, const CList<T, A>& orig)
{
POSITION curpos;

// Make sure mod is empty
while (!mod.IsEmpty())
mod.RemoveHead();


#pragma warning(disable:4706)
if (!(curpos = orig.GetHeadPosition()))

return mod;
else
mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));

orig.GetNext(curpos);
while (curpos)
{
mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));
orig.GetNext(curpos);
};

// Do one more...
mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));
orig.GetNext(curpos);


return mod;
}

I get the following error:
fatal error C1001: INTERNAL COMPILER ERROR

Trying to compile with option /Bd (which is supposed to help you locate
where the internal error occurs) ends up crashing the compiler, instead of
yielding a C1001. I've found out that the problem lies in the #pragma
warning(disable:4706).

By placing the #pragma warning(disable:4706) outside of the template, the
template works fine. Is there a practical reason for this? Or is it just one
of the many bugs that M$ produces every year...

No idea, but the effect of pragmas is completely compiler dependent and if
MS want to make it a requirement that you put this pragma outside of any
templates they can.
Microsoft Visual C++ 6.0 using MFC
------------------------------------------

On an unrelated note, actually, I have one more question about ANSI
standards. In the same block of code, there is a messy line (which you
probably all yelled at when you read it) which reads

mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));

(similar ones follow)

Of course nobody likes to use a const_cast. The problem was that I was
getting a warning, stating that a non-standard extention was being used. I
try to make my programs as standard as possible.

Well why in God's name are you using CList? Use std::list instead (not
std::vector), its both standard and better designed. Obviously this will
mean some code rewriting.
When compiling the (I
thought) pratical line:

mod.AddHead(orig.GetAt(curpos));

I got the following warning:

c:\program files\microsoft visual
studio\myprojects\digitaldarkroom\stdafx.h(53) : warning C4239: nonstandard
extension used : 'argument' : conversion from 'class CFilter' to 'class
CFilter &'
A reference that is not to 'const' cannot be bound to a non-lvalue

That line struck me: "A reference that is not to 'const' cannot be bound to
a non-lvalue." Why exactly is that? It seems like it's just another
compilcation in the midst of C++... I don't see any practical purpose for
not being able to bind a non-lvalue to reference to a non-const. In fact, it
almost makes more sense.

It's alleged that the possibility of binding a temporary (or non-lvalue) to
a non-const reference is confusing. This was feedback during the
developement of C++ according to Bjarne Stroustrup (there's a post in the
archives of comp.lang.c++ to that effect, maybe you could find it).

I have my doubts but it not usually a problem in well written code, so its
not something that bothers me too much. It does bother me that some
compilers don't enforce this rule correctly, that does lead to confusion.
Obviously the line a = 4 is legal, but taking out
the reference, it is exactly the same thing. A non-const (but not a
reference) is being bound by a non-lvalue (obviously you can't write 4 = a).
Thus, I was forced to "de-const" the paramter to make it standardized.
Surely, the line

mod.AddHead(const_cast<CList<T, A>&>(orig).GetAt(curpos));

is much uglier, but at least it's standardized. Certainly nobody ever likes
to run with const_casts in their programs. It's almost as bad as a
reinterpret_cast and completely oversteps the point of a type-strict
language. Of course there are other ways around it, too, but this was the
easiest to code, in my opinion.

What is the type of A in this case? If you made A a const reference I
believe the code should compile without the const_cast.
 
C

Carl Ribbegaardh

Matthew Del Buono said:
Don't try to solve the problem. I've found a way -- around or fixing it. I'm
just curious as to whether this is Microsoft's problem in their compiler or
if there's a standard saying this is to be true (not necessarily an internal
compiler error, but still an error)

This may just a bit OT, but I decided to post it here instead of Microsoft
because my question is more directed towards standards...

Of course, any other day I would have been on my Linux computer with GCC,
but today I didn't have that option. I have the following function. I tried
to standarize it (CList => vector) but just about every function is
different. Basically, type T and A are about the same (the type of the
vector). The functions are somewhat self explanatory... A POSITION is
basically an index; not exactly, but for our purposes we will say that it
is...

template <class T, class A>
CList<T, A>& copyList(CList<T, A>& mod, const CList<T, A>& orig)
{
POSITION curpos;

// Make sure mod is empty
while (!mod.IsEmpty())
mod.RemoveHead();


#pragma warning(disable:4706)
if (!(curpos = orig.GetHeadPosition()))


The compiler warning which you disables is "assignment within conditional
expression".
Are you 100% sure you aren't accidently using the assignment operator (=)
instead of the comparison operator (==) ?

By placing the #pragma warning(disable:4706) outside of the template, the
template works fine. Is there a practical reason for this? Or is it just one
of the many bugs that M$ produces every year...

You can turn off warnings by issuing pragmas. I think it's useful, but I do
find out first what the warning's about. If I decide that the code is fine,
then I'll just add a pragma. :)

/Carl
 
M

Michiel Salters

Matthew Del Buono said:
I got the following warning:

c:\program files\microsoft visual
studio\myprojects\digitaldarkroom\stdafx.h(53) : warning C4239: nonstandard
extension used : 'argument' : conversion from 'class CFilter' to 'class
CFilter &'
A reference that is not to 'const' cannot be bound to a non-lvalue

That line struck me: "A reference that is not to 'const' cannot be bound to
a non-lvalue." Why exactly is that?

int f() { return 42; }
void increment( int& v ) { ++v; }
increment(f());

What is incremented? Where does the result go?

Regards,
Michiel Salters
 
M

Marc

Michiel said:
int f() { return 42; }
void increment( int& v ) { ++v; }
increment(f());

What is incremented? Where does the result go?

a temporary containing 42 could be incremented, and the result then be
dropped. And everything would be optimized away in the end.

What's wrong with allowing it ? There is no ambiguity.
 
J

J. Andrew MacDonald

Michiel said:
int f() { return 42; }
void increment( int& v ) { ++v; }
increment(f());

What is incremented? Where does the result go?

I guess the temporary from f() would be incrememented, but that'll just "disappear".

The warning is complaining about passing a temporary into a function that could
possibly changes its value (due to a non-const reference).

If you changed the increment method to return the incremented value, you'd be
ok. Or in the case of the warning, whatever you're trying to pass a CFilter
into... make it "const CFilter &".

int f() { return 42; }
const int increment(const int & v) { return(v++); }
int value = increment(f());
 
P

puppet_sock

Matthew Del Buono said:
Trying to compile with option /Bd (which is supposed to help you locate
where the internal error occurs) ends up crashing the compiler, instead of
yielding a C1001. I've found out that the problem lies in the #pragma
warning(disable:4706).

By placing the #pragma warning(disable:4706) outside of the template, the
template works fine. Is there a practical reason for this? Or is it just one
of the many bugs that M$ produces every year...

Urm. Well, it's a tad off topic, and also a tad sarcastic and snide.
But I've already got today's headache, so...

C1001 is the "I'm in trouble but don't know how to get out" message.
Someplace, a "sensibility" check has failed, indicating that something
has gone badly wrong. But the compiler can't pinpoint it, and has
no way of correcting it. Generally, in such situations, anything
output after that is mighty suspect at best.

Dealing with it can be frustrating. It can happen in perfectly correct
and legal code, even according to MS's definition of those words. Or
it can happen due to a real error in the code, and indicate that the
compiler has misdiagnosed something, or failed to correctly handle
the error condition. For example, it might be that there is some
bug in the compiler that does not correctly deal with some category
of syntax errors, in some set of conditions. Or there may be some
poorly mapped limitation of the compiler, say depth of this-n-that
combined with width of that-n-this, etc., that only shows up when
you skate close enough to the edge on several things.

About all you can do is nudge and poke your code till the error goes
away.
Socks
 
M

Matthew Del Buono

J. Andrew MacDonald said:
I guess the temporary from f() would be incrememented, but that'll just "disappear".

The warning is complaining about passing a temporary into a function that could
possibly changes its value (due to a non-const reference).

If you changed the increment method to return the incremented value, you'd be
ok. Or in the case of the warning, whatever you're trying to pass a CFilter
into... make it "const CFilter &".

int f() { return 42; }
const int increment(const int & v) { return(v++); }
int value = increment(f());

Ah, okay, I get it. Honestly I didn't care about the pass-back from the
value. So I guess it's that I didn't properly understand its wording. Thanks
for explaining it.

-- Matt
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top