Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -3613,7 +3613,12 @@ if (!E->getType()->isVariableArrayType()) { assert(isa(Addr.getElementType()) && "Expected pointer to array"); + + if (getLangOpts().isSignedOverflowDefined()) + llvm::setSignedWrap(true); + Addr = Builder.CreateConstArrayGEP(Addr, 0, "arraydecay"); + } // The result of this decay conversion points to an array element within the Index: clang/test/CodeGen/inbounds.c =================================================================== --- /dev/null +++ clang/test/CodeGen/inbounds.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fwrapv -emit-llvm -o - %s | FileCheck %s + +extern char base[]; + +char *test() { + return base + 1; +} + +// CHECK: ret ptr getelementptr (i8, ptr @base, i64 1) Index: llvm/include/llvm/IR/ConstantFold.h =================================================================== --- llvm/include/llvm/IR/ConstantFold.h +++ llvm/include/llvm/IR/ConstantFold.h @@ -26,10 +26,15 @@ namespace llvm { template class ArrayRef; + inline bool SignedWrap = false; + class Value; class Constant; class Type; + bool getSignedWrap(void); + void setSignedWrap(bool Wrap); + // Constant fold various types of instruction... Constant *ConstantFoldCastInstruction( unsigned opcode, ///< The opcode of the cast Index: llvm/lib/IR/ConstantFold.cpp =================================================================== --- llvm/lib/IR/ConstantFold.cpp +++ llvm/lib/IR/ConstantFold.cpp @@ -347,6 +347,14 @@ } } +bool llvm::getSignedWrap() { + return llvm::SignedWrap; +} + +void llvm::setSignedWrap(bool SignedWrap) { + llvm::SignedWrap=SignedWrap; +} + Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, Type *DestTy) { if (isa(V)) Index: llvm/lib/IR/Constants.cpp =================================================================== --- llvm/lib/IR/Constants.cpp +++ llvm/lib/IR/Constants.cpp @@ -2510,7 +2510,9 @@ ArgVec.push_back(Idx); } - unsigned SubClassOptionalData = InBounds ? GEPOperator::IsInBounds : 0; + unsigned SubClassOptionalData = ( InBounds && !llvm::getSignedWrap() ) ? + GEPOperator::IsInBounds : 0; + if (InRangeIndex && *InRangeIndex < 63) SubClassOptionalData |= (*InRangeIndex + 1) << 1; const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,