LLVM variadic parameters - llvm

When I compile a c file to LLVM-IR which uses the printf function, I get a function declaration line, which looks as follows:
declare i32 #printf(i8* nocapture readonly, ...) local_unnamed_addr #2
I now wonder how LLVM translates the variadic parameter? Doesn't the printf(char *, ...) refer to a macro in the standard library?
Also how can I make such a declaration in the LLVM library?

Related

Will compiler ignore inline qualifier for my function?

I read that having more than a line in a function will falsify "inline", if so how do i get to know when my function is inlined and vice-versa :/
inline int foo(int x, int y)
{
cout<<"foo-boo";
return (x > y)? x : y;
}
Remember, inlining is only a request to the compiler, not a command. Compiler can ignore the request for inlining. Compiler may not perform inlining in such circumstances like:
If a function contains a loop. (for, while, do-while)
If a function contains static variables.
If a function is recursive.
If a function return type is other than void, and the return statement doesn’t exist in function body.
If a function contains switch or goto statement.
inline is in no way related to the number of lines in a function1. It is just a compiler hint, which the compiler is not, by any means, obliged to follow. Whether a function is really inlined when declared inline, is implementation-defined.
From C++14 standard draft N3690, §7.1.2:
A function declaration (8.3.5, 9.3, 11.3) with an inline specifier
declares an inline function. The inline specifier indicates to the
implementation that inline substitution of the function body at the
point of call is to be preferred to the usual function call mechanism.
An implementation is not required to perform this inline substitution at the point of call [...]
(Formatting mine.)
There are compiler-specific options and attributes to enable/disable inlining for all functions and do other, related stuff. Look up your compiler's documentation for further information.
1 A compiler could take the line count of a function into account when deciding on whether to inline a function or not but that's implementation-defined and not required by the standard.

Forbids functions with `static_assert`

I want to prevent certain functions from being called. Let's ignore the case of calling the function via a function pointer or something, and just concentrate on the case of direct function call. I can do this with = delete. However, the diagnostic issued is not quite informative. I considered using static_assert, with which you can supply a custom diagnostic message. I placed a static_assert(false, ...) statement within the function body, hoping that it fires when the function is called. However, it turns out that the static_assert fails even if the function is not called. Any suggestions?
Additional Note: The function is forbidden unconditionally. So, std::enable_if does not apply here. The motivation for such a function is that I want to prevent certain use, which would otherwise compile fine with overload resolution. So I can't just remove the function. deprecated is not what I want. I want a compilation error, not a warning.
I agree with others that you shouldn't use static_assert for this at all and mark the function as deprecated instead.
static_assertions fire at the time they are compiled. For an ordinary function, this is the time it is parsed, not the time it is called. For a template, however, it is the time of instantiation. So you can make your function a template like this.
template <typename...>
struct always_false { static constexpr bool value = false; };
template <typename... Ts>
void
never_call_me(Ts&&...)
{
static_assert(always_false<Ts...>::value,
"You should have never called this function!");
}
If typename... is not right for you (because the function is overloaded), try narrowing it down to only match what you want to make an error.
The trick used here is that always_false<Ts...>::value depends on the type parameters Ts... so it cannot be evaluated until the template is instantiated. (Even though we can clearly see that it will always be false.)
If it is a member function then = delete is your best (most portable) bet. Otherwise, both GCC and MSVC have support for marking a function as "deprecated", which will cause the compiler to issue a warning when the function is called.
From C++ mark as deprecated:
#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif
Usage:
DEPRECATED(void badidea(int a, const char* b));
.... and now with C++ 14, we can write it as:
#define DEPRECATED(func, reason) [[deprecated(reason)]] func
With usage:
DEPRECATED( void badidea(int a, const char* b), "This function was a bad idea");
As a shorter version of #5gon12eder's good answer, you can simply use
template<typename ... Ts>
void never_call_me(Ts&&...ts)
{
static_assert(not (std::is_same_v<Ts,Ts> && ...),
"You should have never called this function!");
}

Bulky macro definition overload

I want to define macro like
#define DECLARE_FUNCTION(funcName, retType, args) retType funcName(args)
And use it like
DECLARE_FUNCTION(intFunc, int, void);
DECLARE_FUNCTION(voidFunc, void, double, double);
DECLARE_FUNCTION(doubleFunc, double, int, double, double);
expecting that those will expand to
int intFunc(void);
void voidFunc(double, double);
double doubleFunc(int, double, double);
This is certainly not working, as macro defined with three arguments eats all the “redundant” arguments and result is
int intFunc(void);
void voidFunc(double);
double doubleFunc(int);
I don’t mind defining macros for different cases, like
DECLARE_FUNCTION_WITH_0_ARGS, DECLARE_FUNCTION_WITH_1_ARG, DECLARE_FUNCTION_WITH_2_ARGS, etc. But the problem is that these macros are not as primitive as I gave in the example, they contain a lot of lines of code, and it would be nice not to rewrite them, but to define only one nontrivial macro, e.q. DECLARE_FUNCTION_WITH_1_ARG, and call it from bodies of all other macros.
You can have a variable number of arguments in your macro. They can be accessed by using special symbols like __VA_ARGS__ inside the macro.
Here's the syntax in standard C.
#define DECLARE_FUNCTION(funcName, retType, ...) retType funcName(__VA_ARGS__)
The ... stands for all the dynamic arguments and is accessed by __VA_ARGS__. Note that you need at least one dynamic argument, otherwise you get a compiler error.
GNU C++ introduces extensions to prevent this from happening. So you can alternatively declare the above as:
#define DECLARE_FUNCTION(funcName, retType, ...) retType funcName(##__VA_ARGS__)
Here are some examples:
DECLARE_FUNCTION(func1, void) becomes void func1() (only with extensions).
DECLARE_FUNCTION(func2, int, int, char) becomes int func2(int, char)
This feature is called "variadic macros". You can read more here.

Possible ambiguity with extern "C", overloading, and function pointers

With normal functions, one can write
extern "C" int Frotz(int); // in a header
int Frotz(int x) { return x; }
With function pointers, however, this appears to have been implemented inconsistently between compilers.
extern "C" int Klutz(int (*)(int), int);
int Klutz(int (*fptr)(int), int x) { return (*fptr)(x); }
In the declaration, the argument is also extern "C". In the definition, most compilers appear to match these functions and make Klutz an extern "C" function. The Sun and Cray compilers, however, interpret these functions as being different, producing an overloaded int Klutz(int (*fptr)(int), int x), which later generates a link-time error.
Although Section 7.5.5 of C++98 and C++11 guarantees the interpretation of Frotz, I cannot tell if the standard is ambiguous about whether extern "C" matching should occur before or after checking for overloading.
Should Klutz above generate a mangled (C++) symbol or an extern "C" symbol?
EDIT 1
I could use a typedef to disambiguate the function pointer to have C or C++ ABI, but I'm interested in whether the code here (a) defines Klutz to have C++ linkage, (b) defines it to have C linkage, or (c) is ambiguous according to the standard, so that compilers are free to choose how to interpret it.
EDIT 2
This appears to be a known issue, at least by those compilers with searchable bug trackers. In my tests, GCC, Clang, Intel, MSVC, IBM XL, PathScale, PGI, and Open64 all fail to distinguish function types that are identical except for language linkage, as explicitly required by the standard (see section 7.5.1, quoted in the accepted answer). Fixing this would break a lot of existing code and require an ABI change. I'm not aware of any compiler that actually uses a different calling convention for C versus C++ language linkage.
GCC bug: "Finding reasons to ask for the removal of this feature from the next standard is kind of relevant ;-)" ... "And we may even decide on an official WONTFIX."
Clang bug: "I'm terrified of actually enforcing this rule, because doing it properly means making language linkage part of the canonical type, which is going to break a ton of code."
The C ABI and the C++ ABI are not guaranteed to be the same. So, an extern "C" function pointer is a different type from a C++ function pointer. You need something like this:
extern "C" {
typedef int (*KlutzFuncType)(int);
int Klutz (KlutzFuncType, int);
}
int Klutz (KlutzFuncType fptr, int x) { return (*fptr)(x); }
There is some discussion of this issue here.
I only have a copy of the draft. From 7.5p1:
Two function types with different language linkages are distinct types even if they are otherwise identical.
My reading of this is that the first parameter of your first Klutz has a different type than the first parameter of your second Klutz, and so your second Klutz should have C++ linkage.
There are C++ implementations that do not take language linkage into account for function types, despite what the standard says. In the following code snippet, KlutzCxxFuncType refers to a function with C++ linkage, while KlutzCFuncType refers to a function with C linkage.
typedef int (*KlutzCxxFuncType)(int);
extern "C" {
typedef int (*KlutzCFuncType)(int);
int Klutz (KlutzCFuncType, int);
}
int Klutz (KlutzCxxFuncType fptr, int x) { return (*fptr)(x); }
int Klutz (KlutzCFuncType fptr, int x) { return (*fptr)(x); }
A compiler that does not distinguish function types based on language linkage will generate a redefinition error on this code. For example, g++ 4.7.2 will emit:
prog.cpp: In function ‘int Klutz(KlutzCFuncType, int)’:
prog.cpp:9:5: error: redefinition of ‘int Klutz(KlutzCFuncType, int)’
prog.cpp:8:5: error: ‘int Klutz(KlutzCxxFuncType, int)’ previously defined here

Can a function with variable no. of arguments be overloaded in VC++?

I have an exported function in a dll(written in vc++) which has got variable no. of arguments. Now I want to overload this function without variable no. of arguments. Is there anything wrong with this concept? The reason I am concerned is because I have read that vc++ uses __cdecl calling convention for c and c++.
Sample signatures are given below.
void f(int i, char *fmt, ...);
void f(int i, string str);
It depends from where are you planning to call these functions.
They should be converted to names like f__FiPc?? and f__Fi6string.
C++ compiler will decode them and C compiler will miss the function f if you haven't declared extern "c". However it depends on the implementation of your compiler.