codeql-coding-standards
codeql-coding-standards copied to clipboard
`DCL51-CPP`: Only reserve function names when used within the global namespace
Affected rules
-
DCL51-CPP
Description
The rule currently enforces that function names defined in standard library headers are not reused in any namespace. However, a careful re-reading of the C++ standard suggests that's overly specific. [reserved.names]
specifically states that the only kinds of name that are reserved are macros, "global names" and "names with external linkage". In [extern.names]
, the standard says:
Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
So only global function signatures are reserved, and only where they have external linkage. I think we need to do the following:
- Apply only to the global namespace
- Filter list of reserved function names by those that appear in the global namespace and have external linkage (this may already be the case).
- Match function signatures (I believe it is valid to reuse the name as long as the signature is different).
We may also need to review the rules for objects and _
prefixes.
Example
namespace MyNamespace {
void all_of(); // COMPLIANT
}
in your description above I think you meant to say "C++ standard suggests that's overly general" and not overly specific.
[extern.names] states:
1 # Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage,164 both in namespace std and in the global namespace. 2 # Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.165
so, for example, std::min
and ::min
are both reserved names
164) The list of such reserved names includes errno, declared or defined in cerrno. 165) The list of such reserved function signatures with external linkage includes setjmp(jmp_buf), declared or defined in csetjmp, and va_end(va_list), declared or defined in cstdarg. 166) The function signatures declared in cuchar, cwchar, and cwctype are always reserved, notwithstanding the restrictions imposed in subclause 4.5.1 of Amendment 1 to the C Standard for these headers.
struct ThisIsNotReserved {
void errno();
};
that member function is not a global name, nor does it have external linkage (IIRC), but it needs to be reserved.
"Match function signatures (I believe it is valid to reuse the name as long as the signature is different)."
No, it is not. Reserved means reserved.
Names are reserved for the implementation to steal the name to give it meaning or it's for the standard to steal the name to give it meaning, and the name might become a keyword or a macro instead of a regular identifier. Once you attack it from that angle, the rule makes more sense. It's basically saying "don't try to take names that aren't yours and use them in ways that may cause problems in the future"
Then, I think the rule boils down to:
Don't cause a name clash with a std::
function by using the same name, whatever signature that user-defined function bears, whatever scope that user-defined function lives in. Also, whether it's extern
or not do not matter.
@lcartey Could you confirm my understanding is correct?
One thing I'm not sure is if this only applies to functions. Should macros be covered then as well?