diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 7a0a4e1e824..783c32e6669 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -681,6 +681,7 @@ static Constant *SymbolicallyEvaluateGEP(ArrayRef Ops, // This makes it easy to determine if the getelementptr is "inbounds". // Also, this helps GlobalOpt do SROA on GlobalVariables. Type *Ty = Ptr->getType(); + assert(Ty->isPointerTy() && "Forming regular GEP of non-pointer type"); SmallVector NewIdxs; do { if (SequentialType *ATy = dyn_cast(Ty)) { @@ -711,10 +712,17 @@ static Constant *SymbolicallyEvaluateGEP(ArrayRef Ops, } Ty = ATy->getElementType(); } else if (StructType *STy = dyn_cast(Ty)) { - // Determine which field of the struct the offset points into. The - // getZExtValue is at least as safe as the StructLayout API because we - // know the offset is within the struct at this point. + // If we end up with an offset that isn't valid for this struct type, we + // can't re-form this GEP in a regular form, so bail out. The pointer + // operand likely went through casts that are necessary to make the GEP + // sensible. const StructLayout &SL = *TD->getStructLayout(STy); + if (Offset.uge(SL.getSizeInBytes())) + break; + + // Determine which field of the struct the offset points into. The + // getZExtValue is fine as we've already ensured that the offset is + // within the range representable by the StructLayout API. unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue()); NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Ty->getContext()), ElIdx)); diff --git a/test/Transforms/GlobalOpt/constantfold-initializers.ll b/test/Transforms/GlobalOpt/constantfold-initializers.ll index af8fa324db8..ce6e2c46d62 100644 --- a/test/Transforms/GlobalOpt/constantfold-initializers.ll +++ b/test/Transforms/GlobalOpt/constantfold-initializers.ll @@ -12,6 +12,11 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 @xs = global [2 x i32] zeroinitializer, align 4 ; CHECK: @xs = global [2 x i32] [i32 1, i32 1] +; PR12642 +%PR12642.struct = type { i8 } +@PR12642.s = global <{}> zeroinitializer, align 1 +@PR12642.p = constant %PR12642.struct* bitcast (i8* getelementptr (i8* bitcast (<{}>* @PR12642.s to i8*), i64 1) to %PR12642.struct*), align 8 + define internal void @test1() { entry: store i32 1, i32* getelementptr inbounds ([2 x i32]* @xs, i64 0, i64 0)