First Last Prev Next    No search results available
Details
: C front-end crash on empty structure
Bug#: 80
: tools
: llvm-gcc
Status: RESOLVED
Resolution: FIXED
: PC
: Linux
: 1.0
: P2
: normal
: 1.1

:
: compile-fail
:
:
  Show dependency tree - Show dependency graph
People
Reporter: Brian R. Gaeke <gaeke+bugs@uiuc.edu>
Assigned To: Chris Lattner <clattner@apple.com>

Attachments


Note

You need to log in before you can comment on or make changes to this bug.

Related actions


Description:   Opened: 2003-11-01 13:37
108 gally> llvm-gcc -c cracktacular.c
cracktacular.c: In function `foo':

cracktacular.c:3: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://llvm.cs.uiuc.edu> for instructions.
109 gally> cat cracktacular.c
typedef struct { } the_coolest_struct_in_the_world;
extern the_coolest_struct_in_the_world xyzzy;
void *foo() { return &xyzzy; }


The unfortunate thing is that regular old gcc accepts this code, and I think it
should be giving us a parse error. In ISO9899 6.2.5 (20), it says that
"A structure type describes a sequentially allocated *nonempty* set of member
objects..." (emphasis mine).
------- Comment #1 From Brian R. Gaeke 2003-11-01 14:12:41 -------
Another crashing testcase involving an empty struct:

247 gally> cat arf4.i
typedef struct { } rwlock_t;
struct fs_struct { rwlock_t lock; int umask; };
void __copy_fs_struct(struct fs_struct *fs) { fs->lock = (rwlock_t) { }; }

I expect that this is a very closely-related problem.   Note that if you take
out `umask' from fs_struct, the crash stops happening.
------- Comment #2 From Brian R. Gaeke 2003-11-01 14:38:39 -------
I should perhaps point out that the reason we are interested in these empty
structs is that the linux kernel sources assume that empty structs are OK.
------- Comment #3 From Brian R. Gaeke 2003-11-01 15:34:02 -------
The "critical" status was just us kidding around. :-)
------- Comment #4 From Chris Lattner 2003-11-01 17:49:24 -------
Fixed.  Testcase: test/Regression/CFrontend/2003-11-01-EmptyStructCrash.c

Thanks!

-Chris
------- Comment #5 From Misha Brukman 2003-11-04 12:47:53 -------
I can reproduce it as of Nov 4, 2003, so the bug is not fixed.
------- Comment #6 From Misha Brukman 2003-11-04 12:51:34 -------
So the confusion stems from the fact that Chris only fixed the first but not the
second test case. I managed to narrow my large test case to an exact replica of
Brian's post.
------- Comment #7 From Chris Lattner 2003-11-04 12:55:46 -------
Ah, roit.  The second, even uglier test is now
llvm/test/Regression/CFrontend/2003-11-04-EmptyStruct.c

-Chris
------- Comment #8 From Chris Lattner 2003-11-04 13:52:39 -------
This is now (re)fixed.  Here's a CFE patch:

$ diff -u llvm-types.c~ llvm-types.c
--- llvm-types.c~       2003-11-02 17:08:38.000000000 -0600
+++ llvm-types.c        2003-11-04 13:25:46.000000000 -0600
@@ -672,7 +672,7 @@
     unsigned ElSize = GetDeclSize(field);  /* In bits */
     int HasSignedField;
     unsigned StartByte;
-    if (BitAlignment > ElSize) ElSize = BitAlignment;
+    if (ElSize && BitAlignment > ElSize) ElSize = BitAlignment;
 
     HasSignedField = !TREE_UNSIGNED(TREE_TYPE(field));
 
@@ -1205,15 +1205,25 @@
     fprintf(stderr, "Setting field indexes to: { ");
 #endif
     
+    Idx = 0;
     for (; Field; Field = GetNextFieldDecl(Field)) {
       unsigned FieldByteOffset = GetFieldOffset(Field)/8;
-      for (Idx = 0; Idx+1 < Result->NumElements &&
-             ElementOffsets[Idx+1] <= FieldByteOffset; ++Idx)
+      for (; Idx+1 < Result->NumElements &&
+             ElementOffsets[Idx+1] <= FieldByteOffset &&
+             ElementOffsets[Idx] != FieldByteOffset; ++Idx)
         /*empty*/;
 #if DEBUG_STRUCT_LAYOUT
       fprintf(stderr, "%d, ", Idx);
 #endif
       SET_DECL_LLVM(Field, llvm_constant_new_integral(UByteTy, Idx));
+
+      /* If we just passed over a zero sized field, skip ahead to the next
+       * field, so we don't assign all consequtive zero sized elements to the
+       * same field.
+       */
+      if (Idx+1 < Result->NumElements &&
+          ElementOffsets[Idx+1] == ElementOffsets[Idx])
+        ++Idx;   /* Start looking at the next field */
     }
 
 #if DEBUG_STRUCT_LAYOUT

First Last Prev Next    No search results available