Clang (3.1 and 3.2): __attribute__((overloadable)) and enum types.

Hello,

I was trying to use attribute((overloadable)) for functions accepting enumerated types but hadn’t succeeded so far.

Clang 3.1 and 3.2 failed to compile the following example.

/* clang -x c foo.cpp */

typedef enum __One {DUMMY_1} One;

typedef enum {DUMMY_2} Two;

enum Three {DUMMY_3};

attribute((overloadable)) void foo(One);

attribute((overloadable)) void foo(Two);

attribute((overloadable)) void foo(enum Three);

int main()

{

foo(DUMMY_1);

return 0;

}

Providing me with the following error message:

$ clang -x c foo.cpp

foo.cpp:22:3: error: call to ‘foo’ is ambiguous

foo(DUMMY_1);

^~~

foo.cpp:16:36: note: candidate function

attribute((overloadable)) void foo(One);

^

foo.cpp:17:36: note: candidate function

attribute((overloadable)) void foo(Two);

^

foo.cpp:18:36: note: candidate function

attribute((overloadable)) void foo(enum Three);

^

1 error generated.

While with “-x c++” both versions of Clang compiled it successfully (failed to link though).

According to http://clang.llvm.org/docs/LanguageExtensions.html#function-overloading-in-c overloadable attribute is an analogue for C++ function overloading in C.

So, is it a bug in the Clang or I didn’t understand/consider something?

BR,

Andrey Lizunov

Since enums in C are just named integers, they are all of the same type. So it would be the same as doing three functions with int as the argument.

// bleh.cpp

#include

enum class One : int {DUMMY_1 = 1};
enum class Two : unsigned int {DUMMY_2 = 1};
enum class Three : char {DUMMY_3 = 1};

void foo(One)
{
std::cout << “One” << std::endl;
}
void foo(Two)
{
std::cout << “Two” << std::endl;
}
void foo(Three)
{
std::cout << “Three” << std::endl;
}

int main()
{
foo(One::DUMMY_1);
foo(Two::DUMMY_2);
foo(Three::DUMMY_3);
return 0;
}

//

$ clang++ -std=c++11 bleh.cpp -o bleh

$ ./bleh

One

Two

Three

Thank you for the answer,

So, it is not a bug but a standard behavior in C unlike of C++.

To make it work a variable of enum type should be defined.

$ cat try.c

#include <stdio.h>

typedef enum {ONE = 1} One;

typedef enum {TWO = 2} Two;

attribute((overloadable)) void foo(One arg){

printf(“One = %d\n”, arg);

}

attribute((overloadable)) void foo(Two arg){

printf(“Two = %d\n”, arg);

}

int main() {

One one = ONE;

Two two = TWO;

foo(one);

foo(two);

return 0;

}

bash-4.1$ clang -x c try.c; ./a.out

One = 1

Two = 2

BR,

Andrey Lizunov