ECC: add function pattern check for non-boolean predicate expression check.
authorjlin16 <jlin16@7335b38e-4728-0410-8992-fb3ffe349368>
Mon, 16 Jun 2008 02:46:05 +0000 (02:46 +0000)
committerjlin16 <jlin16@7335b38e-4728-0410-8992-fb3ffe349368>
Mon, 16 Jun 2008 02:46:05 +0000 (02:46 +0000)
git-svn-id: https://buildtools.tianocore.org/svn/buildtools/trunk/BaseTools@1255 7335b38e-4728-0410-8992-fb3ffe349368

Source/Python/Ecc/c.py

index 70bbf62..8c2fff7 100644 (file)
@@ -14,13 +14,14 @@ IncludeFileListDict = {}
 IncludePathListDict = {}\r
 ComplexTypeDict = {}\r
 SUDict = {}\r
+IgnoredKeywordList = ['EFI_ERROR']\r
 \r
 def GetIgnoredDirListPattern():\r
     p = re.compile(r'.*[\\/](?:BUILD|INTELRESTRICTEDTOOLS|INTELRESTRICTEDPKG|PCCTS)[\\/].*')\r
     return p\r
 \r
 def GetFuncDeclPattern():\r
-    p = re.compile(r'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\).*', re.DOTALL)\r
+    p = re.compile(r'(EFIAPI|EFI_BOOT_SERVICE|EFI_RUNTIME_SERVICE)?\s*[_\w]+\s*\(.*\)$', re.DOTALL)\r
     return p\r
 \r
 def GetArrayPattern():\r
@@ -124,10 +125,10 @@ def GetIdentifierList():
         var.Declarator = DeclText\r
         if FuncDeclPattern.match(var.Declarator):\r
             DeclSplitList = var.Declarator.split('(')     \r
-            FuncName = DeclSplitList[0]\r
+            FuncName = DeclSplitList[0].strip()\r
             FuncNamePartList = FuncName.split()\r
             if len(FuncNamePartList) > 1:\r
-                FuncName = FuncNamePartList[-1]\r
+                FuncName = FuncNamePartList[-1].strip()\r
                 NameStart = DeclSplitList[0].rfind(FuncName)\r
                 var.Declarator = var.Declarator[NameStart:]\r
                 if NameStart > 0:\r
@@ -160,7 +161,7 @@ def GetIdentifierList():
                             Index += 1\r
                             VarNameStartColumn += 1\r
                         PreChar = FirstChar\r
-            IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, '', DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)\r
+            IdVar = DataClass.IdentifierClass(-1, var.Modifier, '', var.Declarator, FuncName, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, -1, -1, var.StartPos[0], var.StartPos[1], VarNameStartLine, VarNameStartColumn)\r
             IdList.append(IdVar)\r
             continue\r
         \r
@@ -208,7 +209,7 @@ def GetIdentifierList():
             Value = ''\r
         else:\r
             Name = su.Content[SkipLen:LBPos].strip()\r
-            Value = su.Content[LBPos+1:RBPos]\r
+            Value = su.Content[LBPos:RBPos+1]\r
         IdPE = DataClass.IdentifierClass(-1, '', '', Name, Value, Type, -1, -1, su.StartPos[0],su.StartPos[1],su.EndPos[0],su.EndPos[1])\r
         IdList.append(IdPE)\r
     \r
@@ -633,7 +634,7 @@ def GetCNameList(Lvalue):
         DotIndex = Lvalue[VarEnd:].find('.')\r
         ArrowIndex = Lvalue[VarEnd:].find('->')\r
         if DotIndex == -1 and ArrowIndex == -1:\r
-                break\r
+            break\r
         elif DotIndex == -1 and ArrowIndex != -1:\r
             SearchBegin = VarEnd + ArrowIndex\r
         elif ArrowIndex == -1 and DotIndex != -1:\r
@@ -767,8 +768,13 @@ def GetTypedefDict(FullFileName):
         ResultSet = Db.TblFile.Exec(SqlStatement)\r
     \r
         for Result in ResultSet:\r
-            if len(Result[0]) == 0:\r
+            if not Result[2].startswith('FP ('):\r
                 Dict[Result[1]] = Result[2]\r
+            else:\r
+                if len(Result[0]) == 0:\r
+                    Dict[Result[1]] = 'VOID'\r
+                else:\r
+                    Dict[Result[1]] = GetDataTypeFromModifier(Result[0])\r
                 \r
     ComplexTypeDict[FullFileName] = Dict\r
     return Dict\r
@@ -845,20 +851,26 @@ def GetFinalTypeValue(Type, FieldName, TypedefDict, SUDict):
             continue\r
         if not Field[Index - 1].isalnum():\r
             if Index + len(FieldName) == len(Field):\r
-                Type = GetCNameList(Field[0:Index])\r
-                if len(Type) == 0:\r
-                    return Field[0:Index]\r
-                return Type[0]\r
-            else:\r
-                if not Field[Index + len(FieldName) + 1].isalnum():\r
-                    Type = GetCNameList(Field[0:Index])\r
-                    if len(Type) == 0:\r
-                        return Field[0:Index]\r
-                    return Type[0]\r
+                Type = GetDataTypeFromModifier(Field[0:Index])\r
+                return Type.split()[-1]\r
+#            else:\r
+#                if not Field[Index + len(FieldName) + 1].isalnum():\r
+#                    Type = GetCNameList(Field[0:Index])\r
+#                    if len(Type) == 0:\r
+#                        return Field[0:Index]\r
+#                    return Type[0]\r
     return None\r
     \r
+def GetRealType(Type, TypedefDict, TargetType = None):\r
+    if TargetType != None and Type == TargetType:\r
+            return Type\r
+    while TypedefDict.get(Type):\r
+        Type = TypedefDict.get(Type)\r
+        if TargetType != None and Type == TargetType:\r
+            return Type\r
+    return Type\r
 \r
-def GetTypeInfo(RefList, Modifier, FullFileName):\r
+def GetTypeInfo(RefList, Modifier, FullFileName, TargetType = None):\r
     TypedefDict = GetTypedefDict(FullFileName)\r
     SUDict = GetSUDict(FullFileName)\r
     Type = GetDataTypeFromModifier(Modifier).rstrip('*').strip()\r
@@ -873,15 +885,84 @@ def GetTypeInfo(RefList, Modifier, FullFileName):
         Type = FromType\r
         Index += 1\r
 \r
+    Type = GetRealType(Type, TypedefDict, TargetType)\r
+\r
     return Type\r
 \r
-def GetVarInfo(PredVarList, FuncRecord, FullFileName):\r
+def GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall = False, TargetType = None):\r
     \r
     PredVar = PredVarList[0]\r
     FileID = GetTableID(FullFileName)\r
     \r
     Db = GetDB()\r
     FileTable = 'Identifier' + str(FileID)\r
+    # search variable in include files\r
+    IncludeFileList = GetAllIncludeFiles(FullFileName)\r
+    # it is a function call, search function declarations and definitions\r
+    if IsFuncCall:\r
+        SqlStatement = """ select Modifier, ID\r
+                       from %s\r
+                       where Model = %d and Value = \'%s\'\r
+                   """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)\r
+        ResultSet = Db.TblFile.Exec(SqlStatement)\r
+    \r
+        for Result in ResultSet:        \r
+            Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
+            TypedefDict = GetTypedefDict(FullFileName)\r
+            Type = GetRealType(Type, TypedefDict, TargetType)\r
+            return Type\r
+        \r
+        for F in IncludeFileList:\r
+            FileID = GetTableID(F)\r
+            if FileID < 0:\r
+                continue\r
+        \r
+            FileTable = 'Identifier' + str(FileID)\r
+            SqlStatement = """ select Modifier, ID\r
+                           from %s\r
+                           where Model = %d and Value = \'%s\'\r
+                       """ % (FileTable, DataClass.MODEL_IDENTIFIER_FUNCTION_DECLARATION, PredVar)\r
+            ResultSet = Db.TblFile.Exec(SqlStatement)\r
+    \r
+            for Result in ResultSet:\r
+                Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
+                TypedefDict = GetTypedefDict(FullFileName)\r
+                Type = GetRealType(Type, TypedefDict, TargetType)\r
+                return Type\r
+    \r
+        FileID = GetTableID(FullFileName)\r
+        SqlStatement = """ select Modifier, ID\r
+                       from Function\r
+                       where BelongsToFile = %d and Name = \'%s\'\r
+                   """ % (FileID, PredVar)\r
+        ResultSet = Db.TblFile.Exec(SqlStatement)\r
+    \r
+        for Result in ResultSet:        \r
+            Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
+            TypedefDict = GetTypedefDict(FullFileName)\r
+            Type = GetRealType(Type, TypedefDict, TargetType)\r
+            return Type\r
+        \r
+        for F in IncludeFileList:\r
+            FileID = GetTableID(F)\r
+            if FileID < 0:\r
+                continue\r
+        \r
+            FileTable = 'Identifier' + str(FileID)\r
+            SqlStatement = """ select Modifier, ID\r
+                           from Function\r
+                           where BelongsToFile = %d and Name = \'%s\'\r
+                       """ % (FileID, PredVar)\r
+            ResultSet = Db.TblFile.Exec(SqlStatement)\r
+    \r
+            for Result in ResultSet:\r
+                Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
+                TypedefDict = GetTypedefDict(FullFileName)\r
+                Type = GetRealType(Type, TypedefDict, TargetType)\r
+                return Type\r
+         \r
+        return None\r
+       \r
     # really variable, search local variable first\r
     SqlStatement = """ select Modifier, ID\r
                        from %s\r
@@ -891,10 +972,12 @@ def GetVarInfo(PredVarList, FuncRecord, FullFileName):
     VarFound = False\r
     for Result in ResultSet:\r
         if len(PredVarList) > 1:\r
-            Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName)\r
+            Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)\r
             return Type\r
         else:\r
             Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
+            TypedefDict = GetTypedefDict(FullFileName)\r
+            Type = GetRealType(Type, TypedefDict, TargetType)\r
             return Type\r
                 \r
     # search function parameters second\r
@@ -902,10 +985,12 @@ def GetVarInfo(PredVarList, FuncRecord, FullFileName):
     for Param in ParamList:\r
         if Param.Name.strip() == PredVar:\r
             if len(PredVarList) > 1:\r
-                Type = GetTypeInfo(PredVarList[1:], Param.Modifier, FullFileName)\r
+                Type = GetTypeInfo(PredVarList[1:], Param.Modifier, FullFileName, TargetType)\r
                 return Type\r
             else:\r
                 Type = GetDataTypeFromModifier(Param.Modifier).split()[-1]\r
+                TypedefDict = GetTypedefDict(FullFileName)\r
+                Type = GetRealType(Type, TypedefDict, TargetType)\r
                 return Type\r
           \r
     # search global variable next\r
@@ -917,14 +1002,14 @@ def GetVarInfo(PredVarList, FuncRecord, FullFileName):
 \r
     for Result in ResultSet:\r
         if len(PredVarList) > 1:\r
-            Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName)\r
+            Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)\r
             return Type\r
         else:\r
             Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
+            TypedefDict = GetTypedefDict(FullFileName)\r
+            Type = GetRealType(Type, TypedefDict, TargetType)\r
             return Type\r
     \r
-    # search variable in include files\r
-    IncludeFileList = GetAllIncludeFiles(FullFileName)\r
     for F in IncludeFileList:\r
         FileID = GetTableID(F)\r
         if FileID < 0:\r
@@ -939,10 +1024,12 @@ def GetVarInfo(PredVarList, FuncRecord, FullFileName):
 \r
         for Result in ResultSet:\r
             if len(PredVarList) > 1:\r
-                Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName)\r
+                Type = GetTypeInfo(PredVarList[1:], Result[0], FullFileName, TargetType)\r
                 return Type\r
             else:\r
                 Type = GetDataTypeFromModifier(Result[0]).split()[-1]\r
+                TypedefDict = GetTypedefDict(FullFileName)\r
+                Type = GetRealType(Type, TypedefDict, TargetType)\r
                 return Type\r
 \r
 def CheckFuncLayoutReturnType(FullFileName):\r
@@ -1415,6 +1502,9 @@ def CheckNonBooleanValueComparison(FullFileName):
     if FileID < 0:\r
         return ErrorMsgList\r
     \r
+    # cache the found function return type to accelerate later checking in this file.\r
+    FuncReturnTypeDict = {}\r
+    \r
     Db = GetDB()\r
     FileTable = 'Identifier' + str(FileID)\r
     SqlStatement = """ select Value, StartLine, ID\r
@@ -1444,23 +1534,46 @@ def CheckNonBooleanValueComparison(FullFileName):
             continue\r
         \r
         for Exp in GetPredicateListFromPredicateExpStr(Str[0]):\r
-            if p.match(Exp):\r
-                continue\r
+#            if p.match(Exp):\r
+#                continue\r
             PredInfo = SplitPredicateStr(Exp)\r
             if PredInfo[1] == None:\r
-                PredVarList = GetCNameList(PredInfo[0][0])\r
+                PredVarStr = PredInfo[0][0].strip()\r
+                IsFuncCall = False\r
+                SearchInCache = False\r
+                # PredVarStr may contain '.' or '->'\r
+                TmpStr = PredVarStr.replace('.', '').replace('->', '')\r
+                if p.match(TmpStr):\r
+                    PredVarStr = PredVarStr[0:PredVarStr.find('(')]\r
+                    SearchInCache = True\r
+                    \r
+                if PredVarStr.strip() in IgnoredKeywordList:\r
+                    continue\r
+                PredVarList = GetCNameList(PredVarStr)\r
                 # No variable found, maybe value first? like (0 == VarName)\r
                 if len(PredVarList) == 0:\r
                     continue\r
-                # in the form of function call\r
-                if p.match(PredInfo[0][0]):\r
-                    continue\r
-                \r
-                Type = GetVarInfo(PredVarList, FuncRecord, FullFileName)\r
+                # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.\r
+                if len(PredVarList) == 1:    \r
+                    IsFuncCall = True   \r
+                if SearchInCache:\r
+                    Type = FuncReturnTypeDict.get(PredVarStr)\r
+                    if Type != None:\r
+                        if Type.find('BOOLEAN') == -1:\r
+                            PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
+                        continue\r
+                    \r
+                    if PredVarStr in FuncReturnTypeDict:\r
+                        continue\r
+                    \r
+                Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN')\r
+                if SearchInCache:\r
+                    FuncReturnTypeDict[PredVarStr] = Type\r
                 if Type == None:\r
                     continue\r
                 if Type.find('BOOLEAN') == -1:\r
                     PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
+            \r
 \r
 def CheckBooleanValueComparison(FullFileName):\r
     ErrorMsgList = []\r
@@ -1469,6 +1582,9 @@ def CheckBooleanValueComparison(FullFileName):
     if FileID < 0:\r
         return ErrorMsgList\r
     \r
+    # cache the found function return type to accelerate later checking in this file.\r
+    FuncReturnTypeDict = {}\r
+    \r
     Db = GetDB()\r
     FileTable = 'Identifier' + str(FileID)\r
     SqlStatement = """ select Value, StartLine, ID\r
@@ -1501,14 +1617,37 @@ def CheckBooleanValueComparison(FullFileName):
             PredInfo = SplitPredicateStr(Exp)\r
             if PredInfo[1] in ('==', '!=') and PredInfo[0][1] in ('TRUE', 'FALSE'):\r
                 PredVarList = GetCNameList(PredInfo[0][0])\r
+                IsFuncCall = False\r
+                SearchInCache = False\r
+                # PredVarStr may contain '.' or '->'\r
+                TmpStr = PredVarStr.replace('.', '').replace('->', '')\r
+                if p.match(TmpStr):\r
+                    PredVarStr = PredVarStr[0:PredVarStr.find('(')]\r
+                    SearchInCache = True\r
+                    \r
+                if PredVarStr.strip() in IgnoredKeywordList:\r
+                    continue\r
+                PredVarList = GetCNameList(PredVarStr)\r
                 # No variable found, maybe value first? like (0 == VarName)\r
                 if len(PredVarList) == 0:\r
                     continue\r
-                # in the form of function call\r
-                if p.match(PredInfo[0][0]):\r
-                    continue\r
                 \r
-                Type = GetVarInfo(PredVarList, FuncRecord, FullFileName)\r
+                # Only direct function call using IsFuncCall branch. Multi-level ref. function call is considered a variable.\r
+                if len(PredVarList) == 1:    \r
+                    IsFuncCall = True   \r
+                if SearchInCache:\r
+                    Type = FuncReturnTypeDict.get(PredVarStr)\r
+                    if Type != None:\r
+                        if Type.find('BOOLEAN') != -1:\r
+                            PrintErrorMsg(ERROR_PREDICATE_EXPRESSION_CHECK_NO_BOOLEAN_OPERATOR, 'Predicate Expression: %s' % Exp, FileTable, Str[2])\r
+                        continue\r
+                    \r
+                    if PredVarStr in FuncReturnTypeDict:\r
+                        continue\r
+                \r
+                Type = GetVarInfo(PredVarList, FuncRecord, FullFileName, IsFuncCall, 'BOOLEAN')\r
+                if SearchInCache:\r
+                    FuncReturnTypeDict[PredVarStr] = Type\r
                 if Type == None:\r
                     continue\r
                 if Type.find('BOOLEAN') != -1:\r