LCOV - code coverage report
Current view: top level - /mnt/build/buildbot/bld/build-lcov/gcc/m2/gm2-compiler-boot - M2Students.c (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.4 % 103 89
Test Date: 2026-02-28 14:20:25 Functions: 80.0 % 10 8
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* do not edit automatically generated by mc from M2Students.  */
       2              : /* M2Students.mod checks for new programmer errors.
       3              : 
       4              : Copyright (C) 2001-2026 Free Software Foundation, Inc.
       5              : Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
       6              : 
       7              : This file is part of GNU Modula-2.
       8              : 
       9              : GNU Modula-2 is free software; you can redistribute it and/or modify
      10              : it under the terms of the GNU General Public License as published by
      11              : the Free Software Foundation; either version 3, or (at your option)
      12              : any later version.
      13              : 
      14              : GNU Modula-2 is distributed in the hope that it will be useful, but
      15              : WITHOUT ANY WARRANTY; without even the implied warranty of
      16              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17              : General Public License for more details.
      18              : 
      19              : You should have received a copy of the GNU General Public License
      20              : along with GNU Modula-2; see the file COPYING3.  If not see
      21              : <http://www.gnu.org/licenses/>.  */
      22              : 
      23              : #include "config.h"
      24              : #include "system.h"
      25              : #include "gcc-consolidation.h"
      26              : 
      27              : #include <stdbool.h>
      28              : #   if !defined (PROC_D)
      29              : #      define PROC_D
      30              :        typedef void (*PROC_t) (void);
      31              :        typedef struct { PROC_t proc; } PROC;
      32              : #   endif
      33              : 
      34              : #   if !defined (TRUE)
      35              : #      define TRUE (1==1)
      36              : #   endif
      37              : 
      38              : #   if !defined (FALSE)
      39              : #      define FALSE (1==0)
      40              : #   endif
      41              : 
      42              : #define _M2Students_C
      43              : 
      44              : #include "GM2Students.h"
      45              : #   include "GSymbolTable.h"
      46              : #   include "GNameKey.h"
      47              : #   include "GM2MetaError.h"
      48              : #   include "GLists.h"
      49              : #   include "GM2Reserved.h"
      50              : #   include "GDynamicStrings.h"
      51              : #   include "GFormatStrings.h"
      52              : #   include "GM2LexBuf.h"
      53              : #   include "GASCII.h"
      54              : #   include "GM2Options.h"
      55              : 
      56              : static Lists_List ErrantNames;
      57              : static Lists_List ErrantSymbols;
      58              : 
      59              : /*
      60              :    CheckVariableAgainstKeyword - checks for a identifier that looks the same
      61              :                                  as a keyword except for its case.
      62              : */
      63              : 
      64              : extern "C" void M2Students_CheckVariableAgainstKeyword (unsigned int tok, NameKey_Name name);
      65              : 
      66              : /*
      67              :    StudentVariableCheck - checks to see that variables are quite different from keywords and
      68              :                           issues an message if they are not. It ignores case so to catch
      69              :                           1st and 2nd semester programming errors.
      70              : */
      71              : 
      72              : extern "C" void M2Students_StudentVariableCheck (void);
      73              : 
      74              : /*
      75              :    IsNotADuplicate - returns TRUE if either s1 or s2 have not been reported before.
      76              : */
      77              : 
      78              : static bool IsNotADuplicate (unsigned int s1, unsigned int s2);
      79              : 
      80              : /*
      81              :    IsNotADuplicateName - returns TRUE if name has not been reported before.
      82              : */
      83              : 
      84              : static bool IsNotADuplicateName (NameKey_Name name);
      85              : 
      86              : /*
      87              :    PerformVariableKeywordCheck - performs the check and constructs the metaerror notes if appropriate.
      88              : */
      89              : 
      90              : static void PerformVariableKeywordCheck (unsigned int tok, NameKey_Name name);
      91              : 
      92              : /*
      93              :    CheckAsciiName - checks to see whether ascii names, s1, and, s2, are similar.
      94              : */
      95              : 
      96              : static void CheckAsciiName (unsigned int previous, unsigned int s1, unsigned int newblock, unsigned int s2);
      97              : 
      98              : /*
      99              :    CheckProcedure - checks the procedure, p, for symbols which look like, s.
     100              : */
     101              : 
     102              : static void CheckProcedure (unsigned int m, unsigned int p);
     103              : 
     104              : /*
     105              :    CheckModule - checks the module, m, for symbols which look like, s.
     106              : */
     107              : 
     108              : static void CheckModule (unsigned int m, unsigned int s);
     109              : 
     110              : 
     111              : /*
     112              :    IsNotADuplicate - returns TRUE if either s1 or s2 have not been reported before.
     113              : */
     114              : 
     115            0 : static bool IsNotADuplicate (unsigned int s1, unsigned int s2)
     116              : {
     117            0 :   if ((! (Lists_IsItemInList (ErrantSymbols, s1))) && (! (Lists_IsItemInList (ErrantSymbols, s2))))
     118              :     {
     119            0 :       Lists_IncludeItemIntoList (ErrantSymbols, s1);
     120            0 :       Lists_IncludeItemIntoList (ErrantSymbols, s2);
     121            0 :       return true;
     122              :     }
     123              :   else
     124              :     {
     125            0 :       return false;
     126              :     }
     127              :   /* static analysis guarentees a RETURN statement will be used before here.  */
     128              :   __builtin_unreachable ();
     129              : }
     130              : 
     131              : 
     132              : /*
     133              :    IsNotADuplicateName - returns TRUE if name has not been reported before.
     134              : */
     135              : 
     136            1 : static bool IsNotADuplicateName (NameKey_Name name)
     137              : {
     138            1 :   if (! (Lists_IsItemInList (ErrantNames, name)))
     139              :     {
     140            1 :       Lists_IncludeItemIntoList (ErrantNames, name);
     141            1 :       return true;
     142              :     }
     143              :   else
     144              :     {
     145              :       return false;
     146              :     }
     147              :   /* static analysis guarentees a RETURN statement will be used before here.  */
     148              :   __builtin_unreachable ();
     149              : }
     150              : 
     151              : 
     152              : /*
     153              :    PerformVariableKeywordCheck - performs the check and constructs the metaerror notes if appropriate.
     154              : */
     155              : 
     156        29745 : static void PerformVariableKeywordCheck (unsigned int tok, NameKey_Name name)
     157              : {
     158        29745 :   NameKey_Name upper;
     159        29745 :   M2Reserved_toktype token;
     160        29745 :   DynamicStrings_String orig;
     161        29745 :   DynamicStrings_String upperS;
     162              : 
     163        29745 :   orig = DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (name));
     164        29745 :   upperS = DynamicStrings_ToUpper (DynamicStrings_Dup (orig));
     165        29745 :   upper = NameKey_makekey (DynamicStrings_string (upperS));
     166        29745 :   if (M2Reserved_IsReserved (upper, &token))
     167              :     {
     168            1 :       if (IsNotADuplicateName (name))
     169              :         {
     170            1 :           M2MetaError_MetaErrorStringT0 (tok, FormatStrings_Sprintf2 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "either the identifier has the same name as a keyword or alternatively a keyword has the wrong case ({%%K%s} and {!%%O:{%%K%s}})", 127)), (const unsigned char *) &upperS, (sizeof (upperS)-1), (const unsigned char *) &orig, (sizeof (orig)-1)));
     171            1 :           M2MetaError_MetaErrorStringT0 (tok, FormatStrings_Sprintf1 (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "the symbol name {!%%O:{%%K%s}} is legal as an identifier, however as such it might cause confusion and is considered bad programming practice", 141)), (const unsigned char *) &orig, (sizeof (orig)-1)));
     172              :         }
     173              :     }
     174        29745 :   upperS = DynamicStrings_KillString (upperS);
     175        29745 :   orig = DynamicStrings_KillString (orig);
     176        29745 : }
     177              : 
     178              : 
     179              : /*
     180              :    CheckAsciiName - checks to see whether ascii names, s1, and, s2, are similar.
     181              : */
     182              : 
     183       288960 : static void CheckAsciiName (unsigned int previous, unsigned int s1, unsigned int newblock, unsigned int s2)
     184              : {
     185       288960 :   NameKey_Name a1;
     186       288960 :   NameKey_Name a2;
     187              : 
     188       288960 :   a1 = SymbolTable_GetSymName (s1);
     189       288960 :   a2 = SymbolTable_GetSymName (s2);
     190       288960 :   if ((a1 == a2) && (a1 != NameKey_NulName))
     191              :     {
     192              :       /* avoid dangling else.  */
     193            0 :       if (IsNotADuplicate (s1, s2))
     194              :         {
     195            0 :           M2MetaError_MetaError2 ((const char *) "identical symbol name in two different scopes, scope {%1Oad} has symbol {%2Mad}", 79, previous, s1);
     196            0 :           M2MetaError_MetaError2 ((const char *) "identical symbol name in two different scopes, scope {%1Oad} has symbol {%2Mad}", 79, newblock, s2);
     197              :         }
     198              :     }
     199       288960 :   else if (NameKey_IsSameExcludingCase (a1, a2))
     200              :     {
     201              :       /* avoid dangling else.  */
     202            0 :       if (IsNotADuplicate (s1, s2))
     203              :         {
     204            0 :           M2MetaError_MetaError2 ((const char *) "very similar symbol names (different case) in two different scopes, scope {%1ORad} has symbol {%2Mad}", 101, previous, s1);
     205            0 :           M2MetaError_MetaError2 ((const char *) "very similar symbol names (different case) in two different scopes, scope {%1OCad} has symbol {%2Mad}", 101, newblock, s2);
     206              :         }
     207              :     }
     208       288960 : }
     209              : 
     210              : 
     211              : /*
     212              :    CheckProcedure - checks the procedure, p, for symbols which look like, s.
     213              : */
     214              : 
     215        11960 : static void CheckProcedure (unsigned int m, unsigned int p)
     216              : {
     217        11960 :   unsigned int i;
     218        11960 :   unsigned int n1;
     219        11960 :   unsigned int j;
     220        11960 :   unsigned int n2;
     221              : 
     222        11960 :   if (p != SymbolTable_NulSym)
     223              :     {
     224              :       i = 1;  /* I would have used NoOfParam(p)+1 but Stuart wants parameters checked as well - maybe he is right.  */
     225       120496 :       do {  /* I would have used NoOfParam(p)+1 but Stuart wants parameters checked as well - maybe he is right.  */
     226       120496 :         n1 = SymbolTable_GetNth (p, i);
     227       120496 :         if (n1 != SymbolTable_NulSym)
     228              :           {
     229       108536 :             if ((((SymbolTable_IsVar (n1)) || (SymbolTable_IsType (n1))) || (SymbolTable_IsProcedure (n1))) || (SymbolTable_IsRecord (n1)))
     230              :               {
     231              :                 j = 1;
     232       391848 :                 do {
     233       391848 :                   n2 = SymbolTable_GetNth (m, j);
     234       391848 :                   if (n2 != SymbolTable_NulSym)
     235              :                     {
     236       283312 :                       if ((((SymbolTable_IsVar (n2)) || (SymbolTable_IsType (n2))) || (SymbolTable_IsProcedure (n2))) || (SymbolTable_IsRecord (n2)))
     237              :                         {
     238       283312 :                           CheckAsciiName (m, n2, p, n1);
     239              :                         }
     240              :                     }
     241       391848 :                   j += 1;
     242       391848 :                 } while (! (n2 == SymbolTable_NulSym));
     243              :               }
     244              :           }
     245       120496 :         i += 1;
     246       120496 :       } while (! (n1 == SymbolTable_NulSym));
     247              :     }
     248        11960 : }
     249              : 
     250              : 
     251              : /*
     252              :    CheckModule - checks the module, m, for symbols which look like, s.
     253              : */
     254              : 
     255          852 : static void CheckModule (unsigned int m, unsigned int s)
     256              : {
     257          852 :   unsigned int i;
     258          852 :   unsigned int n;
     259              : 
     260          852 :   if (m != SymbolTable_NulSym)
     261              :     {
     262              :       i = 1;
     263         7352 :       do {
     264         7352 :         n = SymbolTable_GetNth (m, i);
     265         7352 :         if (n != SymbolTable_NulSym)
     266              :           {
     267         6500 :             if ((n != SymbolTable_NulSym) && (n != s))
     268              :               {
     269         5648 :                 if ((((SymbolTable_IsVar (n)) || (SymbolTable_IsType (n))) || (SymbolTable_IsProcedure (n))) || (SymbolTable_IsRecord (n)))
     270              :                   {
     271         5648 :                     CheckAsciiName (m, s, m, n);
     272              :                   }
     273              :               }
     274              :           }
     275         7352 :         i += 1;
     276         7352 :       } while (! (n == SymbolTable_NulSym));
     277              :     }
     278          852 : }
     279              : 
     280              : 
     281              : /*
     282              :    CheckVariableAgainstKeyword - checks for a identifier that looks the same
     283              :                                  as a keyword except for its case.
     284              : */
     285              : 
     286      1694938 : extern "C" void M2Students_CheckVariableAgainstKeyword (unsigned int tok, NameKey_Name name)
     287              : {
     288      1694938 :   if (M2Options_StyleChecking)
     289              :     {
     290        29745 :       PerformVariableKeywordCheck (tok, name);
     291              :     }
     292      1694938 : }
     293              : 
     294              : 
     295              : /*
     296              :    StudentVariableCheck - checks to see that variables are quite different from keywords and
     297              :                           issues an message if they are not. It ignores case so to catch
     298              :                           1st and 2nd semester programming errors.
     299              : */
     300              : 
     301          613 : extern "C" void M2Students_StudentVariableCheck (void)
     302              : {
     303          613 :   unsigned int i;
     304          613 :   unsigned int n;
     305          613 :   unsigned int m;
     306              : 
     307          613 :   m = SymbolTable_GetMainModule ();
     308              :   /* first check global scope  */
     309          613 :   i = 1;
     310         1465 :   do {
     311         1465 :     n = SymbolTable_GetNth (m, i);
     312         1465 :     if (n != SymbolTable_NulSym)
     313              :       {
     314          852 :         if ((((SymbolTable_IsVar (n)) || (SymbolTable_IsType (n))) || (SymbolTable_IsProcedure (n))) || (SymbolTable_IsRecord (n)))
     315              :           {
     316          852 :             CheckModule (m, n);
     317              :           }
     318              :       }
     319         1465 :     i += 1;
     320         1465 :   } while (! (n == SymbolTable_NulSym));
     321              :   /* now check local scope  */
     322              :   i = 1;
     323        12573 :   do {
     324        12573 :     n = SymbolTable_GetNthProcedure (m, i);
     325        12573 :     if (n != SymbolTable_NulSym)
     326              :       {
     327        11960 :         if (SymbolTable_IsProcedure (n))
     328              :           {
     329        11960 :             CheckProcedure (m, n);
     330              :           }
     331              :       }
     332        12573 :     i += 1;
     333        12573 :   } while (! (n == SymbolTable_NulSym));
     334          613 : }
     335              : 
     336        14952 : extern "C" void _M2_M2Students_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
     337              : {
     338        14952 :   Lists_InitList (&ErrantSymbols);
     339        14952 :   Lists_InitList (&ErrantNames);
     340        14952 : }
     341              : 
     342            0 : extern "C" void _M2_M2Students_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
     343              : {
     344            0 : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.