diff options
-rw-r--r-- | lib/CodeGen/TargetInfo.cpp | 36 | ||||
-rw-r--r-- | test/CodeGen/arm-arguments.c | 27 |
2 files changed, 45 insertions, 18 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index bc512e7a27..92ff312425 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -1611,30 +1611,30 @@ static bool isIntegerLikeType(QualType Ty, i != e; ++i, ++idx) { const FieldDecl *FD = *i; - // Check if this field is at offset 0. - uint64_t Offset = Layout.getFieldOffset(idx); - if (Offset != 0) { - // Allow padding bit-fields, but only if they are all at the end of the - // structure (despite the wording above, this matches gcc). - if (FD->isBitField() && - !FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) { - for (; i != e; ++i) - if (!i->isBitField() || - i->getBitWidth()->EvaluateAsInt(Context).getZExtValue()) - return false; - - // All remaining fields are padding, allow this. - return true; - } + // Bit-fields are not addressable, we only need to verify they are "integer + // like". We still have to disallow a subsequent non-bitfield, for example: + // struct { int : 0; int x } + // is non-integer like according to gcc. + if (FD->isBitField()) { + if (!RD->isUnion()) + HadField = true; + + if (!isIntegerLikeType(FD->getType(), Context, VMContext)) + return false; - return false; + continue; } + // Check if this field is at offset 0. + if (Layout.getFieldOffset(idx) != 0) + return false; + if (!isIntegerLikeType(FD->getType(), Context, VMContext)) return false; - // Only allow at most one field in a structure. Again this doesn't match the - // wording above, but follows gcc. + // Only allow at most one field in a structure. This doesn't match the + // wording above, but follows gcc in situations with a field following an + // empty structure. if (!RD->isUnion()) { if (HadField) return false; diff --git a/test/CodeGen/arm-arguments.c b/test/CodeGen/arm-arguments.c index fb61b0f784..c97c97bc58 100644 --- a/test/CodeGen/arm-arguments.c +++ b/test/CodeGen/arm-arguments.c @@ -92,3 +92,30 @@ void f15(struct s7 a0) {} // APCS-GNU: define arm_apcscc void @f16() // AAPCS: define arm_aapcscc void @f16() void f16(struct s8 a0) {} + +// APCS-GNU: define arm_apcscc i32 @f17() +// AAPCS: define arm_aapcscc i32 @f17() +struct s17 { short f0 : 13; char f1 : 4; }; +struct s17 f17(void) {} + +// APCS-GNU: define arm_apcscc i32 @f18() +// AAPCS: define arm_aapcscc i32 @f18() +struct s18 { short f0; char f1 : 4; }; +struct s18 f18(void) {} + +// APCS-GNU: define arm_apcscc void @f19( +// APCS-GNU: struct.s19* noalias sret +// AAPCS: define arm_aapcscc i32 @f19() +struct s19 { int f0; struct s8 f1; }; +struct s19 f19(void) {} + +// APCS-GNU: define arm_apcscc void @f20( +// APCS-GNU: struct.s20* noalias sret +// AAPCS: define arm_aapcscc i32 @f20() +struct s20 { struct s8 f1; int f0; }; +struct s20 f20(void) {} + +// APCS-GNU: define arm_apcscc i32 @f21() +// AAPCS: define arm_aapcscc i32 @f21() +struct s21 { struct {} f1; int f0 : 4; }; +struct s21 f21(void) {} |