Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -2586,11 +2586,23 @@ } } + // Handle (explicit) opaque pointer types (not --force-opaque-pointers). + // + // Type ::= ptr ('addrspace' '(' uint32 ')')? if (Result->isOpaquePointerTy()) { unsigned AddrSpace; if (parseOptionalAddrSpace(AddrSpace)) return true; Result = PointerType::get(getContext(), AddrSpace); + + // Give a nice error for 'ptr*'. + if (Lex.getKind() == lltok::star) + return tokError("ptr* is invalid - use ptr instead"); + + // Fall through to type suffix logic if this 'ptr' is a function return. + // Otherwise return success. + if (Lex.getKind() != lltok::lparen) + return false; } // parse the type suffixes. @@ -2608,8 +2620,6 @@ 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-double-addrspace.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/invalid-opaque-ptr-double-addrspace.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: expected top-level entity +@g1 = external global ptr addrspace(3) addrspace(4) Index: llvm/test/Assembler/opaque-ptr.ll =================================================================== --- llvm/test/Assembler/opaque-ptr.ll +++ llvm/test/Assembler/opaque-ptr.ll @@ -4,6 +4,13 @@ ; CHECK: @global = external global ptr @global = external global ptr +; CHECK: @fptr1 = external global ptr ()* +; CHECK: @fptr2 = external global ptr () addrspace(1)* +; CHECK: @fptr3 = external global ptr () addrspace(1)* addrspace(2)* +@fptr1 = external global ptr ()* +@fptr2 = external global ptr () addrspace(1)* +@fptr3 = external global ptr () addrspace(1)* addrspace(2)* + ; CHECK: define ptr @f(ptr %a) { ; CHECK: %b = bitcast ptr %a to ptr ; CHECK: ret ptr %b Index: llvm/test/Other/force-opaque-ptrs.ll =================================================================== --- llvm/test/Other/force-opaque-ptrs.ll +++ llvm/test/Other/force-opaque-ptrs.ll @@ -32,3 +32,15 @@ @g.fwd = global i32 0 declare void @fn.fwd(i32) + +define void @f2(i32** %p) { +; CHECK-LABEL: define {{[^@]+}}@f2( +; CHECK-SAME: ptr {{%.*}}) { + unreachable +} + +define void @f3(i32 addrspace(1)* addrspace(2)* %p) { +; CHECK-LABEL: define {{[^@]+}}@f3( +; CHECK-SAME: ptr addrspace(2) {{%.*}}) { + unreachable +}