Ancient
view release on metacpan or search on metacpan
xt/c-compat.t view on Meta::CPAN
# C89: inline keyword without guard
'unguarded_inline' => {
pattern => qr/^\s*(?<!static\s)(?<!OBJECT_)inline\s+\w/m,
severity => 'warning',
message => 'Bare inline keyword may fail on C89 (use OBJECT_INLINE or static inline)',
},
# C89: // comments (C++ style) - may fail on strict C89
'cpp_style_comments' => {
pattern => qr{^\s*//(?![/*])}m, # // at start of line (not in string)
severity => 'info',
message => 'C++ style // comments may fail on strict C89 compilers',
only_in_c_files => 1,
},
# C89: Variable declarations after statements (mixed declarations)
# This is tricky to detect reliably, so we look for common patterns
'mixed_declarations' => {
pattern => qr/;\s*\n\s*(int|char|bool|SV|AV|HV|CV|GV|STRLEN|I32|U32|IV|UV|NV|Size_t)\s+\w+\s*[=;]/,
severity => 'info',
message => 'Variable declaration after statement may fail on C89',
only_in_c_files => 1,
skip_functions => 1, # Too many false positives
},
# C99: restrict keyword
'restrict_keyword' => {
pattern => qr/\brestrict\b/,
severity => 'info',
message => 'restrict keyword is C99+ only',
},
# C99: Variable-length arrays (disabled - too many false positives with array indexing)
# 'variable_length_array' => {
# pattern => qr/\[\s*[a-z_][a-z0-9_]*\s*\]\s*[;=]/i,
# severity => 'info',
# message => 'Variable-length arrays are C99+ only',
# only_in_c_files => 1,
# },
# === COMPILER-SPECIFIC ISSUES ===
# GCC/Clang __attribute__ without guard
'unguarded_attribute' => {
pattern => qr/__attribute__\s*\(\(/,
severity => 'info',
message => '__attribute__ is GCC/Clang specific - use PERL_UNUSED_DECL or guard',
skip_in_ppport => 1,
},
# GCC __builtin_ functions
'builtin_functions' => {
pattern => qr/__builtin_(?!expect)/, # __builtin_expect is commonly used
severity => 'info',
message => '__builtin_* functions are GCC specific',
},
# === PERL XS ISSUES ===
# NOTE: PERL_NO_GET_CONTEXT is a micro-optimization for threaded perls.
# Most XS code works fine without it. Only flag if explicitly requested.
# Disabled by default as it's too noisy.
# NOTE: PL_sv_undef, PL_sv_yes, PL_sv_no, etc. are standard Perl globals
# that are perfectly safe to use in XS code. They're thread-safe constants.
# Disabled as it creates too much noise for legitimate XS patterns.
# === MEMORY/SAFETY ISSUES ===
# sprintf without size limit (buffer overflow risk)
'unsafe_sprintf' => {
pattern => qr/\bsprintf\s*\(/,
severity => 'warning',
message => 'sprintf is unsafe - use snprintf or sv_catpvf for safety',
only_in_c_files => 1,
},
# strcpy without size limit
'unsafe_strcpy' => {
pattern => qr/\bstrcpy\s*\(/,
severity => 'warning',
message => 'strcpy is unsafe - use strncpy or Copy/Move macros',
only_in_c_files => 1,
},
# strcat without size limit
'unsafe_strcat' => {
pattern => qr/\bstrcat\s*\(/,
severity => 'warning',
message => 'strcat is unsafe - use strncat or sv_catpv',
only_in_c_files => 1,
},
# gets() - extremely unsafe
'unsafe_gets' => {
pattern => qr/\bgets\s*\(/,
severity => 'error',
message => 'gets() is extremely unsafe and removed in C11 - use fgets',
only_in_c_files => 1,
},
# === PORTABILITY ISSUES ===
# Assuming sizeof(int) or sizeof(pointer)
'hardcoded_sizes' => {
pattern => qr/\b(sizeof\s*\(\s*(int|long|void\s*\*)\s*\)\s*==\s*[48]|[48]\s*==\s*sizeof)/,
severity => 'warning',
message => 'Hardcoded type sizes are not portable across platforms',
},
# Platform-specific headers without guards
'unistd_without_guard' => {
pattern => qr/^#\s*include\s+<unistd\.h>/m,
severity => 'info',
message => '<unistd.h> is Unix-only - may need HAS_UNISTD guard',
negative_pattern => qr/#\s*if.*HAS_UNISTD|#\s*ifdef.*WIN32|#\s*ifndef.*_WIN32/,
},
# Windows-specific headers without guards
'windows_header_without_guard' => {
pattern => qr/^#\s*include\s+<windows\.h>/mi,
severity => 'info',
message => '<windows.h> is Windows-only - ensure proper guards',
negative_pattern => qr/#\s*if.*WIN32|#\s*ifdef.*_WIN32/,
},
( run in 0.528 second using v1.01-cache-2.11-cpan-f889d44b568 )