[cfe-commits] r99042 - in /cfe/trunk: lib/AST/ExprConstant.cpp test/CodeGen/const-arithmetic.c

Daniel Dunbar daniel at zuster.org
Fri Mar 19 22:53:45 PDT 2010


Author: ddunbar
Date: Sat Mar 20 00:53:45 2010
New Revision: 99042

URL: http://llvm.org/viewvc/llvm-project?rev=99042&view=rev
Log:
Evaluate: Fix a subtle bug in the pointer evaluator in which we would do an
expression computation in the wrong bit-width, and end up generating a totally
bogus array reference (_g0+8589934546).
 - This showed up on Prolangs/cdecl.

Added:
    cfe/trunk/test/CodeGen/const-arithmetic.c
Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=99042&r1=99041&r2=99042&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sat Mar 20 00:53:45 2010
@@ -406,27 +406,34 @@
   if (!EvaluatePointer(PExp, ResultLValue, Info))
     return APValue();
 
-  llvm::APSInt AdditionalOffset(32);
+  llvm::APSInt AdditionalOffset;
   if (!EvaluateInteger(IExp, AdditionalOffset, Info))
     return APValue();
 
-  QualType PointeeType = PExp->getType()->getAs<PointerType>()->getPointeeType();
-  CharUnits SizeOfPointee;
+  // Compute the new offset in the appropriate width.
+
+  QualType PointeeType =
+    PExp->getType()->getAs<PointerType>()->getPointeeType();
+  llvm::APSInt SizeOfPointee(AdditionalOffset);
 
   // Explicitly handle GNU void* and function pointer arithmetic extensions.
   if (PointeeType->isVoidType() || PointeeType->isFunctionType())
-    SizeOfPointee = CharUnits::One();
+    SizeOfPointee = 1;
   else
-    SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
-
-  CharUnits Offset = ResultLValue.getLValueOffset();
+    SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType).getQuantity();
 
+  llvm::APSInt Offset(AdditionalOffset);
+  Offset = ResultLValue.getLValueOffset().getQuantity();
   if (E->getOpcode() == BinaryOperator::Add)
-    Offset += AdditionalOffset.getLimitedValue() * SizeOfPointee;
+    Offset += AdditionalOffset * SizeOfPointee;
   else
-    Offset -= AdditionalOffset.getLimitedValue() * SizeOfPointee;
+    Offset -= AdditionalOffset * SizeOfPointee;
 
-  return APValue(ResultLValue.getLValueBase(), Offset);
+  // Sign extend prior to converting back to a char unit.
+  if (Offset.getBitWidth() < 64)
+    Offset.extend(64);
+  return APValue(ResultLValue.getLValueBase(),
+                 CharUnits::fromQuantity(Offset.getLimitedValue()));
 }
 
 APValue PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {

Added: cfe/trunk/test/CodeGen/const-arithmetic.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/const-arithmetic.c?rev=99042&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/const-arithmetic.c (added)
+++ cfe/trunk/test/CodeGen/const-arithmetic.c Sat Mar 20 00:53:45 2010
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: @g1 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 8 ; <[2 x i8*]*> [#uses=0]
+// CHECK: @g2 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 8 ; <[2 x i8*]*> [#uses=0]
+
+extern struct { unsigned char a, b; } g0[];
+void *g1[] = {g0 + -1, g0 + -23 };
+void *g2[] = {g0 - 1, g0 - 23 };





More information about the cfe-commits mailing list