Day 251: GCC/Clang build report

Here are some issues that I observed when compiling with GCC and Clang. In order to keep Handmade Hero compiling on Linux and OS X with minimal effort I am looking for volunteers to bring these issues to Casey's attention during the stream.
I am not sure how the macro issues should be fixed, though.

There are a couple of issues with the TIMED_FUNCTION macro
GCC complains: “expected ')' before '__FUNCTION__'
#define TIMED_FUNCTION(...) TIMED_BLOCK_(DEBUG_NAME(__FUNCTION__), ## __VA_ARGS__)”


GCC expands the macro to
1
timed_block TimedBlock_("../cpp/code/handmade_asset.cpp" "|" "31" "|" "2" "|" __FUNCTION__);


Problem is that __FUNCTION__ is declared as a variable and cannot be concatenated with other string literals. I am not sure how to fix this in an elegant way, any ideas?

Clang has another complaint: “too few arguments provided to function-like macro invocation TIMED_FUNCTION();”

The TIMED_BLOCK_'s “Number” parameter is not set to a value. I guess we want to pass __COUNTER__ here as well
1
#define TIMED_FUNCTION(...) TIMED_BLOCK_(DEBUG_NAME(__FUNCTION__), __COUNTER__, ## __VA_ARGS__)


And now Clang is happy, but GCC is not: “expected primary-expression before ')' token #define TIMED_BLOCK__(GUID, Number, ...) timed_block TimedBlock_##Number(GUID, ## __VA_ARGS__)”

GCC now expands the macro to
1
timed_block TimedBlock_3("../cpp/code/handmade_asset.cpp" "|" "31" "|" "2" "|" "function",);


Note the trailing comma. Shouldn't “##” take care of this? I hate this macro nonsense :(

_snprintf_s is not supported and should be replaced
See https://hero.handmadedev.org/foru...y-211-gcc-clang-build-report#5277

Cast from void * to GLuint (and vice versa)
“cast from pointer to smaller type 'GLuint' (aka 'unsigned int') loses information”
and the warning “cast to 'void *' from smaller integer type 'GLuint' (aka 'unsigned int')”

We could use the PointerToU32 macro here and define new one for the other direction

/Kim
The only way I could get it to work was by manually joining the DEBUG_NAME string to the __FUNCTION__ string. (using gcc -std=gnu++11)

Is there any useful reason for gcc to define __FUNCTION__ as a variable rather than a macro? I can only see it as a poor choice.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
-#define TIMED_FUNCTION(...) TIMED_BLOCK_(DEBUG_NAME(__FUNCTION__), ##\
 __VA_ARGS__)
+
+// NOTE: brute force work around because gcc defines __FUNCTION__ as \
a
+// variable instead of just treating __FUNCTION__ as a macro style
+// string replace
+internal void
+JoinStrings(char *String1, char *String2, char *Result)
+{    
+    char *R = Result;
+    char *C = 0;
+    for(C = String1; *C != 0; ++C)
+    {
+        *R = *C;
+        ++R;
+    }
+    for(C = String2; *C != 0; ++C)
+    {
+        *R = *C;
+        ++R;
+    }
+    *R = 0;
+}
+#define TIMED_FUNCTION(...) char *DebugName = DEBUG_NAME(""); \
+    u32 DebugNameLength = StringLength(DebugName); \
+    char *FunctionName = (char *)__FUNCTION__; \
+    u32 FunctionNameLength = StringLength(FunctionName); \
+    char DebugFunctionName[DebugNameLength + FunctionNameLength + 1] \
= {}; \
+    JoinStrings(DebugName, FunctionName, DebugFunctionName); \
+    TIMED_BLOCK_(DebugFunctionName, __COUNTER__, ## __VA_ARGS__)
Does CLANG also define __FUNCTION__ as a variable, or is it only GCC?

- Casey
Clang does same thing as gcc - defines it as variable.
Kim, would you be so friendly and enlighten me a bit?
Linux platform Code is empty, what are you compiling at the moment?
I do crosscompile host:linux target:windows with mingw

Still missing half of the videos atm, so please have mercy with me ;)
people
Is there any useful reason for gcc to define __FUNCTION__ as a variable rather than a macro? I can only see it as a poor choice.

I agree. But it seems like the C99 committee found is more important that __func__ == __func__ would always hold.


Acry
Kim, would you be so friendly and enlighten me a bit?
Linux platform Code is empty, what are you compiling at the moment?

I'm using the SDL port of Handmade Hero (private repository).

/Kim
Looking at that c99 committee thread made me sad, I saw the thread was from 1999 and the issue still isn't fixed. Sadder still, is that string literal replacement for gcc was implemented in 1992, which was then replaced with the less useful variable replacement when it was standardized in c99. The rest of the thread consists of people showing why the "improved" version is worse, and committee members making excuses, covering their asses and explaining that they chose that way because, "Nobody mentioned this as a significant requirement at the point the proposal was being proposed, or during public comments.", implying that nobody on the committee was knowledgeable enough to know themselves.

It seems counter intuitive, you would think that a group of people coming together to standardize something would be a good thing, but it seems to be the opposite, consistently. I wonder the reason, is it that the type of people who are attracted to committees are just not very competent, or is there something about being part of a committee which makes a person less competent while interacting with that committee, or is there something about the very nature of this social structure which incentivises poor decision making, or is it just that committees are vulnerable to bullies taking over?

Maybe ranting is contagious :)
Now you know why "design by committee" is a slur.

One problem with language and API design committees is I think that they don't produce any real usage code. Or if they do they only produce 1 project and then refine just that.

This ends up optimizing the design for that single project.

Not to mention the people designing tend to get emotionally attached to their decisions and will actively try to stop any "pollution" of the design.
Hi,

For those who haven't got access to the git repository, I have an alternative suggestion that is currently working in my personal version of handmade hero. It allows use of __FUNCTION__ when compiling with either GCC or Clang (LLVM).

The idea is that at build time a preprocessor is run which locates all __FUNCTION__ variables and replaces them with an inline string of the function name.

Cheers
Jeremy
I think this is relevant. In this thread it's explained how I store profiled sections with hot code reloading and clang. https://hero.handmade.network/for...9-hot_code_reloading_and_profiler

// Just to connect infos through the forum.