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 @@ -2586,11 +2586,24 @@ } } + // 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 parsing the type suffixes only if this 'ptr' is a + // function return. Otherwise, return success, implicitly rejecting other + // suffixes. + if (Lex.getKind() != lltok::lparen) + return false; } // parse the type suffixes. @@ -2608,8 +2621,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); diff --git a/llvm/test/Assembler/invalid-opaque-ptr-double-addrspace.ll b/llvm/test/Assembler/invalid-opaque-ptr-double-addrspace.ll new file mode 100644 --- /dev/null +++ b/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) 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 @@ -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 diff --git a/llvm/test/Other/force-opaque-ptrs.ll b/llvm/test/Other/force-opaque-ptrs.ll --- a/llvm/test/Other/force-opaque-ptrs.ll +++ b/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 +}