diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-02-19 22:24:01 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-02-19 22:24:01 +0000 |
commit | 1c8560d93ef3ae8d4fded9d355b27d53f5b04e8c (patch) | |
tree | 6bc9fc5d425fd3896ec20668b220b42c57e836bb | |
parent | cf04aa1a024b8cbcf95593c06aaf62e8ce7ca6c0 (diff) | |
download | bcm5719-llvm-1c8560d93ef3ae8d4fded9d355b27d53f5b04e8c.tar.gz bcm5719-llvm-1c8560d93ef3ae8d4fded9d355b27d53f5b04e8c.zip |
Extend Evaluate() to fold (int) <pointer type>.
- PR3463, PR3398, <rdar://problem/6553401> crash on relocatable
symbol addresses as constants in static locals.
- There are many more scenarious we could handle (like arithmetic on
such an int) but this is the main use case.
llvm-svn: 65074
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 15 | ||||
-rw-r--r-- | clang/test/CodeGen/const-init.c | 28 |
2 files changed, 39 insertions, 4 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index cfe1a74f320..5e08e52a7ca 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -1057,7 +1057,7 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { if (!Result.isInt()) return false; - return Success(HandleIntToIntCast(DestType, SrcType, + return Success(HandleIntToIntCast(DestType, SrcType, Result.getInt(), Info.Ctx), E); } @@ -1067,10 +1067,17 @@ bool IntExprEvaluator::VisitCastExpr(CastExpr *E) { if (!EvaluatePointer(SubExpr, LV, Info)) return false; - if (LV.getLValueBase()) - return false; + if (LV.getLValueBase()) { + // Only allow based lvalue casts if they are lossless. + if (Info.Ctx.getTypeSize(DestType) != Info.Ctx.getTypeSize(SrcType)) + return false; + + Result = LV; + return true; + } - return Success(LV.getLValueOffset(), E); + APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset(), SrcType); + return Success(HandleIntToIntCast(DestType, SrcType, AsInt, Info.Ctx), E); } if (!SrcType->isRealFloatingType()) diff --git a/clang/test/CodeGen/const-init.c b/clang/test/CodeGen/const-init.c index c98cfd4ca22..957e3733e41 100644 --- a/clang/test/CodeGen/const-init.c +++ b/clang/test/CodeGen/const-init.c @@ -48,4 +48,32 @@ int g9 = (2 + 3i) * (5 + 7i) != (-11 + 29i); int g10 = (2.0 + 3.0i) * (5.0 + 7.0i) != (-11.0 + 29.0i); +// Global references +// RUN: grep '@g11.l0 = internal global i32 ptrtoint (i32 ()\* @g11 to i32)' %t && +long g11() { + static long l0 = (long) g11; + return l0; +} + +// RUN: grep '@g12 = global i32 ptrtoint (i8\* @g12_tmp to i32)' %t && +static char g12_tmp; +long g12 = (long) &g12_tmp; + +// RUN: grep '@g13 = global \[1 x .struct.g13_s0\] \[.struct.g13_s0 <{ i32 ptrtoint (i8\* @g12_tmp to i32) }>\]' %t && +struct g13_s0 { + long a; +}; +struct g13_s0 g13[] = { + { (long) &g12_tmp } +}; + +// RUN: grep '@g14 = global i8\* inttoptr (i64 100 to i8\*)' %t && +void *g14 = (void*) 100; + +// RUN: grep '@g15 = global i32 -1' %t && +int g15 = (int) (char) ((void*) 0 + 255); + +// RUN: grep '@g16 = global i64 4294967295' %t && +long long g16 = (long long) ((void*) 0xFFFFFFFF); + // RUN: true |