Index: llvm/include/llvm/IR/Type.h =================================================================== --- llvm/include/llvm/IR/Type.h +++ llvm/include/llvm/IR/Type.h @@ -227,6 +227,9 @@ /// True if this is an instance of PointerType. bool isPointerTy() const { return getTypeID() == PointerTyID; } + /// True if this is an instance of PointerType that's opaque. + bool isOpaquePointerTy() const { return isPointerTy() && !NumContainedTys; } + /// Return true if this is a pointer type or a vector of pointer types. bool isPtrOrPtrVectorTy() const { return getScalarType()->isPointerTy(); } Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -2597,6 +2597,8 @@ return tokError("basic block pointers are invalid"); if (Result->isVoidTy()) return tokError("pointers to void are invalid - use i8* instead"); + if (Result->isOpaquePointerTy()) + return tokError("ptr* is invalid - use ptr instead"); if (!PointerType::isValidElementType(Result)) return tokError("pointer to this type is invalid"); Result = PointerType::getUnqual(Result); Index: llvm/test/Assembler/invalid-opaque-ptr-addrspace.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/invalid-opaque-ptr-addrspace.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: ptr* is invalid - use ptr instead +define void @f(ptr addrspace(3) %a) { + %b = bitcast ptr addrspace(3) %a to ptr addrspace(3)* + ret void +} Index: llvm/test/Assembler/invalid-opaque-ptr.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/invalid-opaque-ptr.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: ptr* is invalid - use ptr instead +define void @f(ptr %a) { + %b = bitcast ptr %a to ptr* + ret void +}