#This script is designed to run with Understand - CodeCheck use base qw(Understand::Codecheck); use strict; use constant ERR1 => 'Violation: %2 "%1" (which has external linkage) defined multiple times.'; use constant ERR2 => 'Violation: %2 "%1" (which has external linkage) is not defined.'; sub register_tr_text { my $check = shift; $check->add_tr_text(ERR1); } sub name { '3-2-4 Is An identifier with external linkage shall have exactly one definition.' } sub description { '3-2-4 (Required) An identifier with external linkage shall have exactly one definition.' } sub detailed_description { <<'END_DESC'
Rationale
It is undefined behaviour if an identifier is used for which multiple definitions exist (in different
translation units) or no definition exists at all. With the exception of templates and inline functions,
multiple definitions in different translation units are not permitted, even if the definitions are the
same.
// file1.cpp int32_t i = 0; // file2.cpp int32_t i = 1; // Non-compliantTo ignore all overloads select the option below.
END_DESC } sub test_language { my $language = shift; return $language eq 'C++'; } sub test_entity { 0 } sub test_global { 1 } sub define_options { my $check = shift; $check->option->checkbox('overloads','Ignore Overloads',0); } sub check { my $check = shift; my %seen; my %notdefined; foreach my $file ($check->get_files) { return if $check->is_abort(); foreach my $ref ($file->filerefs("~implicit","global object ~static ~unknown, function ~static ~unknown" ,0)) { if($ref->kind->check("define")){ push(@{$seen{$ref->ent->longname}},$ref); $notdefined{$ref->ent->longname}=0; }else{ $notdefined{$ref->ent->longname}=$ref unless exists $notdefined{$ref->ent->longname}; } } } foreach my $refArray(keys %seen){ my @array = @{$seen{$refArray}}; my @violations; next unless @array > 1; if($check->option->lookup('overloads')){ foreach my $i (@array){ my $count = 0; foreach my $j (@array){ $count++ if $i->ent->parent && $j->ent->parent && $i->ent->parent->id == $j->ent->parent->id; } push(@violations, $i)unless $count > 1; } } else{ @violations = @array; } foreach my $ref (@violations){ $check->violation($ref->ent, $ref->file, $ref->line, $ref->column, ERR1, $ref->ent->longname, $ref->ent->kindname); } } foreach my $ref (values%notdefined){ next unless $ref; next if($ref->ent->name && $ref->ent->name eq "operator="); $check->violation($ref->ent, $ref->file, $ref->line, $ref->column, ERR2, $ref->ent->longname, $ref->ent->kindname); } return; }