From jnhall@motsat.sat.mot.com Mon Aug 16 19:13:02 1993 Date: Mon, 16 Aug 1993 16:12:56 -0700 From: Joseph Hall To: comments@mac.archive.umich.edu Subject: TC_TPM_TCL_SC++_Bug_List_1.2 I'm the maintainer. Uploaded a copy to you just now. When you figure out where to put it, drop me a note. It's UNIX text ... -joseph Joseph Nathan Hall | "If you can't dazzle them with brilliance, Software Architect | baffle them with 'x ^= y ^= x ^= y;'" Gorca Systems Inc. | ----- joseph@joebloe.maple-shade.nj.us (home) ----- (on assignment) | (602) 732-2549 jnhall@sat.mot.com (work) Here, again, is the short bug list. No, the long bug list still doesn't exist and, well, may not ever. I've simply been too busy to verify most of these. Neither has anyone offered any comments nor verified any of them for me. :-( Of course, in the past couple of weeks I have received a steady stream of *requests* for this list. I'm happy to honor them but I haven't had time recently. I'll try to mail out a few in the next couple of days. If any of you out there feel you need something to do in your spare time, please feel FREE to try to reproduce these bugs, explain why they aren't bugs, and so on. Kudos to Greg Gilley and John Werner for submitting many, many interesting and well-documented reports. Thanks to the rest of you submitters as well. -joseph SYMANTEC C/C++/TCL BUG LIST Version 1.2 (15 August 1993) Maintained (if you can call it that) by Joseph N. Hall Part 1: Short Ones CHANGES since last release: Added note to (12), couldn't reproduce it. Appended discussion to (17). Removed non-bug (39). Added bugs (40)-(45). ============================================================================ Contents: ---------------------------------------------------------------------------- (1) The MAXLONG and MAXINT definitions conflict in files Values.h (Mac #includes) and Global.h (TCL Core). (2) C++ generates garbage code if given an empty destructor. (3) If you call endl on an ostream, it should flush any pending output; however, streambuf::sync doesn't perform the sync operation. (4) One of the include files is misnamed. 'strstrea.h' should be 'strstream.h'. (5) Calls to Pascal functions taking extended or double arguments are incorrect when the argument comes from a struct or an array. (6) Symantec C++ calls a library routine for longint multiplication when generating 68020-only code. (7) Some errors encountered during compilation are not handled properly. (8) The LoadSeg patch in CApplication.asm can cause unnecessary heap scrambling every time LoadSeg is called for a segment in memory. (9) CPane::ChangeSize is not Prepare()d correctly. (10) Calling ValidRect in CPane::ChangeSize isn't really a good idea. (11) The class browser is confused by precompiled headers. (12) Nifty problem with SC++ #include directive (13) Problem w/ declaration using elaborated struct type in C++ (14) Large precompiled headers yield out of memory error in debugger (15) Bug in TCL 1.1.3 CRunArray (16) Unspecified problems in C++ optimizer trash data passed on the stack (17) Template declaration bombs compiler. (18) Fixes to new_by_name according to Object Factory (19) Elaborated class name in template expansion confuses compiler (20) C++ compiler accepts static constructor (21) Filenames reported in template error messages can be incorrect (22) Constructors can be defined to return int (23) Problem w/ templates and __pasobj (24) Bug in MacTraps glue causes problems w/ Smart Linking (25) Assorted debugger complaints (26) Potential bug in new (27) Far data woes (28) Prototype in FormatX2Str has changed (29) The "bug in Lippman" (for all T, class C is a friend of Foo) (30) More troubles with elaborated class names (31) 0 in comma-expression not converted to int* following return (32) Can't take the address of a register variable -- NOT! (33) Errors in THINK C User Manual (34) SC++ accepts return value in function w/ void return type (35) SC++ does not enforce const reference parameter (36) Problem w/ UNIX compatible header stat.h (37) Optimizer screws up code involving Boolean variables (38) Problem deactivating CPopupPanes (possibly ValidRects the wrong area) (39) [Deleted, not a bug]: Incorrect code generated for unsigned char >= 0 (40) '.o' files don't get re-made using Make (41) Surprise, surprise, 'comp' is reserved in SC++ (42) SC++ asm() doesn't work w/ relaxed ANSI (43) Use of MAXFLOAT is screwed because ... (44) Linker merged two static arrays in separate source files. (45) Bugs in CBartender::SetMenuBarState(), EqualMem(). ============================================================================ ============================================================================ From: igorl@uiuc.edu (Igor Livshits) ---------------------------------------------------------------------------- (1) The MAXLONG and MAXINT definitions conflict in files Values.h (Mac #includes) and Global.h (TCL Core). ============================================================================ [NOTE: I don't particularly approve of the NULL = ((void *) 0) suggested here, since this isn't proper C++. I would recommend using 0 for NULL or using a NULL defined as 0. Of course, you can use explicit casts on NULL, e.g., (foo_t *) NULL. --JNH] Actually, this is a remnant from THINK C 5 -- too bad they did not fix it. The MAXLONG and MAXINT definitions conflict in files Values.h (Mac #includes) and Global.h (TCL Core). My fix is to augment the Global.h file in the following manner (at the start of the file): #ifndef NULL #define NULL ((void *) 0) /* Nil pointer value */ #endif #ifndef MAXINT #define MAXINT 32767 /* Maximum int value */ #endif #define MININT -32768 /* Mininum int value */ #ifndef MAXLONG #define MAXLONG 0x7FFFFFFF /* Maximum long int value */ #endif #define MINLONG 0x80000000 /* Minimum long int value */ ============================================================================ From: ggilley@mv.us.adobe.com (Greg Gilley) ---------------------------------------------------------------------------- (2) C++ generates garbage code if given an empty destructor. ============================================================================ class foo { public: foo() {} ~foo() {} }; foo x; foo::~foo(void): 00000000: 4E56 0000 LINK A6,#$0000 00000004: 48E7 1020 MOVEM.L D3/A2,-(A7) 00000008: 246E 0008 MOVEA.L $0008(A6),A2 0000000C: 262E 000C MOVE.L $000C(A6),D3 00000010: 200A MOVE.L A2,D0 00000012: 6600 4CDF BNE *+$4CE1 ; 00004CF3 00000016: 0408 4E5E SUBI.B #$4E5E,A0 ; '^' 0000001A: 4E74 0008 RTD #$0008 0000001E: 8C5F 5F64 745F DC.B $80+$0C, '__dt__3fooFv', $00 5F33 666F 6F46 7600 ============================================================================ From: ggilley@mv.us.adobe.com (Greg Gilley) ---------------------------------------------------------------------------- (3) If you call endl on an ostream, it should flush any pending output; however, streambuf::sync doesn't perform the sync operation. ============================================================================ If you call endl on an ostream, it should flush any pending output, however, streambuf::sync doesn't perform the sync operation... The proposed fix follows // Make the external character stream and the streambuf consistent // with each other. int streambuf::sync() { // The get area will always be empty in streambuf. Any characters put // can't be flushed away if (_pptr == _pbase) return 0; // nothing put so sync would have nothing to do else return overflow(); } ============================================================================ From: ggilley@mv.us.adobe.com (Greg Gilley) ---------------------------------------------------------------------------- (4) One of the include files is misnamed. 'strstrea.h' should be 'strstream.h'. ============================================================================ One of the include files is misnamed. 'strstrea.h' should be 'strstream.h'. Obviously this was just copied over from dos. However, if you #include under dos, it will find 'strstrea.h', so on the Macintosh, the file name should be 'strstream.h' to be compatible with machines without braindead file names. ============================================================================ From: Andrew Shearer ---------------------------------------------------------------------------- (5) Calls to Pascal functions taking extended or double arguments are incorrect when the argument comes from a struct or an array. ============================================================================ Here's a repeat of the bug report I sent to comp.sys.mac.programmer last week. Symantec acknowleged that it was a known bug. --------------- I've had a strange problem recompiling an existing TCL project with Symantec C++ which may be a bug in the compiler, though the situation is so common I'd have thought that someone would have run into it during the beta stage. When calling a Pascal function which takes an extended or double argument, such as X2Fix or X2Frac, the C++ compiler correctly passes the address of the 10-byte extended argument if the value comes from a variable. If the argument comes from a struct or array, though, the compiler passes the first 4 bytes of the extended directly. Since the first 4 bytes usually point somewhere deep in the 32-bit yonder when interpreted as an address, the Pascal routine crashes with a bus error (or at least gives something wildly different than the right answer). A workaround is to copy each structure or array member into a temporary variable. (It works, but it's time-consuming, and it's a lot of code to change.) Here's a test case. I've tried this with 68000/68020 code generation, optimization on/off, and with a new project with default options. (begin test.cp) #include typedef struct $ short inconsequentialData; extended x;  ExtendedStruct; static Fixed foo( ExtendedStruct *test) $ return X2Fix(test->x);  (end test.cp) The code through the C compiler: foo: 00000000: 4E56 0000 LINK A6,#$0000 00000004: 42A7 CLR.L -(A7) 00000006: 206E 0008 MOVEA.L test(A6),A0 0000000A: 4868 0002 PEA $0002(A0) ; <-- 0000000E: A846 _X2Fix 00000010: 201F MOVE.L (A7)+,D0 00000012: 4E5E UNLK A6 00000014: 4E75 RTS 00000016 The PEA instruction pushes the address of the extended on the stack, which X2Fix dereferences. The C++ compiler gives: foo(ExtendedStruct *): 00000000: 4E56 0000 LINK A6,#$0000 00000004: 594F SUBQ.W #$4,A7 00000006: 206E 0008 MOVEA.L $0008(A6),A0 0000000A: 2F28 0002 MOVE.L $0002(A0),-(A7) ; <-- 0000000E: A846 _X2Fix 00000010: 201F MOVE.L (A7)+,D0 00000012: 4E5E UNLK A6 00000014: 205F MOVEA.L (A7)+,A0 00000016: 584F ADDQ.W #$4,A7 00000018: 4ED0 JMP (A0) 0000001A This code pushes the first long of the extended on the stack, which X2Fix then dereferences, usually causing a bus error. ============================================================================ From: Andrew Shearer ---------------------------------------------------------------------------- (6) Symantec C++ calls a library routine for longint multiplication when generating 68020-only code. ============================================================================ Also, as has already been reported, Symantec C++ calls a library routine for longint multiplication when generating 68020-only code. It's easy to see when disassembling the Vector sample project-- the call in Square() appears at the top of the screen.) ============================================================================ From: ggilley@mv.us.adobe.com (Greg Gilley) ---------------------------------------------------------------------------- (7) Some errors encountered during compilation are not handled properly. ============================================================================ If you encounter an error such as code overflow or duplicate resource id while compiling, Think throws away all the successful results up to that point and aborts the compilation. These errors should be logged like other errors and the compilation should continue. ============================================================================ From: werner@soe.berkeley.edu (John Werner) ---------------------------------------------------------------------------- (8) The LoadSeg patch in CApplication.asm can cause unnecessary heap scrambling every time LoadSeg is called for a segment in memory. ============================================================================ In CApplication.asm, the patch to LoadSeg has some new code that finds the size of the resource to be loaded and reserves space for it low in the heap, to avoid fragmentation. The problem (I think) is that it does this all the time, even if the code resource is already loaded. This can cause unnecessary heap scrambling every time LoadSeg is called for a segment that's already in memory. This happens quite often if you use the segmentation strategy of calling UnloadSeg for lots of non-critical segments each time through the event loop. If this really is a problem and I'm not imagining it, the fix is pretty simple. The new/changed lines are marked with '!': Near the top of the patch: GetResource ! MOVE.B D6, ResLoad ; restore the old ResLoad setting ! MOVE.L (SP)+, A3 ; get the unloaded resource BEQ.S @bail ; let normal error handling take it ! ! ; See if the resource is already loaded ! TST.L (A3) ! BNE.S @alldone ; Get the resource's size and reserve space for it SUBQ.L #4, SP ! MOVE.L A3, -(SP) SizeResource MOVE.L (SP)+, D0 ResrvMem ; any errors will repeat down below !@bail move.b #kAllocCanFail, -(sp) ; this allocation And near the end: !@alldone move.l origLoadSeg, 56(sp) ; store original LoadSeg on stack movem.l (sp)+, a0-a5/d0-d7 ; restore regs rts ; return to original LoadSeg ============================================================================ From: werner@soe.berkeley.edu (John Werner) ---------------------------------------------------------------------------- (9) CPane::ChangeSize is not Prepare()d correctly. ============================================================================ In CPane::ChangeSize, there's some code that looks like this: Refresh(); /* Force draw of pane at new size */ RefreshBorder(); /* TCL 1.1.1 DLP 10/1/91 */ /* If autoRefresh is FALSE (and */ /* other safety checks), we do */ /* not want to redraw the area */ /* which is common to the old and */ /* new pane size. Note that the */ /* Refresh method will have set */ /* the port for us already. */ if (!autoRefresh && ReallyVisible()) { This used to be correct, but I think the call to RefreshBorder that was added in 1.1.1 broke it, because RefreshBorder calls GetWindow()->Prepare(); So if there really is a border, Prepare needs to get called for this view again at some point. ============================================================================ From: werner@soe.berkeley.edu (John Werner) ---------------------------------------------------------------------------- (10) Calling ValidRect in CPane::ChangeSize isn't really a good idea. ============================================================================ In the same piece of code in CPane::ChangeSize, I think one other safety check needs to be added to the "!autoRefresh" case. If there are any pending updates for the window, calling ValidRect isn't really a good idea. Probably the cleanest way to fix this would be to call RectInRgn to see if any of the rects being passed to ValidRect intersect with the window's update region. If they do, they shouldn't be "validated." A simpler fix would just be to remember if the update region was non-empty at the top of ChangeSize, and if it was, dispense with all the ValidRect calls. ============================================================================ From: werner@soe.berkeley.edu (John Werner) ---------------------------------------------------------------------------- (11) The class browser is confused by precompiled headers. ============================================================================ This one is actually a bug in the class browser. On pages 295-296 of the manual it says "For instance, to see the declaration of the CBureaucrat class, double-click on the CBureaucrat box. The editor opens the file CBureaucrat.h...." If I try this, it opens CBureaucrat.cp instead, and highlights the first occurrance of "CBureaucrat", which isn't too useful. For some other classes, double-clicking correctly brings up the .h file. I think what's going on is that precompiled headers are confusing the class browser. It can't find the header file that CBureaucrat was declared in, so it figures that the source file is the next best thing. This is really annoying. ============================================================================ From: werner@soe.berkeley.edu (John Werner) ---------------------------------------------------------------------------- (12) Nifty problem with SC++ #include directive ============================================================================ [I was not able to reproduce this, 15 Aug 93. Perhaps this is an example of TPM "getting confused" from time to time about where its sources and headers are? -- Ed.] Compiling the following line of code with Symantec C++ produces an error because the compiler can't find the file "printf": #include // Because I want the "printf" function If you change the comment to use the /* ... */ syntax, it works fine. ============================================================================ From: werner@soe.berkeley.edu (John Werner) ---------------------------------------------------------------------------- (13) Problem w/ declaration using elaborated struct type in C++ ============================================================================ Here's another C++ compiler bug, I think. The following piece of code won't compile. It gives an error on the next-to-last line (followed by lots of nonsense errors): struct TMyPtr { TMyPtr(struct TMyObj *obj); struct TMyObj *fObj; }; struct TMyObj { void AddRef(); }; TMyPtr::TMyPtr(TMyObj *obj) : fObj(obj) { fObj->AddRef(); // <-- Error: 'AddRef' is not a member of struct 'TMyObj' } If you reverse the order in which TMyPtr and TMyObj are declared, it compiles without errors. ============================================================================ From: koehn@macc.wisc.edu Sun Jun 27 23:02:05 1993 ---------------------------------------------------------------------------- (14) Large precompiled headers yield out of memory error in debugger ============================================================================ Well, the one major one that I have been able to nail down is: If you use large precompiled headers (i.e. precompiling all TCL Headers) the debugger will give you an out of memory error if you try to view variables. This behavior seems to correspond with the last character of the variable name you're trying to view being cut off. ============================================================================ From: koehn@macc.wisc.edu Sun Jun 27 23:02:05 1993 ---------------------------------------------------------------------------- (15) Bug in TCL 1.1.3 CRunArray ============================================================================ In TCL 1.1.3, there is a bug in CRunArray: if the any element(s) in the array have a value of zero, CRunArray::FindSum crashes with a divide by zero error. This can be fixed by inserting the line: if (currRun->value) in front of the line: currIndex -= (currSum - aSum -1) / currRun->value + 1; ============================================================================ From: koehn@macc.wisc.edu Sun Jun 27 23:02:05 1993 ---------------------------------------------------------------------------- (16) Unspecified problems in C++ optimizer trash data passed on the stack ============================================================================ Also, I have found problems in the C++ optimizer, but cannot nail them down to an exact bug, but I have had the optimizer trash data being passed on the stack. ============================================================================ From: ??? ---------------------------------------------------------------------------- (17) Template declaration bombs compiler ============================================================================ Here's yet another Symantec C++ compiler crash, on templates this time. If you compile the following file, you get an error message and then drop into the debugger at _DeQueue+0188. It probably doesn't take this much code to crash it, but I decided this was a small enough test case.... // Crash.cp #include #include class GenList : public CObject { public: void IGenList(); protected: void Append(CObject *obj) { fList->Append(obj); }; private: CList *fList; }; template class PList : public GenList { public: void Append(T *t) { GenList::Append(t); }; }; class CFoo : public CObject { public: Point loc; virtual void Draw(); }; class CBar : public CDocument { public: void IBar(); private: PList *fFoos; // <--- This line makes it crash }; [Discussion from comp.sys.mac.programmer -Ed.] In article <22lkc8$b9t@fizban.solace.hsh.se>, Lars Farm wrote: > Templates work ok as long as you write legit c++. No they don't. If you want proof, try compiling a declaration for a template class that has inline functions. But save all your files first, because the compiler will crash. The example I ran into looked something like this: class base { protected: void foo(void * a); } template class crash : public base { public: void foo (T *t) { inherited::foo(t); }; }; This is perfectly legitimate code which is often useful as a type-specific wrapper around a generic container class. Most of the code can live in the non-type-specific base class, and the type-specific subclasses only have inline functions and maybe a constructor or two. This way you get the type safety of template classes without getting an entire copy of the classes code every time you need a container for a different kind of object I've also had trouble trying to pass PascalObject descendants to template functions like this: template void foo(T *t) { ... } CObject *obj = ...; foo(obj); I think this one just produced bizarre errors rather than crashes. [Later ... -ed.] In article , shawn@jubal (Shawn Lavin/ MDL SL 1375) wrote: > > template class crash : public base { > > void foo (T *t) { inherited::foo(t); }; > > }; > > Only one problem with that, the previous poster (Lars.Farm@ts.hsh.se) > indicated legimate C++, the inherited keyword does not qualify : Fine. Then replace it with "base::foo(t);". It'll still crash. [Still Later ... -ed.] In article , shawn@jubal (Shawn Lavin/ MDL SL x1375) wrote: > I don't doubt that John is getting a crash, but I know from > experience that the cause is not quite as simple as he indicates. Not quite, but really close. I screwed up and left out the crucial thing that makes it crash. The bug doesn't show up until you actually try to _use_ the template class with inline functions. Here's some code that demonstrates both of the bugs I mentioned. I compiled (or tried to) both of them with the default C++ compiler settings in a brand-new project. // Bug # 1: this one crashes the compiler. class base { protected: void foo(void * a); }; template class crash : public base { public: void foo (T *t) { inherited::foo(t); }; }; class boom { crash *mycrash; // This line triggers the crash }; // Bug #2: weird error messages class __pasobj Pclass { public: int x; }; template int GetX (class T *aT ) { // Line 8 return aT->x; } static void test() { Pclass *p = new Pclass; int xp = GetX(p); // Line 15 } The errors it gives are: File Òbug.cpÓ; Line 8 Error: template-argument 'T' not used in function parameter types File Òbug.cpÓ; Line 15 Error: no match for function 'GetX' Looking for GetX(Pclass) I tried changing the function signature to template int GetX (class __pasobj T *aT ) but it had no effect. The combination of these bugs makes templates next to useless in my TCL apps, which is why I keep complaining about them. ============================================================================ From: ??? ---------------------------------------------------------------------------- (18) Fixes to new_by_name according to Object Factory ============================================================================ >Has anybody else come across a bug when using new_by_name in SC++? I tried >using the following two lines in my app: > >theField = (CField *) new_by_name ("CWordField"); >theField = (CField *) new(CWordField); > >The first line trashes most of the local variables in my function if the >optimizer is on, and most of the instance variables in my object if the global >optimizer is turned off. The second line works without a hitch. I've tried >everything I can think of, including recompiling and removing >objects on my entire project. I suppose I can try recompiling oopsDebug++, or >using oops++ instead... According to release notes I received with my copy of Classy (an object library and view editor from Object Factory Incorporated): The Symantec C++ oops libraries have two serious bugs [...] File cp_new_by_name.c The third from the last line of the new_by_name() function, which reads: addq/l #4, sp must be changed to: addq.l #8, sp This change properly restores the stack pointer before returning. [And a bad stack pointer could certainly explain your trashed locals.] File cp_new_i.c In __nw__12PascalObjectFPvUi(), the line: _NewHandle must be changed to: _NewHandleClear This makes new_by_name clear a handle before using it as an object. Exclaimer: I did not test these *before* installing the patches, so I cannot say for certain they were broke:-) _NewHandleClear will never hurt anything, but I just took it on faith that the sp was messed up, I didn't count. I have no relation to Object Factory or to Symantec. ============================================================================ From: Joseph Hall (jnhall@sat.mot.com) ---------------------------------------------------------------------------- (19) Elaborated class name in template expansion confuses compiler ============================================================================ ---------- template class foo { T x; void f(); }; template void foo::f() { } foo a; ---------- gives: size of T is not known But: ---------- ... struct bar { int x; }; ... foo b; ---------- is OK, as is simply: ---------- template class foo { T x; }; foo a; ---------- ============================================================================ From: Joseph Hall (jnhall@sat.mot.com) ---------------------------------------------------------------------------- (20) C++ compiler accepts static constructor ============================================================================ This compiles without error: ---------- class bletch { static bletch(); }; ---------- ============================================================================ From: Joseph Hall (jnhall@sat.mot.com) ---------------------------------------------------------------------------- (21) Filenames reported in template error messages can be incorrect ============================================================================ In some situations the filename (and/or line number?) in template error messages is incorrect. Using one of the foo.h/foo.cp/foo.cp instantation setups suggested in the Vector example, I've had errors in foo.cp reported with the filename foo.h. I wasn't able to reproduce this succinctly. ============================================================================ From: Joseph Hall (jnhall@sat.mot.com) ---------------------------------------------------------------------------- (22) Constructors can be defined to return int ============================================================================ This compiles without error: ---------- class xyzzy { xyzzy(); }; int xyzzy() { return 0; } ---------- ============================================================================ From: werner@soe.berkeley.edu ---------------------------------------------------------------------------- (23) Problem w/ templates and __pasobj ============================================================================ The following code won't compile under Symantec C++: class __pasobj Pclass { public: int x; }; template int GetX (T *aT) { return aT->x; } static void test() { Pclass *p = new Pclass; int xp = GetX(p); } Removing the __pasobj keyword from the Pclass declaration fixes the problem. It's apparently getting confused about Pascal vs non-Pascal classes. I tried a couple of workarounds: template int GetX (T *aT) and template int GetX (class __pasobj T *aT) The first gives assorted syntax errors followed by Error: internal error: file template.c line 1056 The second gives the error Error: template-argument 'T' not used in function parameter types followed by the same internal error as the first one. ============================================================================ From: ??? ---------------------------------------------------------------------------- (24) Bug in MacTraps glue causes problems w/ Smart Linking ============================================================================ In article <1v3a4m$bbs@bigboote.WPI.EDU> markt@wpi.WPI.EDU (Mark Robert Tsombakos) writes: >I found what seems like a bug in Think C 6 (note not C++). I re-compiled a >program I had (that works fine compiled from V5). I ran it and it crashed, big >time - not even MacsBug. I played around a little and dumped out a link map >and it showed that the global variables, including Quickdraw globals, are >allocated at a POSITIVE offset from A5. Not I'm not an expert Mac programmer >but I'm pretty sure that this is wrong. Other programs I tried (link map >under v6) show a negative offset. The program doesn't even get past >InitWindows 'cause InitGraf stomps over a bunch of stuff. I tried re-building >the project from scratch, but no go. > >I seem to remember a similar problem (positive A5 offsets) a little while ago, >but I don't recall seeing an answer. HELP! If you're getting these crashes from a built application, then it is a known bug which originates in some of the MacTraps glue supplied by Apple, and it should be fixed in the next release. This bug shows up when you build an application using Smart Linking, so until a patch is available, you shouild build your apps with Smart Linking turned off (or just test your app while running in the environment). ============================================================================ From: blumenau@robotics.berkeley.edu (Trevor Blumenau) ---------------------------------------------------------------------------- (25) Assorted debugger complaints ============================================================================ In article <1v2v2n$b5c@agate.berkeley.edu> I wrote: > >I've had all sorts of weirdness in the debugger, like losing the last >character off of variable names, crashes de-referencing _valid_ pointers, >breakpoints that cause behavior to change, "internal error" messages, etc. > >I'm running on a Quadra 700. Turning off all inits didn't help. Add to that some really painful bugs: The first breakpoint encountered seems to always be ignored (although if the same breakpoint is encountered a second time, it will cause a break), and a recoverable "User break" somehow being enabled (albeit not consistently) at every page fault. ============================================================================ From: ??? ---------------------------------------------------------------------------- (26) Potential bug in new ============================================================================ // And here is another potential bug in SC++ 'new' #include #include //#define NEWBUG /* delete the comment to test the code */ #ifdef NEWBUG // When NEWBUG is defined SC++ issues the following error: // (assume code is in the file new bug.cp) // File Ònew bug.cpÓ; Line 13 // Error: empty declaration main( int argc, char ** argv) { float * f; f = new float; if ( !f ) { cout << "New 'f'failed!\n"; exit ( 1 ); } delete f; return (0); } #else // BUT--when NEWBUG in ndef'ed this code is compiled and with no // error!! // // W H Y ??? // class Floater { public: float * f; }; main( int argc, char ** argv) { Floater * f; f = new Floater; if ( !f ) { cout << "New 'f'failed!\n"; exit ( 1 ); } delete f; return (0); } #endif ============================================================================ From: ??? ---------------------------------------------------------------------------- (27) Far data woes ============================================================================ In article , werner@soe.berkeley.edu (John Werner) wrote: > > Has anyone gotten a TCL application to work with Far Data? I started > trying yesterday and have gotten nowhere. Every TCL app I build with Far > Data turned on (with or without Far Code) crashes soon after startup, > apparently somewhere in the PascalObject message dispatcher. The suggestions you had and those that others posted are close. After a lot of trying on this too and talking with Symantec, here are the official UNDOCUMENTED rules. All libraries must be compiled with the same option as the project you are using them in. So if you did what I did and just turned on Far Data, you'll have to make new versions of all of the libraries (ANSI++-FarData, oopsDebug++-FarData, etc...). The same goes for your precompiled headers. The problem you get with the standard oopsDebugFar++ and simlar libraries is that they were either created with both Far Data and Far Code -- not matching your project Far Data only. ============================================================================ From: Tom Emerson ---------------------------------------------------------------------------- (28) Prototype in FormatX2Str has changed ============================================================================ In article Michael Hecht, Michael_Hecht@mac.sas.com writes: >Under the new THINK C 6.0, I can't call the Script Manager routine >FormatX2Str the same way as before. The function prototype, from >, is > > pascal FormatStatus FormatX2Str(extended80 x, > const NumFormatString *myCanonical, > const NumberParts *partsTable,Str255 outString) > = {0x2F3C,0x8210,0xFFE8,0xA8B5}; > > >The problem is the extended80 parameter x. Before, I simply passed a >double as x: [deleted] This is definitely a side effect of the new prototype for FormatX2Str. If modify the prototype in to use an extended rather than an extended80 then your code works fine. Your solution works as well. I'll report this to QA. ============================================================================ From: pjl@king.att.com (Paul J. Lucas) ---------------------------------------------------------------------------- (29) The "bug in Lippman" (for all T, class C is a friend of Foo) ============================================================================ [Ed.: This is classically known as "the bug in Lippman." In fact, this is a feature found in cfront() that is not yet in the ARM. Lippman is a cfront author, but not an author of the ARM. ;-) ] The following insists that it wants a semicolon: why? This *is* legal C++: "for all T, class C is a friend of Foo." Examples can be found in Lippman, 2nd ed. template class C; class Foo { template friend class C; // line 4 }; /* File RHD:Desktop Folder:bugs.cS; Line 4 Error: ';' expected */ void main() { } ============================================================================ From: pjl@king.att.com (Paul J. Lucas) ---------------------------------------------------------------------------- (30) More troubles with elaborated class names ============================================================================ In the following, the commented-out line, by virtue of its being commented out, elicits the enclosed (erroneous) error. This violates the ARM, p.168: A name declaration takes effect _immediately_ after the identifier is seen. This is legal C++ code provided that B does not need the *definition* of C, which, in this case, it doesn't. Also, cfront (correctly) accepts this code. // ------------------------------------------------------------- template class B { Derived *d; // definition of Derived unnecessary }; // class C; // omission of this line is supposed to be legal class C : public B { }; // line 7 /* File RHD:Desktop Folder:Targ.c; Line 7 Error: template-argument 'Derived' must be a type-argument */ ============================================================================ From: pjl@king.att.com (Paul J. Lucas) ---------------------------------------------------------------------------- (31) 0 in comma-expression not converted to int* following return ============================================================================ On line 3, the 0 in the comma-expression should be able to be converted to int* with no difficulty; the fact that it's in a comma-expression is irrelevant. See ARM, section 5.18, p. 81. It correctly compiles "(0, 0)"; the bug manifests when the left expression invovles a function-call. int g() { return 1; } int* f() { return (g(), 0); } // line 3 void main() { f(); } /* File "HD:C++:bugs:comma.c"; Line 3 Error: cannot implicitly convert from:int to :<*>int */ ============================================================================ From: pjl@king.att.com (Paul J. Lucas) ---------------------------------------------------------------------------- (32) Can't take the address of a register variable -- NOT! ============================================================================ C++ *allows* the address of a register variable (unlike C); ARM, p. 97, bottom. Your compiler incorrectly refuses this code: void main() { register int i; int *p = &i; } /* File RHD:Desktop Folder:union.cS; Line 3 Error: can't take address of register, bit field, constant or string */ ============================================================================ From: pjl@king.att.com (Paul J. Lucas) ---------------------------------------------------------------------------- (33) Errors in THINK C User Manual ============================================================================ THINK C User Manual: p. 706, access specifier not allowed in union This descrption is just plain wrong. Access specifiers are not allowed only in anonymous unions; ARM p. 183. Ordinary unions may have private members. Anyway, your compiler also gets this wrong too. It accepts the following illegal code: static union { private: int i; } u; void main() { } p. 733, duplicate 'case' The error "case was already used" on p. 726 is what is reported, not this error. Also, "'default:' is already used" on p. 731 is what is reported instead of "duplicate 'default'" p. 749, illegal type for field This error description does not restrict itself to C for the struct S which *can* have a member- function. p. 769, no members defined In C++, memberless structures are allowed. p. 796, using operator++() (or--) ... The second paragraph is backwards: operator++() is prefix and operator++(int) is postfix; ARM, p. 338. ============================================================================ From: ggilley@mv.us.adobe.com (Greg Gilley) ---------------------------------------------------------------------------- (34) SC++ accepts return value in function w/ void return type ============================================================================ The following should give an error: void foo(); void bar() { return foo(); } ============================================================================ From: ggilley@mv.us.adobe.com (Greg Gilley) ---------------------------------------------------------------------------- (35) SC++ does not enforce const reference parameter ============================================================================ The following should report an error: class bar { protected: int y; public: bar() {} bar(int x) { y = x; } bar(const bar &b) { y = b.y; } friend bar operator-(const bar &, const bar &); }; void foo(const bar &x) { bar y, z; x = y - z; // can't modify x!!!! } ============================================================================ From: rjohnson@aic.lockheed.com (Ray Johnson) ---------------------------------------------------------------------------- (36) Problem w/ UNIX compatible header stat.h ============================================================================ In the global include file stat.h, there is a small typo. The second field in the data structure "struct stat", is named "st_ito", it should be "st_ino" which stands for inode number. The field is only used once in the libraries (as far as I could tell). It's used in the __stat function defined in unixio.c. The fix is to just correct the two typos. Symantic said they will correct the problem in the future. Be careful when using stat etc. for porting code. They are very far from being Posix complient. ( For example: should be , certain types defined in should be in a file named ) If this is important to you (as it is to us) please voice your concern to Symantic. ============================================================================ From: John Werner (werner@soe.berkeley.edu) ---------------------------------------------------------------------------- (37) Optimizer screws up code involving Boolean variables ============================================================================ Here's a bug I just found in the SC++ optimizer. I vaguely remember seeing one like this posted before, but I couldn't find it on our news server, so here it is (again?). The optimizer is screwing up some code involving Boolean variables. Here's the code. The two marked lines in the Track function are where the problem occurs. The rest is mostly filler to keep the optimizer from stripping things away. class __pasobj CBug { public: Boolean fDragging; Point fOldPoint; virtual void Track(Point start, Point next); }; short Distance(Point, Point); void DrawLine(Point, Point); void CBug::Track(Point start, Point next) { if (!EqualPt(start, next)) { Boolean wasDragging = fDragging; // THESE TWO LINES if (!fDragging && Distance(start, next) > 4) { // CAUSE THE PROBLEMS fDragging = true; } if (fDragging) { if (wasDragging) DrawLine(start, fOldPoint); DrawLine(start, next); fOldPoint = next; } } } The code generated for the first part of the function looks like this: CBug::Track: 00000000: 4E56 FFFC LINK A6,#$FFFC 00000004: 48E7 0830 MOVEM.L D4/A2/A3,-(A7) 00000008: 554F SUBQ.W #$2,A7 0000000A: 2F2E 0010 MOVE.L $0010(A6),-(A7) 0000000E: 2F2E 000C MOVE.L $000C(A6),-(A7) 00000012: A881 _EqualPt 00000014: 101F MOVE.B (A7)+,D0 00000016: 6662 BNE.S *+$0064 ; 0000007A 00000018: 246E 0008 MOVEA.L $0008(A6),A2 0000001C: 2052 MOVEA.L (A2),A0 0000001E: 1828 0002 MOVE.B $0002(A0),D4 ; <-- Is it a byte? 00000022: 3D44 FFFC MOVE.W D4,$FFFC(A6) ; <-- Or is it a word? 00000026: 4A2E FFFC TST.B $FFFC(A6) ; <-- Maybe it's a byte 0000002A: 661A BNE.S *+$001C ; 00000046 The "MOVE.W D4,$FFFC(A6)" is the problem, because only the low byte of D4 has been set; the high byte of the low word could be anything. So the code does something like this. ; D4 = XXXXXXXX (garbage) MOVE.B $0002(a0) D4 ; D4 = XXXXXX00 (assuming fDragging is false) MOVE.W D4, $FFFC(a6) ; FFFC(a6) contains XX00 because a word was moved TST.B $FFFC(a6) ; Tests the XX byte at FFFC(a6). Oops. ============================================================================ From: Michael Abramowicz ---------------------------------------------------------------------------- (38) Problem deactivating CPopupPanes (possibly ValidRects the wrong area) ============================================================================ I found the problem with TCL updating that I was having, and it was the fault not of me, but of an obscure change in the TCL from 1.1.2 to 1.1.3 that introduced a very subtle bug. Here's my letter to Symantec documenting the bug: [...] After debugging a problem with updating in my program for 40-50 hours, I was finally able to trace it to a bug in the TCL 1.1.3 CPopupPane class. It is likely to be very very unusual for this bug to actually affect a program, but it did affect mine. Here is the original code with the bug: void CPopupPane::Deactivate( void) { Rect tempRect; // TCL 1.1.3 BF inherited::Deactivate(); FrameToWindR( &aperture, &tempRect); /* Draw inactive control */ DrawAll(&tempRect); ValidRect(&tempRect); // Suppress update TCL 1.1.3 BF } /* CPopupPane::Deactivate */ The problem with this code is that the DrawAll method prepares the popup pane. So when ValidRect is called, tempRect is no longer in window coordinates! It's in frame coordinates. So the wrong portion of the window gets validated. The fix is simple; reverse the order of the calls: void CPopupPane::Deactivate( void) { Rect tempRect; // TCL 1.1.3 BF inherited::Deactivate(); FrameToWindR( &aperture, &tempRect); /* Draw inactive control */ ValidRect(&tempRect); // Suppress update TCL 1.1.3 BF DrawAll(&tempRect); } /* CPopupPane::Deactivate */ This seems to work fine. You might try other fixes, such as converting tempRect back to the frame coordinates. But this can get a little dangerous, as the aperture of a CPopupPane isn't necessarily set to the width of the pane to begin with; I think this has something to do with the fact that popup-pane's widths can be variable, although I haven't really investigated. So if you do opt for an alternate fix, be sure to check it on some code that actually gets nailed by this bug. For complex reasons, this bug will only turn up very rarely. In my program, for example, it will only turn up immediately after a document is printed and two or more dialog boxes are used by the chooser extension. Since most dialogs aren't printable, other programs probably haven't experienced this. It is, however, a bug, and I hope you will fix it to help others avoid the hell I just went through in trying to find it. ============================================================================ From: Michael G. Reed (Reed@ACM.Org) ---------------------------------------------------------------------------- (39) Incorrect code generated for unsigned char >= 0 ============================================================================ Not a bug. Deleted. ============================================================================ From: Greg Gilley (ggilley@mv.us.adobe.com) ---------------------------------------------------------------------------- (40) '.o' files don't get re-made using Make ============================================================================ If you use make to update a project, files which are '.o' don't end up in the list, so they don't get updated. Very annoying to have to manually compile each one to update them. ============================================================================ From: Rick Zaccone (zaccone@bucknell.edu) ---------------------------------------------------------------------------- (41) Surprise, surprise, 'comp' is reserved in SC++ ============================================================================ Here'a a problem that I spent a while chasing down. I hope this post saves someone some time. I've reduced the problem to the smallest example that produces the error. Create a file called test.cp and insert the following function: void test(void) { short comp; } This fails to compile with the following error message: File "test.cp"; Line 2 Error: empty declaration If I change the word "comp" to something else, the compiler is happy. Why should the compiler care about the word "comp"? [ANSWER: because comp is an undocumented reserved word in SC++. You will note that it is defined in Types.h for THINK C, but not SC++. -Ed.] ============================================================================ From: Phil Shapiro (phils@bedford.symantec.com) ---------------------------------------------------------------------------- (42) SC++ asm() doesn't work w/ relaxed ANSI ============================================================================ In article <22k7q5$dpf@charm.magnus.acs.ohio-state.edu> Jasna M Arezina, jarezina@magnus.acs.ohio-state.edu writes: >I recently upgrade to Symatic's C++ (hey, for $150, it's a good deal), and >while it works pretty good, I've had a devil of a time getting to compile >either of the following from C++ (they do compile with no problems under the C >compiler): > >void main() >{ > asm(0xA9FF); // bogus anything >} > >---or--- > >#include > > >The "READ ME" file on Disk #1 states that "assembly is minimally supported" for >C++, but that it "supports the asm statment" to "insert machine instructions" >into the object code. > >However, the compiler always blows up with "Error: function 'asm' has no >protoype"!!!! The C++ compiler doesn't accept the asm() statement when either of the ANSI conformance options are enabled. If you turn off the ANSI conformance checkbox, then the code will compile just fine. This is considered to be a bug, and will be addressed in a future release. (That is, asm() should be accepted when the "relaxed ANSI" option is selected.) >Does anyone have any help for this? The code compiles fine under C, but the C++ >port of it just won't compile the asm! Note that the THINK C inline asm and the C++ asm are very different. Even after you turn off ANSI conformance, you won't be able to compile your THINK C inline assembly in C++. Look at SetUpA4.h for some ideas to help you port your THINK C inline code to C++. ============================================================================ From: John Nagle (nagle@netcom.com) ---------------------------------------------------------------------------- (43) Use of MAXFLOAT is screwed because ... ============================================================================ Here's yet another THINK bug. The basic problem is that any use of "MAXFLOAT" (which is a macro in "values.h") produces the message "Second argument to function "nextfloat" does not match prototype". Explictly copying the relevant lines from the library include files involved produces the test case below. Apparently the compiler is unable to convert 0.0 to "extended". "Extended" is partly built in and partly defined in ""; note the line with the comment "<-- this line is magic", which comes from "". This is Think C 6.0, on a Mac IIci, under System 7.1. Example follows: /* Following lines are from "" */ typedef struct { short exp[1], man[4]; } extended80; typedef struct { short exp[2], man[4]; } extended96; typedef extended80 __extended; // <-- this line is magic typedef __extended extended; /* Following lines are from "" */ extended nextfloat(extended, extended); #define inf() __inf #define pi() __pi extern extended __inf, __pi; /* Following line is from "" */ #define MAXFLOAT nextfloat(inf(),0.0) /* Now we try to use MAXFLOAT. It doesn't work. */ main(argc,argv) int argc; char argv[]; { double S; S = MAXFLOAT; /* "Second argument to function "nextfloat" does not match prototype" */ } ============================================================================ From: Harry Erwin (erwin@trwacs.fp.trw.com) ---------------------------------------------------------------------------- (44) Linker merged two static arrays in separate source files. ============================================================================ I've sent this on to Phil Shapiro, but for those of you who are putting together a bug list for Symantec C++, here's a goofy one. I defined two static arrays in separate source files with different types but the same name. The linker merged them... This led to some very strange bugs in my program, since I had written it with the assumption that the static arrays were local to each source file in scope... ============================================================================ From: Chris Wysocki (wysocki@netcom.com) ---------------------------------------------------------------------------- (45) Bugs in CBartender::SetMenuBarState(), EqualMem(). ============================================================================ Here's a bug in the new CBartender::SetMenuBarState method that was introduced with TCL 1.1.3. The line: oldState |= ((**(entry->macMenu)).enableFlags & 1) << i; should read: oldState |= ((**(entry->macMenu)).enableFlags & 1) << n; since i is the index into the Bartender's menu array (which includes both menu bar and hierarchical menus), while n is the index of menu bar menus. The effect of this bug is that the menu bar state isn't properly restored after closing a modal dialog. Also, the EqualMem function in TCLUtilities.cp has some serious problems. In its current form, it contains at least four (yes, four) bugs in its sixteen lines of inline assembly. (Bonus points if you can find all of them.) It's probably easiest to just rewrite the function in C and avoid the 68k code altogether: pascal Boolean EqualMem(void *p1, void *p2, long n) { register char *cp1 = (char *)p1; register char *cp2 = (char *)p2; register long i = n; while (i--) { if (*cp1++ != *cp2++) return FALSE; } return TRUE; } The TCL itself doesn't call EqualMem anywhere, as far as I can tell, but nevertheless it's always nice to have code that actually does what it's supposed to do.... ============================================================================ From: ??? ---------------------------------------------------------------------------- (46) More PascalObject strangeness, maybe? ============================================================================ file X.cp: ---------------- #include "X.h" void B::foo3(void) { } void A::foo(int) { } ---------------- file X.h: ---------------- class B : PascalObject { void foo3(void); }; class A : public B { void foo(int); void foo(void); }; ---------------- works fine. but change the foo(void) to foo2(void) and A will not show up in the class browser any more. - 30 -