diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -933,13 +933,14 @@ const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { unsigned Values = 1 + unsigned(IdxList.size()); - if (!PointeeType) + if (!PointeeType) { PointeeType = cast(Ptr->getType()->getScalarType())->getElementType(); - else - assert( - PointeeType == - cast(Ptr->getType()->getScalarType())->getElementType()); + } else { + assert(cast(Ptr->getType()->getScalarType())->isOpaque() || + PointeeType == cast(Ptr->getType()->getScalarType()) + ->getElementType()); + } return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, NameStr, InsertBefore); } @@ -949,13 +950,14 @@ const Twine &NameStr, BasicBlock *InsertAtEnd) { unsigned Values = 1 + unsigned(IdxList.size()); - if (!PointeeType) + if (!PointeeType) { PointeeType = cast(Ptr->getType()->getScalarType())->getElementType(); - else - assert( - PointeeType == - cast(Ptr->getType()->getScalarType())->getElementType()); + } else { + assert(cast(Ptr->getType()->getScalarType())->isOpaque() || + PointeeType == cast(Ptr->getType()->getScalarType()) + ->getElementType()); + } return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, NameStr, InsertAtEnd); } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -7741,7 +7741,7 @@ if (!BasePointerType) return error(Loc, "base of getelementptr must be a pointer"); - if (Ty != BasePointerType->getElementType()) { + if (!BasePointerType->isOpaqueOrPointeeTypeMatches(Ty)) { return error( ExplicitTypeLoc, typeComparisonErrorMessage( diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -4168,7 +4168,8 @@ if (!Ty) { std::tie(FullTy, Ty) = getPointerElementTypes(FullBaseTy->getScalarType()); - } else if (Ty != getPointerElementFlatType(FullBaseTy->getScalarType())) + } else if (!cast(FullBaseTy->getScalarType()) + ->isOpaqueOrPointeeTypeMatches(Ty)) return error( "Explicit gep type does not match pointee type of pointer operand"); diff --git a/llvm/test/Assembler/opaque-ptr.ll b/llvm/test/Assembler/opaque-ptr.ll --- a/llvm/test/Assembler/opaque-ptr.ll +++ b/llvm/test/Assembler/opaque-ptr.ll @@ -40,3 +40,11 @@ store i32 %i, ptr %a ret void } + +; CHECK: define void @gep(ptr %a) +; CHECK: %b = getelementptr i8, ptr %a, i32 2 +; CHECK: ret void +define void @gep(ptr %a) { + %b = getelementptr i8, ptr %a, i32 2 + ret void +}