#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 { '8.9 identifier with external linkage shall have exactly one external definition.' } sub description { '8.9 An identifier with external linkage shall have exactly one external definition.' } sub detailed_description { <<'END_DESC' Behaviour is undefined if an identifier is used for which multiple definitions exist (in different files) or no definition exists at all. Multiple definitions in different files are not permitted even if the definitions are the same, and it is obviously serious if they are different, or initialise the identifier to different values. To 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; }