#This script is designed to run with Understand - CodeCheck
#Robert Gempeler - 7/19/2010
use base ("Understand::Codecheck");
use strict;

use constant ERR1 => 'Violation: File contains invalid dynamic memory statement.';

sub register_tr_text() {
  my $check = shift;
  $check->add_tr_text(ERR1);
}

sub name { return "18-4-1 Dynamic heap memory allocation shall not be used.";}

sub description { return "18-4-1 (Required) Dynamic heap memory allocation shall not be used.";}

sub detailed_description { return <<"END_DESC"
<p><b>Rationale</b><br>
The use of dynamic memory can lead to out-of-storage run-time failures, which are undesirable.
The built-in new and delete operators, other than the placement versions, use dynamic heap 
memory. The functions calloc, malloc, realloc and free also use dynamic heap memory.
There is a range of unspecified, undefined and implementation-defined behaviour associated with 
dynamic memory allocation, as well as a number of other potential pitfalls. Dynamic heap memory 
allocation may lead to memory leaks, data inconsistency, memory exhaustion, non-deterministic 
behaviour, etc.</p>
<p>Note that some implementations may use dynamic heap memory allocation to implement other 
functions (for example, functions in the library cstring). If this is the case, then these functions 
shall also be avoided.</p>
<b>Example</b><pre style="margin-top:0;padding-top:0;">
  void f1 ( ) 
  { 
     int32_t * i = new int32_t;       // Non-compliant
     delete i; 
  }
</pre>
END_DESC
}

sub test_language {
  my $language = shift;
  return $language =~ /C\+\+/; #Handles C and C++
}

sub test_entity { return 1;}

sub test_global { return 0;}

sub define_options{}


sub check {
  my $check = shift; 
  my $file = shift; 
  return unless $file->kind->check("file"); 
  
  my @functionCallRefs = $file->filerefs("call","function",0);
  foreach my $funcCall (@functionCallRefs){
    if ($funcCall->ent->name =~ /^calloc$|^malloc$|^realloc$|^free$/){
      $check->violation($funcCall->ent(),$file,$funcCall->line(),$funcCall->column(),ERR1);
    }
  }
  
    my $lexer = $file->lexer();
    return unless $lexer;
    my $lexeme = $lexer->first;
  
  #check if lexeme text has the new or delete keyword
  while($lexeme) {
	  if ($lexeme->text() =~ /^new$|^delete$/  && $lexeme->token() eq "Keyword"){
		  $check->violation($lexeme->ent(),$file,$lexeme->line_begin(),$lexeme->column_begin(),ERR1);
	 }
   $lexeme=$lexeme->next;
  }
}