llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.96k stars 11.54k forks source link

C function erroneously labeled as variadic? #60421

Open PMunch opened 1 year ago

PMunch commented 1 year ago

Lifting this potential bug from https://github.com/PMunch/futhark/issues/44. In short Futhark is a tool which uses libclang in order to parse C headers into a format which can then be used to generate bindings for C in Nim. This approach seems to work very well, so this issue surprised me. Essentially with a file as simple as

#define own
own int* wasm_engine_new();

the is_function_variadic call on the node for the wasm_engine_new returns 1. The related code in the Futhark project is here: https://github.com/PMunch/futhark/blob/master/src/opir.nim#L111-#L117.

The JSON output the Opir helper tool generates for that file is:

[
  {
    "kind": "proc",
    "file": "/tmp/test/test.h",
    "position": {
      "column": 10,
      "line": 2
    },
    "name": "wasm_engine_new",
    "return": {
      "kind": "pointer",
      "depth": 1,
      "base": {
        "kind": "base",
        "value": "cint"
      }
    },
    "arguments": [],
    "callingConvention": "cdecl",
    "variadic": true,
    "inlined": false
  }
]

Not entirely sure whether this is a bug in Clang, some technically correct but confusing C thing, or improper usage of the translation unit system in libclang (still haven't been able to find any good source of documentation for it). But in the premier case I hope you will be able to resolve it, and otherwise I hope to get a push in the right direction on how to correct this on our end.

llvmbot commented 1 year ago

@llvm/issue-subscribers-clang-frontend

tbaederr commented 1 year ago

The implementation looks slightly fishy: https://github.com/llvm/llvm-project/blob/main/clang/tools/libclang/CXType.cpp#L649-L661

Why does it return 1 if the type is FunctionNoProtoType? But I'm not sure if that branch is even taken, I don't know much about bindings.

dwblaikie commented 1 year ago

this:

own int* wasm_engine_new();

is a function without a prototype, and can be called with any arguments (wasm_engine_new(32, "foo", 3.14)). A function that takes no arguments shoudl be prototyped like this:

own int* wasm_engine_new(void);