Sysprogs forums › Forums › VisualGDB › Support for inline functions in C mode of arm compiler
- This topic has 2 replies, 2 voices, and was last updated 6 years, 2 months ago by support.
-
AuthorPosts
-
August 26, 2018 at 13:24 #21775regus_pregusParticipant
Environment: VisualGDB 5.4 (preview 4, build 2394) with VS Community Edition 2017 (15.8.0)
Target: STM32F746NG (on STM32F746G-DISCOVERY board), but I guess it is reproducible on other targets
Problem summary: C code with inline function compiles but does not link
Steps to reproduce:
- Run VS with VisualGDB installed
- Create new project (File->New->Project->VisualGBB->Embedded Project Wizard)
- Project type page: Create a new project with = MSBuild, Language standard = C11, leave all other settings default
- Device selection page: STM32F746NG, leave all other settings default (Execute from = FLASH, Exclude the startup file from project = UNCHECK)
- Sample selection page: Basic samples tab, select LEDBlink (HAL) sample project, leave all other settings default
- Debug method page: Debug using = OpenOCD, JTAG/SWD programmer = ST-Link v2.1, leave all other settings default
- Locate LEDBlink.c file in source tree (Source files folder) and open it
- Locate main() function in LEDBlink.c file and insert any inline function before it, for example:
inline int test() {return 0;}
- Call that function in main() function:
test();
- Build the project (Build->Build solution)
You will see that the compiler will compile that code without any complaints (as it should), but the linker will abort with an error:
Linking ../VisualGDB/Debug/EmbeddedProject1…
VisualGDB/Debug/LEDBlink.o: In function ‘main’:
LEDBlink.c(20): error : undefined reference to ‘test’Discussion/observations:
- The problem does not appear if you specify C++ mode for the compiler when creating a project (step 2.a above), it only happens in straight-C modes.
- Playing with relevant compiler parameters (Properties->Configuration Properties->C/C++->Optimization->Inline Functions (Yes/No/blank) has no effect.
- Support for inline functions has been added to C standard since C99, so they should compile and link in both C99 and C11 modes.
- Properly working compiler should either inline a function or not inline it (“inline” is only a recommendation), but ARM compiler does it half-way in C mode: if you look at the assembly output, you will see that compiler first, as it should, does not generate a function body for the function that has been requested to be inline, but then it generates a regular, non-inline call to that function, which, of course, results in linker not being able to do its job.
Any ideas how to make the compiler behave according to the standard?
- This topic was modified 6 years, 2 months ago by regus_pregus.
August 26, 2018 at 18:04 #21779regus_pregusParticipantPlease disregard my post above, the described problem is not of VisualGDB, rather it is of GNU Embedded Toolchain for Arm included with the product. It is reproducible even with the latest version of gcc for Arm (7.3.1), not just 7.2.0 included with VisualGDB.
August 27, 2018 at 03:58 #21780supportKeymasterHi,
No worries. This is actually a known issue of gcc (e.g. see this discussion). Generally, though, we advise avoiding non-static inline functions, as they could cause hard-to-diagnose problems in large projects where multiple source files define different versions of an inline function with the same name.
E.g. if file1.cpp defines inline void memset32(void *, int, int numberOfWords) and file2.cpp defines inline void memset32(void *, int, int numberOfBytes), the debug build (with inlining disabled) may silently replace one of the implementations with another one, as both functions will get compiled as weak global symbols. Declaring inline functions as static limits them to the declaring translation unit, fully avoiding this issue and also resolving the problem you encountered.
-
AuthorPosts
- You must be logged in to reply to this topic.