SAMPLE CODECHECK RULE FILE FOR A CORPORATE C++ STYLE GUIDELINE
/* xyzrule.cc
Copyright (c) 1996 by XYZ, Inc. All rights reserved.
==============================================================================
Purpose: Checks for compatibility with XYZ C++ standards.
Written: 1 December 1995.
Revised: 2 January 1996.
Format: Monospaced font with 4 spaces/tab.
==============================================================================
abstract:
These CodeCheck rules check for compatibility with the XYZ C++
Coding Rules. These rules are based on the document "XYZ C++
Guidelines".
These rules are applied to all headers that are included in double
quotes, e.g. #include "project.h". For proper use of these rules, be
sure to include system headers in angle brackets: #include <ctypes.h.
Warning Codes:
9111 Header filename is not in DOS 8.3 format.
9121 Class names must begin with "XYZxxx_
9131 Private member name must not begin in uppercase.
9131 Private member name must end with an underscore.
9211 Definition of class belongs in a header file.
9212 File needs a leading comment block.
9213 Header file should be wrapped in an #ifndef.
9213 is not the correct wrapper name for this file.
9214 Definition of function must NOT be in a header file.
9221 Public section must come first in class .
9222 Data member of class must be private.
9231 Function is too long to be inlined.
9232 Do NOT use inline within a class definition.
9251 Class needs a default constructor.
9251 Class needs a copy constructor.
9252 Class needs an operator=().
9253 Class has too many constructors (limit is 3).
9254 Class needs a destructor.
9255 Destructor for class must be virtual.
9261 Operator should not be a friend.
9261 Do NOT declare friend functions.
9261 Do NOT declare friend classes.
9271 Do NOT use virtual base classes.
9281 Declare using a typedef name, not a basic C type.
9282 Define typedef name in a base class.
9293 Define enum in a base class.
9311 Declare parameter to be a reference to .
9312 Operator should not return an object.
9314 Function should not return an object.
9315 Reference parameters must come first.
9316 Constant member functions should be avoided.
9317 Parameter should not be const.
9411 Use // comments, not oldstyle C comments.
9421 Declare as a const, not a macro.
9422 This enumeration needs an enum type name.
9431 Global constant should be a class member.
9441 Function needs an explicit return type.
==============================================================================
*/
#include <check.cch
#define DOT ('.') // period character
#define SLASH ('/') // forward slash character
#define BACKSLASH ('\\') // backslash character
#define COLON (':') // colon character
#define TILDE ('~') // tilde character
#define UNDERSCORE ('_') // underscore character
#define PUBLIC 0
#define PROTECTED 1
#define PRIVATE 2
int ch, j, k, okay, level,
is_constant, is_object,
lin_if_depth, // Holds latest value of pp_if_depth.
comment_needed, // True until a header file's comment-block is found.
define_needed, // True until a header file's wrapper macro is #defined.
public_needed, // True when a class definition begins.
one_liner_needed, // True when a function is explicitly inlined.
no_wrap_message, // True if a wrapper-needed message has NOT been given.
class_has_virtual_function,
destructor_is_virtual,
non_ref_parm_found, // True if a non-reference fcn parameter has been found.
detect_virtual_base,
bad_name, // True if the wrapper name is wrong.
length, ch1, ch2;
// ---------- Rule 1.1.1 ----------
if ( header_name() ) // A header is about to be opened
{
if ( pp_include <3 ) // Header filename is in double quotes
{
j = 0;
k = 0;
ch = header_name()[k++];
while ( ch != 0 )
{
ch = header_name()[k++];
if ( ch == DOT )
{
break; // beginning of extension found
}
else
{
j = k; // count characters before dot
}
if ( ch == BACKSLASH || ch == COLON )
{
j = 0; // DOS directory or disk marker
}
else if ( ch == SLASH || ch == TILDE )
{
j = 0; // Unix directory or disk marker
}
}
if ( j > 8 )
{
warn( 9111, "Header filename %s is not in DOS 8.3 format.",
header_name() );
}
else if ( ch == DOT )
{
j = 0;
ch = header_name()[k+j];
while ( ch != 0 )
{
j++;
ch = header_name()[k+j]; // count chars after dot.
}
if ( j 3 )
{
warn( 9111, "Header filename %s is not in DOS 8.3 format.",
header_name() );
}
}
}
}
// ---------- Rule 1.2.1 ----------
if ( tag_begin )
{
// Apply this rule to global classes only:
if ( tag_global && (tag_kind == CLASS_TAG) )
{
if ( ! prefix("XYZ") )
warn( 9121, "Class names must begin with \"XYZ_\"" );
else if ( strstr(tag_name(), "_") == 0 )
warn( 9121, "Use an underscore after the class name prefix." );
}
}
// ---------- Rule 1.3.1 ----------
if ( dcl_member == 3 )
{
if ( dcl_access == PRIVATE )
{
if ( dcl_variable )
{
if ( isupper(dcl_name()[0]) )
warn( 9131, "Private data member name %s must not begin in uppercase.",
dcl_name() );
if ( ! suffix("_") )
warn( 9131, "Private data member name %s must end with an underscore.",
dcl_name() );
}
else if ( dcl_function )
{
if ( isupper(dcl_name()[0]) )
warn( 9131, "Private function name %s must not begin in uppercase.",
dcl_name() );
if ( ! suffix("_") )
warn( 9131, "Private function name %s must end with an underscore.",
dcl_name() );
}
}
}
// ---------- Rule 2.1.1 ----------
if ( tag_begin )
{
if ( tag_global && (tag_kind == CLASS_TAG) )
{
if ( lin_source )
warn( 9211, "Definition of class %s belongs in a header file.",
tag_name() );
}
}
// ---------- Rules 2.1.2 ----------
if ( mod_begin )
{
comment_needed = FALSE;
}
if ( lin_end )
{
if ( lin_number == 1 )
{
if ( lin_is_comment )
{
comment_needed = FALSE;
}
else if ( lin_header )
{
comment_needed = TRUE;
}
}
if ( comment_needed )
{
if ( lin_is_comment )
{
comment_needed = FALSE;
}
else if ( lin_preprocessor )
{
warn( 9212, "File %s needs a leading comment block.",
file_name() );
comment_needed = FALSE;
}
else if ( lin_has_code )
{
warn( 9212, "File %s needs a leading comment block.",
file_name() );
comment_needed = FALSE;
}
}
}
// ---------- Rule 2.1.3 ----------
if ( pp_if_depth || pp_endif )
{
lin_if_depth = pp_if_depth;
}
if ( pp_include )
{
if ( lin_header )
{
if ( no_wrap_message )
{
warn( 9213, "Header file %s should be wrapped in an #ifndef.",
file_name() );
}
}
no_wrap_message = TRUE;
define_needed = TRUE;
}
if ( lin_dcl_count )
{
if ( lin_header && lin_if_depth == 0 )
{
if ( no_wrap_message )
{
warn( 9213, "Header file %s should be wrapped in an #ifndef.",
file_name() );
no_wrap_message = FALSE;
define_needed = FALSE;
}
}
}
if ( pp_macro )
{
if ( lin_header )
{
if ( no_wrap_message && lin_if_depth == 0 )
{
warn( 9213, "Header file %s should be wrapped in an #ifndef.",
file_name() );
no_wrap_message = FALSE;
define_needed = FALSE;
}
if ( define_needed && lin_if_depth == 1 )
{
bad_name = FALSE;
length = strlen( pp_name() );
k = 0;
while ( k 1 )
{
if ( one_liner_needed )
{
warn( 9231, "Function %s is too long to be inlined.",
fcn_name() );
}
}
// ---------- Rule 2.3.2 ----------
if ( dcl_inline )
{
if ( lin_within_class == 1 )
{
warn( 9232, "Do NOT use inline within a class definition. (%d)", lin_within_class );
}
}
// ---------- Rule 2.4.1 ----------
// *** This needs a new trigger in CodeCheck: dcl_override. ***
// ---------- Rules 2.5.1, 2.5.2, and 2.5.4 ----------
if ( tag_end )
{
if ( tag_global && (tag_kind == CLASS_TAG) )
{
if ( ! tag_has_default )
{
warn( 9251, "Class %s needs a default constructor.", class_name() );
}
if ( ! tag_has_copy )
{
warn( 9251, "Class %s needs a copy constructor.", class_name() );
}
if ( ! tag_has_assign )
{
warn( 9252, "Class %s needs an operator=(%s&).", class_name(),
class_name() );
}
}
}
// ---------- Rule 2.5.3 ----------
if ( tag_constructors 3 )
{
warn( 9253, "Class %s has too many constructors (limit = 3).",
class_name() );
}
// ---------- Rules 2.5.4 and 2.5.5 ----------
if ( tag_begin )
{
if ( tag_global && (tag_kind == CLASS_TAG) )
{
class_has_virtual_function = FALSE;
destructor_is_virtual = FALSE;
}
}
if ( dcl_function )
{
if ( dcl_virtual )
{
if ( dcl_base == DESTRUCTOR_TYPE )
{
destructor_is_virtual = TRUE;
}
else
{
class_has_virtual_function = TRUE;
}
}
}
if ( tag_end )
{
if ( tag_global && (tag_kind == CLASS_TAG) )
{
if ( tag_has_destr )
{
if ( class_has_virtual_function )
{
if ( ! destructor_is_virtual )
{
warn( 9255, "Destructor %s::~%s() must be virtual.",
class_name(), class_name() );
}
}
}
else
{
warn( 9254, "Class %s needs a destructor.", class_name() );
}
}
}
// ---------- Rules 2.6.1 and 2.6.2 ----------
if ( dcl_friend )
{
if ( dcl_function )
{
if ( prefix("operator") )
{
if ( strequiv(root(), "=") )
;
else if ( strequiv(root(), "+") )
;
else if ( strequiv(root(), "-") )
;
else if ( strequiv(root(), "*") )
;
else if ( strequiv(root(), "/") )
;
else if ( strequiv(root(), "%") )
;
else if ( strequiv(root(), "") )
;
else if ( strequiv(root(), "<<") )
;
else
warn( 9261, "%s should not be a friend.", dcl_name() );
}
else
warn( 9261, "Do NOT declare friend functions." );
}
else
{
warn( 9262, "Do NOT declare friend classes." );
}
}
// ---------- Rule 2.7.1 ----------
if ( keyword("class") )
{
detect_virtual_base = TRUE;
}
if ( keyword("virtual") )
{
if ( detect_virtual_base )
{
warn( 9271, "Do NOT use virtual base classes." );
}
}
if ( dcl_base == CLASS_TYPE )
{
detect_virtual_base = FALSE;
}
// ---------- Rule 2.8.1 ----------
if ( dcl_member )
{
if ( dcl_variable && dcl_base != DEFINED_TYPE )
{
warn( 9281, "Declare %s using a typedef name, not a basic C type.",
dcl_name() );
}
}
// ---------- Rule 2.8.2 ----------
if ( dcl_typedef )
{
if ( dcl_member == 0 )
{
warn( 9282, "Define typedef name %s in a base class.",
dcl_name() );
}
}
// ---------- Rule 2.9.1 ----------
// This rule is not currently enforceable with CodeCheck.
// ---------- Rule 2.9.2 ----------
// This rule is redundant (covered by 3.1.2).
// ---------- Rule 2.9.3 ----------
if ( tag_kind == ENUM_TAG )
{
if ( tag_global )
{
warn( 9293, "Define enum %s in a base class.", tag_name() );
}
}
// ---------- Rule 3.1.1 ----------
if ( dcl_parameter )
{
is_object = ((dcl_base == CLASS_TYPE) || (dcl_base == STRUCT_TYPE));
if ( is_object )
{
if ( (dcl_levels == 0) || ((dcl_levels == 1) && (dcl_level(0) == POINTER)) )
{
if ( dcl_axyztract )
{
warn( 9311, "Declare parameter #%d to be a reference to %s.",
dcl_parameter, dcl_base_name() );
}
else
{
warn( 9311, "Declare parameter %s to be a reference to %s",
dcl_name(), dcl_base_name() );
}
}
}
}
// ---------- Rules 3.1.2 and 3.1.4 ----------
if ( dcl_function )
{
is_object = ((dcl_base == CLASS_TYPE) || (dcl_base == STRUCT_TYPE));
if ( dcl_member && is_object )
{
if ( (dcl_levels == 1) || ((dcl_levels == 2) && (dcl_level(1) == REFERENCE)) )
{
if ( prefix("operator") )
{
if ( strequiv(root(), "=") )
;
else if ( strequiv(root(), "+") )
;
else if ( strequiv(root(), "-") )
;
else if ( strequiv(root(), "*") )
;
else if ( strequiv(root(), "/") )
;
else if ( strequiv(root(), "%") )
;
else if ( strequiv(root(), "") )
;
else if ( strequiv(root(), "<<") )
;
else
{
warn( 9312, "%s::%s() should not return an object.",
class_name(), dcl_name() );
}
}
else
{
warn( 9314, "Function %s::%s() should not return an object.",
class_name(), dcl_name() );
}
}
}
}
// ---------- Rule 3.1.3 ----------
// This rule cannot be enforced with this version of CodeCheck
// ---------- Rule 3.1.5 ----------
if ( dcl_parameter )
{
if ( dcl_parameter == 1 )
{
non_ref_parm_found = FALSE;
}
if ( dcl_level(0) == REFERENCE )
{
if ( non_ref_parm_found )
{
warn( 9315, "Reference parameters must come first." );
}
}
else // a non-reference fcn parameter has been found
{
non_ref_parm_found = TRUE;
}
}
// ---------- Rule 3.1.6 ----------
if ( dcl_function )
{
is_constant = (dcl_level_flags(0) & CONST_FLAG);
if ( dcl_member && is_constant )
{
warn( 9316, "Constant member functions should be avoided." );
}
}
// ---------- Rule 3.1.7 ----------
if ( dcl_parameter )
{
is_object = ((dcl_base == CLASS_TYPE) || (dcl_base == STRUCT_TYPE));
if ( is_object && (dcl_levels == 1) )
{
is_constant = (dcl_level_flags(1) & CONST_FLAG);
level = dcl_level( 0 );
if ( is_constant && ((level == POINTER) || (level == REFERENCE)) )
{
if ( dcl_axyztract )
{
warn( 9317, "Parameter #%d should not be const.",
dcl_parameter );
}
else
{
warn( 9317, "Parameter %s should not be const.", dcl_name() );
}
}
}
}
// ---------- Rule 4.1.1 ----------
if ( lex_c_comment )
{
warn( 9411, "Use /\/ comments, not \/\*...*\/ comments." );
}
// ---------- Rule 4.2.1 ----------
if ( pp_const )
{
if ( lin_header && ! define_needed )
{
warn( 9421, "Declare %s as a const, not a macro.", pp_name() );
}
}
// ---------- Rule 4.2.2 ----------
if ( tag_anonymous )
{
if ( tag_global && tag_kind == ENUM_TAG )
{
warn( 9422, "This enumeration needs an enum type name." );
}
}
// ---------- Rule 4.3.1 ----------
if ( dcl_variable )
{
is_constant = (dcl_level_flags(dcl_levels) & CONST_FLAG);
if ( dcl_global && is_constant )
{
warn( 9431, "Global constant %s should be a class member.",
dcl_name() );
}
}
// ---------- Rule 4.4.1 ----------
if ( dcl_no_specifier )
{
if ( dcl_function )
{
warn( 9441, "Function %s needs an explicit return type.",
dcl_name() );
}
}
// ---------- Rule 4.4.2 ----------
// This rule cannot be enforced with this version of CodeCheck.