RW612 SDK - C++ header guards improperly placed

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RW612 SDK - C++ header guards improperly placed

Jump to solution
2,274 Views
dmarks_ls
Senior Contributor II

I just ran into an issue with the RW612 SDK for MCUXpresso (v2.16.1).  Currently using the MCUX IDE, but this also affects VS CODE.

TL;DR - When compiling a C API module for C++, the extern "C" { } declaration in the header file must surround ALL header file declarations, not just function declarations; otherwise, enum labels defined within structs will not appear in the global namespace as intended.

My issue... I'm writing a C++ driver for the RW612 FLEXCOMM UART, so naturally I'm calling the FSL driver API for the UART and the clock subsystem.  Here's my code snippet for attaching the FRG clock:

Source code, compile fails because of C++ namespace issueSource code, compile fails because of C++ namespace issue

But when I compile this, I get an error "'kCLOCK_FrgPllDiv' was not declared in this scope".  Well, that's strange, I can see the definition for kCLOCK_FrgPllDiv in fsl_clock.h.

Definition of kCLOCK_FrgPllDivDefinition of kCLOCK_FrgPllDiv

Then I realized... I wonder if this is a namespace thing.  Turns out, yes it is, because the extern "C" { } declaration is improperly placed.  It's only surrounding the C functions in fsl_clock.h; it is NOT surrounding any of the data type declarations in fsl_clock.h, including the definition of clock_frg_clk_config_t.

In C, all enum labels are in the global namespace, even if they are defined within a structure (such as here).  In C++, any data type or label defined within a struct, even a "weak" enum label, is scoped by the name of the struct and requires x::y syntax to use.  In order to get my code fragment above to compile correctly, I have to write:

"Fixed" code using struct type name::enum label"Fixed" code using struct type name::enum label

This is not correct behavior for a native C code module.  Moving the extern "C" opening declaration to near the start of the header file (say, line 18) will have no side effects for C code and in C++ will cause all enum labels to appear in the global namespace as intended, regardless of where they are defined.

fsl_clock.h is the only header file currently giving me this issue, but I can see in other FSL header files that the extern "C" { } block is similarly positioned (fsl_flexcomm.h, fsl_gdma.h, etc).  You need to fix all of these header files and update your coding standards documentation to prevent this specific issue occurring in the future.

Dana M.

Tags (2)
0 Kudos
Reply
1 Solution
2,002 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Dear @dmarks_ls ,

 

I got feedback from internal team, see below, please!

==========================================

We can reproduce issue now, it is related to enum definition in struct definition only, it is not related to common prototype defintion.

SW team will fix this issue in next release

==========================================

 

Thanks!

Regards,

weidong

View solution in original post

0 Kudos
Reply
5 Replies
2,153 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Dear @dmarks_ls ,

 

Internal team could not reproduce the issue you encountered , could you please share your project with us?

If yes, you can send it to me directly over email.

My email is : weidong.sun@nxp.com

 

Thanks!

Regards,

weidong

0 Kudos
Reply
2,141 Views
dmarks_ls
Senior Contributor II

Not sure why your engineers couldn't reproduce the issue.  Here is the code to demonstrate the issue:

 

/* This code tests whether the enum definitions in clock_frg_clk_config_t are
 * in the global C namespace (as they should be) or are scoped within the
 * struct (which is a C++-only behavior). */

#define DEMONSTRATE_COMPILER_FAILURE    1

#include <fsl_clock.h>

void CPP_TestScopedLabels(void) {
  clock_frg_clk_config_t frg_config;
#if DEMONSTRATE_COMPILER_FAILURE
  /* This would be correct code if this module was being compiled as a C
   * translation unit.  But when it is compiled as C++, the compiler throws
   * an error because kCLOCK_FrgPllDiv is not in the global namespace; it is
   * instead scoped by clock_frg_clk_config_t. */
  frg_config.sfg_clock_src=kCLOCK_FrgPllDiv;
#else
  /* This code qualifies the enum label with the type name of the struct.
   * This is not necessary in C because all enum are "weak" and all enum labels
   * appear in the global namespace, regardless of where they are defined. */
  frg_config.sfg_clock_src=clock_frg_clk_config_t::kCLOCK_FrgPllDiv;
#endif
  (void) frg_config;
}

 

I have included the source file as well.  (As an aside, your forum software does NOT accept files with a CPP extension, only C.  PLEASE FIX THIS.)

Dana M.

0 Kudos
Reply
2,003 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Dear @dmarks_ls ,

 

I got feedback from internal team, see below, please!

==========================================

We can reproduce issue now, it is related to enum definition in struct definition only, it is not related to common prototype defintion.

SW team will fix this issue in next release

==========================================

 

Thanks!

Regards,

weidong

0 Kudos
Reply
1,987 Views
dmarks_ls
Senior Contributor II

Thanks for getting back to me.  To be clear, the enum definition inside the struct is not the actual problem... the problem is the misplacement of C++ guards ("extern "C" { }) in this and many other SDK header files.  Please make sure you treat the root cause, not merely the symptom.  Thanks.

Dana M.

0 Kudos
Reply
2,252 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Dear @dmarks_ls ,

 

Thanks for your kindly feedback!

I will escalate it to internal team.

 

Regards,

weidong