Compare commits
18 Commits
Author | SHA1 | Date |
---|---|---|
Daniel Marjamäki | 392741715b | |
Daniel Marjamäki | ef8a499c8d | |
Wolfgang Stöggl | 1cc234ac2c | |
Daniel Marjamäki | 9ef14d179d | |
Daniel Marjamäki | 41872f9a6d | |
Daniel Marjamäki | 635059603a | |
Daniel Marjamäki | 4c650289ad | |
Daniel Marjamäki | 760436c56e | |
Daniel Marjamäki | 355866f0cf | |
Daniel Marjamäki | 97bf53515b | |
Daniel Marjamäki | a06898dc8e | |
Daniel Marjamäki | a045149181 | |
Daniel Marjamäki | 54d079387e | |
Georgi D. Sotirov | 199fe343c3 | |
Oliver Stöneberg | d922a3b0bc | |
Daniel Marjamäki | f0150069c8 | |
Daniel Marjamäki | 6ef6b02153 | |
Daniel Marjamäki | c5b3fafe84 |
|
@ -27,7 +27,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install libxml2-utils
|
sudo apt-get install libxml2-utils
|
||||||
sudo apt-get install z3 libz3-dev
|
sudo apt-get install libz3-dev libtinyxml2-dev
|
||||||
sudo apt-get install qtbase5-dev qttools5-dev libqt5charts5-dev qt5-default
|
sudo apt-get install qtbase5-dev qttools5-dev libqt5charts5-dev qt5-default
|
||||||
|
|
||||||
- name: Fix missing z3_version.h
|
- name: Fix missing z3_version.h
|
||||||
|
@ -45,6 +45,20 @@ jobs:
|
||||||
python -m pip install pip --upgrade
|
python -m pip install pip --upgrade
|
||||||
python -m pip install pytest
|
python -m pip install pytest
|
||||||
|
|
||||||
|
- name: CMake build on ubuntu (with GUI / system tinyxml2)
|
||||||
|
if: contains(matrix.os, 'ubuntu')
|
||||||
|
run: |
|
||||||
|
mkdir cmake.output.tinyxml2
|
||||||
|
cd cmake.output.tinyxml2
|
||||||
|
cmake -G "Unix Makefiles" -DUSE_Z3=On -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DUSE_BUNDLED_TINYXML2=Off ..
|
||||||
|
cmake --build . -- -j$(nproc)
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
- name: Run CMake test (system tinyxml2)
|
||||||
|
if: contains(matrix.os, 'ubuntu')
|
||||||
|
run: |
|
||||||
|
cmake --build cmake.output.tinyxml2 --target check -- -j$(nproc)
|
||||||
|
|
||||||
- name: CMake build on ubuntu (with GUI)
|
- name: CMake build on ubuntu (with GUI)
|
||||||
if: contains(matrix.os, 'ubuntu')
|
if: contains(matrix.os, 'ubuntu')
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -13,6 +13,7 @@ import argparse
|
||||||
import cppcheckdata
|
import cppcheckdata
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
import subprocess
|
||||||
|
|
||||||
VERIFY = ('-verify' in sys.argv)
|
VERIFY = ('-verify' in sys.argv)
|
||||||
VERIFY_EXPECTED = []
|
VERIFY_EXPECTED = []
|
||||||
|
@ -195,7 +196,9 @@ def int31(data, platform):
|
||||||
if to_value_type is None or not from_values:
|
if to_value_type is None or not from_values:
|
||||||
continue
|
continue
|
||||||
bits = None
|
bits = None
|
||||||
if to_value_type.type == 'char':
|
if token.valueType.pointer > 0:
|
||||||
|
bits = platform.pointer_bit
|
||||||
|
elif to_value_type.type == 'char':
|
||||||
bits = platform.char_bit
|
bits = platform.char_bit
|
||||||
elif to_value_type.type == 'short':
|
elif to_value_type.type == 'short':
|
||||||
bits = platform.short_bit
|
bits = platform.short_bit
|
||||||
|
@ -399,6 +402,8 @@ if __name__ == '__main__':
|
||||||
parser = get_args_parser()
|
parser = get_args_parser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
path_premium_addon = cppcheckdata.get_path_premium_addon()
|
||||||
|
|
||||||
if args.verify:
|
if args.verify:
|
||||||
VERIFY = True
|
VERIFY = True
|
||||||
|
|
||||||
|
@ -411,6 +416,14 @@ if __name__ == '__main__':
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
print('Checking %s...' % dumpfile)
|
print('Checking %s...' % dumpfile)
|
||||||
|
|
||||||
|
if path_premium_addon:
|
||||||
|
premium_command = [path_premium_addon, '--cert', dumpfile]
|
||||||
|
if args.cli:
|
||||||
|
premium_command.append('--cli')
|
||||||
|
for line in subprocess.check_output(premium_command).decode('ascii').split('\n'):
|
||||||
|
if line.find('cert-') > 0:
|
||||||
|
print(line.strip())
|
||||||
|
|
||||||
data = cppcheckdata.CppcheckData(dumpfile)
|
data = cppcheckdata.CppcheckData(dumpfile)
|
||||||
|
|
||||||
if VERIFY:
|
if VERIFY:
|
||||||
|
|
|
@ -8,6 +8,8 @@ License: No restrictions, use this as you need.
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
@ -141,21 +143,11 @@ class ValueType:
|
||||||
def __init__(self, element):
|
def __init__(self, element):
|
||||||
self.type = element.get('valueType-type')
|
self.type = element.get('valueType-type')
|
||||||
self.sign = element.get('valueType-sign')
|
self.sign = element.get('valueType-sign')
|
||||||
bits = element.get('valueType-bits')
|
self.bits = int(element.get('valueType-bits', 0))
|
||||||
if bits:
|
|
||||||
self.bits = int(bits)
|
|
||||||
self.typeScopeId = element.get('valueType-typeScope')
|
self.typeScopeId = element.get('valueType-typeScope')
|
||||||
self.originalTypeName = element.get('valueType-originalTypeName')
|
self.originalTypeName = element.get('valueType-originalTypeName')
|
||||||
constness = element.get('valueType-constness')
|
self.constness = int(element.get('valueType-constness', 0))
|
||||||
if constness:
|
self.pointer = int(element.get('valueType-pointer', 0))
|
||||||
self.constness = int(constness)
|
|
||||||
else:
|
|
||||||
self.constness = 0
|
|
||||||
pointer = element.get('valueType-pointer')
|
|
||||||
if pointer:
|
|
||||||
self.pointer = int(pointer)
|
|
||||||
else:
|
|
||||||
self.pointer = 0
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
attrs = ["type", "sign", "bits", "typeScopeId", "originalTypeName",
|
attrs = ["type", "sign", "bits", "typeScopeId", "originalTypeName",
|
||||||
|
@ -618,9 +610,7 @@ class Variable:
|
||||||
self.isPointer = element.get('isPointer') == 'true'
|
self.isPointer = element.get('isPointer') == 'true'
|
||||||
self.isReference = element.get('isReference') == 'true'
|
self.isReference = element.get('isReference') == 'true'
|
||||||
self.isStatic = element.get('isStatic') == 'true'
|
self.isStatic = element.get('isStatic') == 'true'
|
||||||
self.constness = element.get('constness')
|
self.constness = int(element.get('constness',0))
|
||||||
if self.constness:
|
|
||||||
self.constness = int(self.constness)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
attrs = ["Id", "nameTokenId", "typeStartTokenId", "typeEndTokenId",
|
attrs = ["Id", "nameTokenId", "typeStartTokenId", "typeEndTokenId",
|
||||||
|
@ -1364,3 +1354,14 @@ def reportSummary(dumpfile, summary_type, summary_data):
|
||||||
with open(ctu_info_file, 'at') as f:
|
with open(ctu_info_file, 'at') as f:
|
||||||
msg = {'summary': summary_type, 'data': summary_data}
|
msg = {'summary': summary_type, 'data': summary_data}
|
||||||
f.write(json.dumps(msg) + '\n')
|
f.write(json.dumps(msg) + '\n')
|
||||||
|
|
||||||
|
|
||||||
|
def get_path_premium_addon():
|
||||||
|
p = pathlib.Path(sys.argv[0]).parent.parent
|
||||||
|
|
||||||
|
for ext in ('.exe', ''):
|
||||||
|
p1 = os.path.join(p, 'premiumaddon' + ext)
|
||||||
|
p2 = os.path.join(p, 'cppcheck' + ext)
|
||||||
|
if os.path.isfile(p1) and os.path.isfile(p2):
|
||||||
|
return p1
|
||||||
|
return None
|
||||||
|
|
135
addons/misra.py
135
addons/misra.py
|
@ -25,6 +25,7 @@ import argparse
|
||||||
import codecs
|
import codecs
|
||||||
import string
|
import string
|
||||||
import copy
|
import copy
|
||||||
|
import subprocess
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from itertools import izip as zip
|
from itertools import izip as zip
|
||||||
|
@ -422,6 +423,28 @@ def get_type_conversion_to_from(token):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def is_composite_expr(expr, composite_operator=False):
|
||||||
|
"""MISRA C 2012, section 8.10.3"""
|
||||||
|
if expr is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not composite_operator:
|
||||||
|
if (expr.str in ('+', '-', '*', '/', '%', '&', '|', '^', '>>', "<<", "?", ":", '~')):
|
||||||
|
return is_composite_expr(expr.astOperand1,True) or is_composite_expr(expr.astOperand2, True)
|
||||||
|
if expr.str == '?' and simpleMatch(expr.astOperand2, ':'):
|
||||||
|
colon = expr.astOperand2
|
||||||
|
return is_composite_expr(colon.astOperand1,True) or is_composite_expr(colon.astOperand2, True)
|
||||||
|
return False
|
||||||
|
|
||||||
|
# non constant expression?
|
||||||
|
if expr.isNumber:
|
||||||
|
return False
|
||||||
|
if expr.astOperand1 or expr.astOperand2:
|
||||||
|
return is_composite_expr(expr.astOperand1,True) or is_composite_expr(expr.astOperand2, True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def getEssentialTypeCategory(expr):
|
def getEssentialTypeCategory(expr):
|
||||||
if not expr:
|
if not expr:
|
||||||
return None
|
return None
|
||||||
|
@ -1009,16 +1032,14 @@ def isNoReturnScope(tok):
|
||||||
|
|
||||||
|
|
||||||
# Return the token which the value is assigned to
|
# Return the token which the value is assigned to
|
||||||
def getAssignedVariableToken(valueToken):
|
def getAssignedVariableToken(vartok):
|
||||||
if not valueToken:
|
if not vartok:
|
||||||
return None
|
return None
|
||||||
if not valueToken.astParent:
|
parent = vartok.astParent
|
||||||
return None
|
while parent and parent.isArithmeticalOp:
|
||||||
operator = valueToken.astParent
|
parent = parent.astParent
|
||||||
if operator.isAssignmentOp:
|
if parent and parent.isAssignmentOp:
|
||||||
return operator.astOperand1
|
return parent.astOperand1
|
||||||
if operator.isArithmeticalOp:
|
|
||||||
return getAssignedVariableToken(operator)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# If the value is used as a return value, return the function definition
|
# If the value is used as a return value, return the function definition
|
||||||
|
@ -1297,6 +1318,8 @@ class MisraChecker:
|
||||||
self._ctu_summary_identifiers = False
|
self._ctu_summary_identifiers = False
|
||||||
self._ctu_summary_usage = False
|
self._ctu_summary_usage = False
|
||||||
|
|
||||||
|
self.path_premium_addon = None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
attrs = ["settings", "verify_expected", "verify_actual", "violations",
|
attrs = ["settings", "verify_expected", "verify_actual", "violations",
|
||||||
"ruleTexts", "suppressedRules", "filePrefix",
|
"ruleTexts", "suppressedRules", "filePrefix",
|
||||||
|
@ -1372,7 +1395,9 @@ class MisraChecker:
|
||||||
local_identifiers.append(identifier(var.nameToken))
|
local_identifiers.append(identifier(var.nameToken))
|
||||||
elif var.isStatic:
|
elif var.isStatic:
|
||||||
names.append(var.nameToken.str)
|
names.append(var.nameToken.str)
|
||||||
internal_identifiers.append(identifier(var.nameToken))
|
i = identifier(var.nameToken)
|
||||||
|
i['inlinefunc'] = False
|
||||||
|
internal_identifiers.append(i)
|
||||||
else:
|
else:
|
||||||
names.append(var.nameToken.str)
|
names.append(var.nameToken.str)
|
||||||
i = identifier(var.nameToken)
|
i = identifier(var.nameToken)
|
||||||
|
@ -1383,9 +1408,14 @@ class MisraChecker:
|
||||||
if func.tokenDef is None:
|
if func.tokenDef is None:
|
||||||
continue
|
continue
|
||||||
if func.isStatic:
|
if func.isStatic:
|
||||||
internal_identifiers.append(identifier(func.tokenDef))
|
|
||||||
else:
|
|
||||||
i = identifier(func.tokenDef)
|
i = identifier(func.tokenDef)
|
||||||
|
i['inlinefunc'] = func.isInlineKeyword
|
||||||
|
internal_identifiers.append(i)
|
||||||
|
else:
|
||||||
|
if func.token is None:
|
||||||
|
i = identifier(func.tokenDef)
|
||||||
|
else:
|
||||||
|
i = identifier(func.token)
|
||||||
i['decl'] = func.token is None
|
i['decl'] = func.token is None
|
||||||
external_identifiers.append(i)
|
external_identifiers.append(i)
|
||||||
|
|
||||||
|
@ -1404,12 +1434,12 @@ class MisraChecker:
|
||||||
continue
|
continue
|
||||||
if token.function and token.scope.isExecutable:
|
if token.function and token.scope.isExecutable:
|
||||||
if (not token.function.isStatic) and (token.str not in names):
|
if (not token.function.isStatic) and (token.str not in names):
|
||||||
names.append(token.str)
|
names.append({'name': token.str, 'file': token.file})
|
||||||
elif token.variable:
|
elif token.variable:
|
||||||
if token == token.variable.nameToken:
|
if token == token.variable.nameToken:
|
||||||
continue
|
continue
|
||||||
if token.variable.access == 'Global' and (not token.variable.isStatic) and (token.str not in names):
|
if token.variable.access == 'Global' and (not token.variable.isStatic) and (token.str not in names):
|
||||||
names.append(token.str)
|
names.append({'name': token.str, 'file': token.file})
|
||||||
|
|
||||||
if len(names) > 0:
|
if len(names) > 0:
|
||||||
cppcheckdata.reportSummary(dumpfile, 'MisraUsage', names)
|
cppcheckdata.reportSummary(dumpfile, 'MisraUsage', names)
|
||||||
|
@ -1759,41 +1789,9 @@ class MisraChecker:
|
||||||
self.reportError(tok, 7, 1)
|
self.reportError(tok, 7, 1)
|
||||||
|
|
||||||
def misra_7_2(self, data):
|
def misra_7_2(self, data):
|
||||||
# Large constant numbers that are assigned to a variable should have an
|
|
||||||
# u/U suffix if the variable type is unsigned.
|
|
||||||
def reportErrorIfMissingSuffix(variable, value):
|
|
||||||
if 'U' in value.str.upper():
|
|
||||||
return
|
|
||||||
if value and value.isNumber:
|
|
||||||
if variable and variable.valueType and variable.valueType.sign == 'unsigned':
|
|
||||||
if variable.valueType.type in ['char', 'short', 'int', 'long', 'long long']:
|
|
||||||
limit = 1 << (bitsOfEssentialType(variable.valueType.type) -1)
|
|
||||||
v = value.getKnownIntValue()
|
|
||||||
if v is not None and v >= limit:
|
|
||||||
self.reportError(value, 7, 2)
|
|
||||||
|
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
# Check normal variable assignment
|
if token.isInt and ('U' not in token.str.upper()) and token.valueType and token.valueType.sign == 'unsigned':
|
||||||
if token.valueType and token.isNumber:
|
self.reportError(token, 7, 2)
|
||||||
variable = getAssignedVariableToken(token)
|
|
||||||
reportErrorIfMissingSuffix(variable, token)
|
|
||||||
|
|
||||||
# Check use as function parameter
|
|
||||||
if isFunctionCall(token) and token.astOperand1 and token.astOperand1.function:
|
|
||||||
functionDeclaration = token.astOperand1.function
|
|
||||||
|
|
||||||
if functionDeclaration.tokenDef:
|
|
||||||
if functionDeclaration.tokenDef is token.astOperand1:
|
|
||||||
# Token is not a function call, but it is the definition of the function
|
|
||||||
continue
|
|
||||||
|
|
||||||
parametersUsed = getArguments(token)
|
|
||||||
for i in range(len(parametersUsed)):
|
|
||||||
usedParameter = parametersUsed[i]
|
|
||||||
if usedParameter.isNumber:
|
|
||||||
parameterDefinition = functionDeclaration.argument.get(i+1)
|
|
||||||
if parameterDefinition and parameterDefinition.nameToken:
|
|
||||||
reportErrorIfMissingSuffix(parameterDefinition.nameToken, usedParameter)
|
|
||||||
|
|
||||||
def misra_7_3(self, rawTokens):
|
def misra_7_3(self, rawTokens):
|
||||||
compiled = re.compile(r'^[0-9.]+[Uu]*l+[Uu]*$')
|
compiled = re.compile(r'^[0-9.]+[Uu]*l+[Uu]*$')
|
||||||
|
@ -2277,8 +2275,7 @@ class MisraChecker:
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
if token.str != '=' or not token.astOperand1 or not token.astOperand2:
|
if token.str != '=' or not token.astOperand1 or not token.astOperand2:
|
||||||
continue
|
continue
|
||||||
if (token.astOperand2.str not in ('+', '-', '*', '/', '%', '&', '|', '^', '>>', "<<", "?", ":", '~') and
|
if not is_composite_expr(token.astOperand2):
|
||||||
not isCast(token.astOperand2)):
|
|
||||||
continue
|
continue
|
||||||
vt1 = token.astOperand1.valueType
|
vt1 = token.astOperand1.valueType
|
||||||
vt2 = token.astOperand2.valueType
|
vt2 = token.astOperand2.valueType
|
||||||
|
@ -4058,7 +4055,10 @@ class MisraChecker:
|
||||||
misra_severity = self.ruleTexts[ruleNum].misra_severity
|
misra_severity = self.ruleTexts[ruleNum].misra_severity
|
||||||
cppcheck_severity = self.ruleTexts[ruleNum].cppcheck_severity
|
cppcheck_severity = self.ruleTexts[ruleNum].cppcheck_severity
|
||||||
elif len(self.ruleTexts) == 0:
|
elif len(self.ruleTexts) == 0:
|
||||||
errmsg = 'misra violation (use --rule-texts=<file> to get proper output)'
|
if self.path_premium_addon:
|
||||||
|
errmsg = subprocess.check_output([self.path_premium_addon, '--get-rule-text=' + errorId]).strip().decode('ascii')
|
||||||
|
else:
|
||||||
|
errmsg = 'misra violation (use --rule-texts=<file> to get proper output)'
|
||||||
else:
|
else:
|
||||||
errmsg = 'misra violation %s with no text in the supplied rule-texts-file' % (ruleNum)
|
errmsg = 'misra violation %s with no text in the supplied rule-texts-file' % (ruleNum)
|
||||||
|
|
||||||
|
@ -4392,6 +4392,10 @@ class MisraChecker:
|
||||||
self.executeCheck(2209, self.misra_22_9, cfg)
|
self.executeCheck(2209, self.misra_22_9, cfg)
|
||||||
self.executeCheck(2210, self.misra_22_10, cfg)
|
self.executeCheck(2210, self.misra_22_10, cfg)
|
||||||
|
|
||||||
|
# Premium MISRA checking, deep analysis
|
||||||
|
if cfgNumber == 0 and self.path_premium_addon:
|
||||||
|
subprocess.call([self.path_premium_addon, '--misra', dumpfile])
|
||||||
|
|
||||||
def analyse_ctu_info(self, ctu_info_files):
|
def analyse_ctu_info(self, ctu_info_files):
|
||||||
all_typedef_info = []
|
all_typedef_info = []
|
||||||
all_tagname_info = []
|
all_tagname_info = []
|
||||||
|
@ -4400,7 +4404,7 @@ class MisraChecker:
|
||||||
all_external_identifiers_def = {}
|
all_external_identifiers_def = {}
|
||||||
all_internal_identifiers = {}
|
all_internal_identifiers = {}
|
||||||
all_local_identifiers = {}
|
all_local_identifiers = {}
|
||||||
all_usage_count = {}
|
all_usage_files = {}
|
||||||
|
|
||||||
from cppcheckdata import Location
|
from cppcheckdata import Location
|
||||||
|
|
||||||
|
@ -4478,8 +4482,9 @@ class MisraChecker:
|
||||||
if summary_type == 'MisraInternalIdentifiers':
|
if summary_type == 'MisraInternalIdentifiers':
|
||||||
for s in summary_data:
|
for s in summary_data:
|
||||||
if s['name'] in all_internal_identifiers:
|
if s['name'] in all_internal_identifiers:
|
||||||
self.reportError(Location(s), 5, 9)
|
if not s['inlinefunc'] or s['file'] != all_internal_identifiers[s['name']]['file']:
|
||||||
self.reportError(Location(all_internal_identifiers[s['name']]), 5, 9)
|
self.reportError(Location(s), 5, 9)
|
||||||
|
self.reportError(Location(all_internal_identifiers[s['name']]), 5, 9)
|
||||||
all_internal_identifiers[s['name']] = s
|
all_internal_identifiers[s['name']] = s
|
||||||
|
|
||||||
if summary_type == 'MisraLocalIdentifiers':
|
if summary_type == 'MisraLocalIdentifiers':
|
||||||
|
@ -4488,10 +4493,10 @@ class MisraChecker:
|
||||||
|
|
||||||
if summary_type == 'MisraUsage':
|
if summary_type == 'MisraUsage':
|
||||||
for s in summary_data:
|
for s in summary_data:
|
||||||
if s in all_usage_count:
|
if s['name'] in all_usage_files:
|
||||||
all_usage_count[s] += 1
|
all_usage_files[s['name']].append(s['file'])
|
||||||
else:
|
else:
|
||||||
all_usage_count[s] = 1
|
all_usage_files[s['name']] = [s['file']]
|
||||||
|
|
||||||
for ti in all_typedef_info:
|
for ti in all_typedef_info:
|
||||||
if not ti['used']:
|
if not ti['used']:
|
||||||
|
@ -4518,9 +4523,12 @@ class MisraChecker:
|
||||||
self.reportError(Location(local_identifier), 5, 8)
|
self.reportError(Location(local_identifier), 5, 8)
|
||||||
self.reportError(Location(external_identifier), 5, 8)
|
self.reportError(Location(external_identifier), 5, 8)
|
||||||
|
|
||||||
for name, count in all_usage_count.items():
|
for name, files in all_usage_files.items():
|
||||||
#print('%s:%i' % (name, count))
|
#print('%s:%i' % (name, count))
|
||||||
if count != 1:
|
count = len(files)
|
||||||
|
if count != 1 or name not in all_external_identifiers_def:
|
||||||
|
continue
|
||||||
|
if files[0] != Location(all_external_identifiers_def[name]).file:
|
||||||
continue
|
continue
|
||||||
if name in all_external_identifiers:
|
if name in all_external_identifiers:
|
||||||
self.reportError(Location(all_external_identifiers[name]), 8, 7)
|
self.reportError(Location(all_external_identifiers[name]), 8, 7)
|
||||||
|
@ -4584,6 +4592,8 @@ def main():
|
||||||
settings = MisraSettings(args)
|
settings = MisraSettings(args)
|
||||||
checker = MisraChecker(settings)
|
checker = MisraChecker(settings)
|
||||||
|
|
||||||
|
checker.path_premium_addon = cppcheckdata.get_path_premium_addon()
|
||||||
|
|
||||||
if args.generate_table:
|
if args.generate_table:
|
||||||
generateTable()
|
generateTable()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -4645,6 +4655,13 @@ def main():
|
||||||
|
|
||||||
checker.analyse_ctu_info(ctu_info_files)
|
checker.analyse_ctu_info(ctu_info_files)
|
||||||
|
|
||||||
|
if args.file_list and checker.path_premium_addon:
|
||||||
|
premium_command = [checker.path_premium_addon, '--misra', '--file-list', args.file_list]
|
||||||
|
if args.cli:
|
||||||
|
premium_command.append('--cli')
|
||||||
|
for line in subprocess.check_output(premium_command).decode('ascii').split('\n'):
|
||||||
|
print(line.strip())
|
||||||
|
|
||||||
if settings.verify:
|
if settings.verify:
|
||||||
sys.exit(exitCode)
|
sys.exit(exitCode)
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ if (WIN32 AND NOT BORLAND)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
||||||
target_link_libraries(cppcheck tinyxml2)
|
target_link_libraries(cppcheck ${tinyxml2_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_dependencies(cppcheck copy_cfg)
|
add_dependencies(cppcheck copy_cfg)
|
||||||
|
|
|
@ -46,6 +46,10 @@
|
||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static void addFilesToList(const std::string& fileList, std::vector<std::string>& pathNames)
|
static void addFilesToList(const std::string& fileList, std::vector<std::string>& pathNames)
|
||||||
{
|
{
|
||||||
// To keep things initially simple, if the file can't be opened, just be silent and move on.
|
// To keep things initially simple, if the file can't be opened, just be silent and move on.
|
||||||
|
@ -122,6 +126,14 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
bool maxconfigs = false;
|
bool maxconfigs = false;
|
||||||
|
|
||||||
mSettings->exename = argv[0];
|
mSettings->exename = argv[0];
|
||||||
|
#ifdef __linux__
|
||||||
|
// Executing cppcheck in PATH. argv[0] does not contain the path.
|
||||||
|
if (mSettings->exename.find_first_of("/\\") == std::string::npos) {
|
||||||
|
char buf[PATH_MAX] = {0};
|
||||||
|
if (FileLister::fileExists("/proc/self/exe") && readlink("/proc/self/exe", buf, sizeof(buf)-1) > 0)
|
||||||
|
mSettings->exename = buf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
if (argv[i][0] == '-') {
|
if (argv[i][0] == '-') {
|
||||||
|
@ -882,6 +894,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
else if (std::strcmp(argv[i], "--version") == 0) {
|
else if (std::strcmp(argv[i], "--version") == 0) {
|
||||||
mShowVersion = true;
|
mShowVersion = true;
|
||||||
mExitAfterPrint = true;
|
mExitAfterPrint = true;
|
||||||
|
mSettings->loadCppcheckCfg();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,7 +936,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mSettings->loadCppcheckCfg(argv[0]);
|
mSettings->loadCppcheckCfg();
|
||||||
|
|
||||||
// Default template format..
|
// Default template format..
|
||||||
if (mSettings->templateFormat.empty()) {
|
if (mSettings->templateFormat.empty()) {
|
||||||
|
|
|
@ -109,12 +109,16 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
if (parser.getShowVersion() && !parser.getShowErrorMessages()) {
|
if (parser.getShowVersion() && !parser.getShowErrorMessages()) {
|
||||||
const char * const extraVersion = CppCheck::extraVersion();
|
if (!settings.cppcheckCfgProductName.empty()) {
|
||||||
if (*extraVersion != 0)
|
std::cout << settings.cppcheckCfgProductName << std::endl;
|
||||||
std::cout << "Cppcheck " << CppCheck::version() << " ("
|
} else {
|
||||||
<< extraVersion << ')' << std::endl;
|
const char * const extraVersion = CppCheck::extraVersion();
|
||||||
else
|
if (*extraVersion != 0)
|
||||||
std::cout << "Cppcheck " << CppCheck::version() << std::endl;
|
std::cout << "Cppcheck " << CppCheck::version() << " ("
|
||||||
|
<< extraVersion << ')' << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "Cppcheck " << CppCheck::version() << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser.getShowErrorMessages()) {
|
if (parser.getShowErrorMessages()) {
|
||||||
|
@ -243,9 +247,9 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (cppCheck.settings().exceptionHandling)
|
if (cppCheck.settings().exceptionHandling)
|
||||||
ret = check_wrapper(cppCheck, argc, argv);
|
ret = check_wrapper(cppCheck);
|
||||||
else
|
else
|
||||||
ret = check_internal(cppCheck, argc, argv);
|
ret = check_internal(cppCheck);
|
||||||
|
|
||||||
mSettings = nullptr;
|
mSettings = nullptr;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -821,12 +825,12 @@ namespace {
|
||||||
* TODO Check for multi-threading issues!
|
* TODO Check for multi-threading issues!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int CppCheckExecutor::check_wrapper(CppCheck& cppcheck, int argc, const char* const argv[])
|
int CppCheckExecutor::check_wrapper(CppCheck& cppcheck)
|
||||||
{
|
{
|
||||||
#ifdef USE_WINDOWS_SEH
|
#ifdef USE_WINDOWS_SEH
|
||||||
FILE *outputFile = stdout;
|
FILE *outputFile = stdout;
|
||||||
__try {
|
__try {
|
||||||
return check_internal(cppcheck, argc, argv);
|
return check_internal(cppcheck);
|
||||||
} __except (filterException(GetExceptionCode(), GetExceptionInformation())) {
|
} __except (filterException(GetExceptionCode(), GetExceptionInformation())) {
|
||||||
// reporting to stdout may not be helpful within a GUI application...
|
// reporting to stdout may not be helpful within a GUI application...
|
||||||
fputs("Please report this to the cppcheck developers!\n", outputFile);
|
fputs("Please report this to the cppcheck developers!\n", outputFile);
|
||||||
|
@ -854,23 +858,23 @@ int CppCheckExecutor::check_wrapper(CppCheck& cppcheck, int argc, const char* co
|
||||||
for (std::map<int, std::string>::const_iterator sig=listofsignals.begin(); sig!=listofsignals.end(); ++sig) {
|
for (std::map<int, std::string>::const_iterator sig=listofsignals.begin(); sig!=listofsignals.end(); ++sig) {
|
||||||
sigaction(sig->first, &act, nullptr);
|
sigaction(sig->first, &act, nullptr);
|
||||||
}
|
}
|
||||||
return check_internal(cppcheck, argc, argv);
|
return check_internal(cppcheck);
|
||||||
#else
|
#else
|
||||||
return check_internal(cppcheck, argc, argv);
|
return check_internal(cppcheck);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* That is a method which gets called from check_wrapper
|
* That is a method which gets called from check_wrapper
|
||||||
* */
|
* */
|
||||||
int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const char* const argv[])
|
int CppCheckExecutor::check_internal(CppCheck& cppcheck)
|
||||||
{
|
{
|
||||||
Settings& settings = cppcheck.settings();
|
Settings& settings = cppcheck.settings();
|
||||||
mSettings = &settings;
|
mSettings = &settings;
|
||||||
const bool std = tryLoadLibrary(settings.library, argv[0], "std.cfg");
|
const bool std = tryLoadLibrary(settings.library, settings.exename, "std.cfg");
|
||||||
|
|
||||||
for (const std::string &lib : settings.libraries) {
|
for (const std::string &lib : settings.libraries) {
|
||||||
if (!tryLoadLibrary(settings.library, argv[0], lib.c_str())) {
|
if (!tryLoadLibrary(settings.library, settings.exename, lib.c_str())) {
|
||||||
const std::string msg("Failed to load the library " + lib);
|
const std::string msg("Failed to load the library " + lib);
|
||||||
const std::list<ErrorMessage::FileLocation> callstack;
|
const std::list<ErrorMessage::FileLocation> callstack;
|
||||||
ErrorMessage errmsg(callstack, emptyString, Severity::information, msg, "failedToLoadCfg", Certainty::normal);
|
ErrorMessage errmsg(callstack, emptyString, Severity::information, msg, "failedToLoadCfg", Certainty::normal);
|
||||||
|
@ -879,22 +883,15 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck, int /*argc*/, const cha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool posix = true;
|
if (!std) {
|
||||||
if (settings.posix())
|
|
||||||
posix = tryLoadLibrary(settings.library, argv[0], "posix.cfg");
|
|
||||||
bool windows = true;
|
|
||||||
if (settings.isWindowsPlatform())
|
|
||||||
windows = tryLoadLibrary(settings.library, argv[0], "windows.cfg");
|
|
||||||
|
|
||||||
if (!std || !posix || !windows) {
|
|
||||||
const std::list<ErrorMessage::FileLocation> callstack;
|
const std::list<ErrorMessage::FileLocation> callstack;
|
||||||
const std::string msg("Failed to load " + std::string(!std ? "std.cfg" : !posix ? "posix.cfg" : "windows.cfg") + ". Your Cppcheck installation is broken, please re-install.");
|
const std::string msg("Failed to load std.cfg. Your Cppcheck installation is broken, please re-install.");
|
||||||
#ifdef FILESDIR
|
#ifdef FILESDIR
|
||||||
const std::string details("The Cppcheck binary was compiled with FILESDIR set to \""
|
const std::string details("The Cppcheck binary was compiled with FILESDIR set to \""
|
||||||
FILESDIR "\" and will therefore search for "
|
FILESDIR "\" and will therefore search for "
|
||||||
"std.cfg in " FILESDIR "/cfg.");
|
"std.cfg in " FILESDIR "/cfg.");
|
||||||
#else
|
#else
|
||||||
const std::string cfgfolder(Path::fromNativeSeparators(Path::getPathFromFilename(argv[0])) + "cfg");
|
const std::string cfgfolder(Path::fromNativeSeparators(Path::getPathFromFilename(settings.exename)) + "cfg");
|
||||||
const std::string details("The Cppcheck binary was compiled without FILESDIR set. Either the "
|
const std::string details("The Cppcheck binary was compiled without FILESDIR set. Either the "
|
||||||
"std.cfg should be available in " + cfgfolder + " or the FILESDIR "
|
"std.cfg should be available in " + cfgfolder + " or the FILESDIR "
|
||||||
"should be configured.");
|
"should be configured.");
|
||||||
|
@ -1143,9 +1140,9 @@ FILE* CppCheckExecutor::getExceptionOutput()
|
||||||
return mExceptionOutput;
|
return mExceptionOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppCheckExecutor::tryLoadLibrary(Library& destination, const char* basepath, const char* filename)
|
bool CppCheckExecutor::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename)
|
||||||
{
|
{
|
||||||
const Library::Error err = destination.load(basepath, filename);
|
const Library::Error err = destination.load(basepath.c_str(), filename);
|
||||||
|
|
||||||
if (err.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT)
|
if (err.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT)
|
||||||
std::cout << "cppcheck: Found unknown elements in configuration file '" << filename << "': " << err.reason << std::endl;
|
std::cout << "cppcheck: Found unknown elements in configuration file '" << filename << "': " << err.reason << std::endl;
|
||||||
|
|
|
@ -112,7 +112,7 @@ public:
|
||||||
* Tries to load a library and prints warning/error messages
|
* Tries to load a library and prints warning/error messages
|
||||||
* @return false, if an error occurred (except unknown XML elements)
|
* @return false, if an error occurred (except unknown XML elements)
|
||||||
*/
|
*/
|
||||||
static bool tryLoadLibrary(Library& destination, const char* basepath, const char* filename);
|
static bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a shell command and read the output from it. Returns true if command terminated successfully.
|
* Execute a shell command and read the output from it. Returns true if command terminated successfully.
|
||||||
|
@ -151,24 +151,20 @@ private:
|
||||||
* - installs optional platform dependent signal handling
|
* - installs optional platform dependent signal handling
|
||||||
*
|
*
|
||||||
* @param cppcheck cppcheck instance
|
* @param cppcheck cppcheck instance
|
||||||
* @param argc from main()
|
|
||||||
* @param argv from main()
|
|
||||||
**/
|
**/
|
||||||
int check_wrapper(CppCheck& cppcheck, int argc, const char* const argv[]);
|
int check_wrapper(CppCheck& cppcheck);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the checking.
|
* Starts the checking.
|
||||||
*
|
*
|
||||||
* @param cppcheck cppcheck instance
|
* @param cppcheck cppcheck instance
|
||||||
* @param argc from main()
|
|
||||||
* @param argv from main()
|
|
||||||
* @return EXIT_FAILURE if arguments are invalid or no input files
|
* @return EXIT_FAILURE if arguments are invalid or no input files
|
||||||
* were found.
|
* were found.
|
||||||
* If errors are found and --error-exitcode is used,
|
* If errors are found and --error-exitcode is used,
|
||||||
* given value is returned instead of default 0.
|
* given value is returned instead of default 0.
|
||||||
* If no errors are found, 0 is returned.
|
* If no errors are found, 0 is returned.
|
||||||
*/
|
*/
|
||||||
int check_internal(CppCheck& cppcheck, int argc, const char* const argv[]);
|
int check_internal(CppCheck& cppcheck);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to current settings; set while check() is running.
|
* Pointer to current settings; set while check() is running.
|
||||||
|
|
|
@ -11,11 +11,11 @@ find_program(RUN_CLANG_TIDY NAMES run-clang-tidy run-clang-tidy-13 run-clang-tid
|
||||||
message(STATUS "RUN_CLANG_TIDY=${RUN_CLANG_TIDY}")
|
message(STATUS "RUN_CLANG_TIDY=${RUN_CLANG_TIDY}")
|
||||||
if (RUN_CLANG_TIDY)
|
if (RUN_CLANG_TIDY)
|
||||||
# disable all compiler warnings since we are just interested in the tidy ones
|
# disable all compiler warnings since we are just interested in the tidy ones
|
||||||
add_custom_target(run-clang-tidy ${RUN_CLANG_TIDY} -p=${CMAKE_BINARY_DIR} -j ${NPROC} -extra-arg=-w -quiet)
|
add_custom_target(run-clang-tidy ${RUN_CLANG_TIDY} -checks=-performance-unnecessary-copy-initialization -p=${CMAKE_BINARY_DIR} -j ${NPROC} -extra-arg=-w -quiet)
|
||||||
if (BUILD_GUI)
|
if (BUILD_GUI)
|
||||||
add_dependencies(run-clang-tidy gui-build-deps)
|
add_dependencies(run-clang-tidy gui-build-deps)
|
||||||
if (BUILD_TESTS)
|
if (BUILD_TESTS)
|
||||||
add_dependencies(run-clang-tidy triage-build-ui-deps)
|
add_dependencies(run-clang-tidy triage-build-ui-deps)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -48,12 +48,13 @@ endif()
|
||||||
|
|
||||||
if (NOT USE_BUNDLED_TINYXML2)
|
if (NOT USE_BUNDLED_TINYXML2)
|
||||||
find_package(tinyxml2 QUIET)
|
find_package(tinyxml2 QUIET)
|
||||||
if (NOT tinyxml2_FOUND)
|
if (TARGET tinyxml2::tinyxml2)
|
||||||
find_library(tinyxml2_LIBRARY tinyxml2)
|
set(tinyxml2_LIBRARIES "tinyxml2::tinyxml2")
|
||||||
if (NOT tinyxml2_LIBRARY)
|
else()
|
||||||
|
find_library(tinyxml2_LIBRARIES tinyxml2)
|
||||||
|
if (NOT tinyxml2_LIBRARIES)
|
||||||
message(FATAL_ERROR "tinyxml2 has not been found")
|
message(FATAL_ERROR "tinyxml2 has not been found")
|
||||||
else()
|
else()
|
||||||
message(STATUS "tinyxml2_LIBRARY: ${tinyxml2_LIBRARY}")
|
|
||||||
set(tinyxml2_FOUND 1)
|
set(tinyxml2_FOUND 1)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -52,7 +52,11 @@ if (USE_Z3)
|
||||||
message( STATUS "Z3_LIBRARIES = ${Z3_LIBRARIES}" )
|
message( STATUS "Z3_LIBRARIES = ${Z3_LIBRARIES}" )
|
||||||
message( STATUS "Z3_CXX_INCLUDE_DIRS = ${Z3_CXX_INCLUDE_DIRS}" )
|
message( STATUS "Z3_CXX_INCLUDE_DIRS = ${Z3_CXX_INCLUDE_DIRS}" )
|
||||||
endif()
|
endif()
|
||||||
|
message( STATUS )
|
||||||
message( STATUS "USE_BUNDLED_TINYXML2 = ${USE_BUNDLED_TINYXML2}" )
|
message( STATUS "USE_BUNDLED_TINYXML2 = ${USE_BUNDLED_TINYXML2}" )
|
||||||
|
if (NOT USE_BUNDLED_TINYXML2)
|
||||||
|
message(STATUS "tinyxml2_LIBRARIES = ${tinyxml2_LIBRARIES}")
|
||||||
|
endif()
|
||||||
message( STATUS )
|
message( STATUS )
|
||||||
|
|
||||||
if(${ANALYZE_ADDRESS})
|
if(${ANALYZE_ADDRESS})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Version for libraries CPP
|
# Version for libraries CPP
|
||||||
SET(VERSION "2.7")
|
SET(VERSION "2.7.4")
|
||||||
STRING(REGEX MATCHALL "[0-9]" VERSION_PARTS "${VERSION}")
|
STRING(REGEX MATCHALL "[0-9]" VERSION_PARTS "${VERSION}")
|
||||||
LIST(GET VERSION_PARTS 0 VERSION_MAJOR)
|
LIST(GET VERSION_PARTS 0 VERSION_MAJOR)
|
||||||
LIST(GET VERSION_PARTS 1 VERSION_MINOR)
|
LIST(GET VERSION_PARTS 1 VERSION_MINOR)
|
||||||
|
|
|
@ -36,7 +36,7 @@ if (BUILD_GUI)
|
||||||
target_link_libraries(cppcheck-gui ${Z3_LIBRARIES})
|
target_link_libraries(cppcheck-gui ${Z3_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
||||||
target_link_libraries(cppcheck-gui tinyxml2)
|
target_link_libraries(cppcheck-gui ${tinyxml2_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(cppcheck-gui Qt5::Core Qt5::Gui Qt5::Widgets Qt5::PrintSupport Qt5::Help)
|
target_link_libraries(cppcheck-gui Qt5::Core Qt5::Gui Qt5::Widgets Qt5::PrintSupport Qt5::Help)
|
||||||
if(WITH_QCHART)
|
if(WITH_QCHART)
|
||||||
|
|
|
@ -67,6 +67,13 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) :
|
||||||
mExiting(false),
|
mExiting(false),
|
||||||
mIsLogfileLoaded(false)
|
mIsLogfileLoaded(false)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
Settings tempSettings;
|
||||||
|
tempSettings.loadCppcheckCfg();
|
||||||
|
mCppcheckCfgProductName = QString::fromStdString(tempSettings.cppcheckCfgProductName);
|
||||||
|
mCppcheckCfgAbout = QString::fromStdString(tempSettings.cppcheckCfgAbout);
|
||||||
|
}
|
||||||
|
|
||||||
mUI.setupUi(this);
|
mUI.setupUi(this);
|
||||||
mThread = new ThreadHandler(this);
|
mThread = new ThreadHandler(this);
|
||||||
mThread->setDataDir(getDataDir());
|
mThread->setDataDir(getDataDir());
|
||||||
|
@ -507,8 +514,6 @@ void MainWindow::doAnalyzeFiles(const QStringList &files, const bool checkLibrar
|
||||||
checkSettings.checkLibrary = checkLibrary;
|
checkSettings.checkLibrary = checkLibrary;
|
||||||
checkSettings.checkConfiguration = checkConfiguration;
|
checkSettings.checkConfiguration = checkConfiguration;
|
||||||
|
|
||||||
checkSettings.loadCppcheckCfg(QCoreApplication::applicationFilePath().toStdString());
|
|
||||||
|
|
||||||
if (mProjectFile)
|
if (mProjectFile)
|
||||||
qDebug() << "Checking project file" << mProjectFile->getFilename();
|
qDebug() << "Checking project file" << mProjectFile->getFilename();
|
||||||
|
|
||||||
|
@ -854,15 +859,10 @@ Settings MainWindow::getCppcheckSettings()
|
||||||
result.exename = QCoreApplication::applicationFilePath().toStdString();
|
result.exename = QCoreApplication::applicationFilePath().toStdString();
|
||||||
|
|
||||||
const bool std = tryLoadLibrary(&result.library, "std.cfg");
|
const bool std = tryLoadLibrary(&result.library, "std.cfg");
|
||||||
bool posix = true;
|
if (!std)
|
||||||
if (result.posix())
|
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1. Your Cppcheck installation is broken. You can use --data-dir=<directory> at the command line to specify where this file is located. Please note that --data-dir is supposed to be used by installation scripts and therefore the GUI does not start when it is used, all that happens is that the setting is configured.").arg("std.cfg"));
|
||||||
posix = tryLoadLibrary(&result.library, "posix.cfg");
|
|
||||||
bool windows = true;
|
|
||||||
if (result.isWindowsPlatform())
|
|
||||||
windows = tryLoadLibrary(&result.library, "windows.cfg");
|
|
||||||
|
|
||||||
if (!std || !posix || !windows)
|
result.loadCppcheckCfg();
|
||||||
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1. Your Cppcheck installation is broken. You can use --data-dir=<directory> at the command line to specify where this file is located. Please note that --data-dir is supposed to be used by installation scripts and therefore the GUI does not start when it is used, all that happens is that the setting is configured.").arg(!std ? "std.cfg" : !posix ? "posix.cfg" : "windows.cfg"));
|
|
||||||
|
|
||||||
// If project file loaded, read settings from it
|
// If project file loaded, read settings from it
|
||||||
if (mProjectFile) {
|
if (mProjectFile) {
|
||||||
|
@ -1356,8 +1356,18 @@ void MainWindow::toggleAllChecked(bool checked)
|
||||||
|
|
||||||
void MainWindow::about()
|
void MainWindow::about()
|
||||||
{
|
{
|
||||||
AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), this);
|
if (!mCppcheckCfgAbout.isEmpty()) {
|
||||||
dlg->exec();
|
QMessageBox msg(QMessageBox::Information,
|
||||||
|
tr("About"),
|
||||||
|
mCppcheckCfgAbout,
|
||||||
|
QMessageBox::Ok,
|
||||||
|
this);
|
||||||
|
msg.exec();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), this);
|
||||||
|
dlg->exec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showLicense()
|
void MainWindow::showLicense()
|
||||||
|
@ -1445,6 +1455,9 @@ void MainWindow::formatAndSetTitle(const QString &text)
|
||||||
nameWithVersion += " (" + extraVersion + ")";
|
nameWithVersion += " (" + extraVersion + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mCppcheckCfgProductName.isEmpty())
|
||||||
|
nameWithVersion = mCppcheckCfgProductName;
|
||||||
|
|
||||||
QString title;
|
QString title;
|
||||||
if (text.isEmpty())
|
if (text.isEmpty())
|
||||||
title = nameWithVersion;
|
title = nameWithVersion;
|
||||||
|
|
|
@ -472,6 +472,9 @@ private:
|
||||||
* List of MRU menu actions. Needs also to store the separator.
|
* List of MRU menu actions. Needs also to store the separator.
|
||||||
*/
|
*/
|
||||||
QAction *mRecentProjectActs[MaxRecentProjects + 1];
|
QAction *mRecentProjectActs[MaxRecentProjects + 1];
|
||||||
|
|
||||||
|
QString mCppcheckCfgAbout;
|
||||||
|
QString mCppcheckCfgProductName;
|
||||||
};
|
};
|
||||||
/// @}
|
/// @}
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
|
|
@ -337,9 +337,6 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile)
|
||||||
if (!mUI.mAddonMisra->isEnabled()) {
|
if (!mUI.mAddonMisra->isEnabled()) {
|
||||||
mUI.mEditMisraFile->setEnabled(false);
|
mUI.mEditMisraFile->setEnabled(false);
|
||||||
mUI.mBtnBrowseMisraFile->setEnabled(false);
|
mUI.mBtnBrowseMisraFile->setEnabled(false);
|
||||||
} else if (misraFile.isEmpty()) {
|
|
||||||
mUI.mAddonMisra->setEnabled(false);
|
|
||||||
mUI.mAddonMisra->setText(mUI.mAddonMisra->text() + ' ' + tr("(no rule texts file)"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mUI.mToolClangAnalyzer->setChecked(projectFile->getClangAnalyzer());
|
mUI.mToolClangAnalyzer->setChecked(projectFile->getClangAnalyzer());
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
qt5_wrap_cpp(test-benchmark-simple_SRC benchmarksimple.h)
|
qt5_wrap_cpp(test-benchmark-simple_SRC benchmarksimple.h)
|
||||||
add_custom_target(build-testbenchmark-simple-deps SOURCES ${test-benchmark-simple_SRC})
|
add_custom_target(build-testbenchmark-simple-deps SOURCES ${test-benchmark-simple_SRC})
|
||||||
add_dependencies(gui-build-deps build-testbenchmark-simple-deps)
|
add_dependencies(gui-build-deps build-testbenchmark-simple-deps)
|
||||||
|
if(USE_BUNDLED_TINYXML2)
|
||||||
|
list(APPEND test-benchmark-simple_SRC $<TARGET_OBJECTS:tinyxml2_objs>)
|
||||||
|
endif()
|
||||||
add_executable(benchmark-simple
|
add_executable(benchmark-simple
|
||||||
${test-benchmark-simple_SRC}
|
${test-benchmark-simple_SRC}
|
||||||
benchmarksimple.cpp
|
benchmarksimple.cpp
|
||||||
$<TARGET_OBJECTS:lib_objs>
|
$<TARGET_OBJECTS:lib_objs>
|
||||||
$<TARGET_OBJECTS:tinyxml2_objs>
|
|
||||||
$<TARGET_OBJECTS:simplecpp_objs>
|
$<TARGET_OBJECTS:simplecpp_objs>
|
||||||
)
|
)
|
||||||
target_include_directories(benchmark-simple PRIVATE ${CMAKE_SOURCE_DIR}/lib)
|
target_include_directories(benchmark-simple PRIVATE ${CMAKE_SOURCE_DIR}/lib)
|
||||||
|
@ -16,4 +18,7 @@ if (HAVE_RULES)
|
||||||
endif()
|
endif()
|
||||||
if (USE_Z3)
|
if (USE_Z3)
|
||||||
target_link_libraries(benchmark-simple ${Z3_LIBRARIES})
|
target_link_libraries(benchmark-simple ${Z3_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
||||||
|
target_link_libraries(benchmark-simple ${tinyxml2_LIBRARIES})
|
||||||
endif()
|
endif()
|
|
@ -22,4 +22,7 @@ if (HAVE_RULES)
|
||||||
endif()
|
endif()
|
||||||
if (USE_Z3)
|
if (USE_Z3)
|
||||||
target_link_libraries(test-xmlreportv2 ${Z3_LIBRARIES})
|
target_link_libraries(test-xmlreportv2 ${Z3_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
||||||
|
target_link_libraries(test-xmlreportv2 ${tinyxml2_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
|
@ -147,22 +147,21 @@ static bool simplifyPathWithVariables(std::string &s, std::map<std::string, std:
|
||||||
|
|
||||||
void ImportProject::FileSettings::setIncludePaths(const std::string &basepath, const std::list<std::string> &in, std::map<std::string, std::string, cppcheck::stricmp> &variables)
|
void ImportProject::FileSettings::setIncludePaths(const std::string &basepath, const std::list<std::string> &in, std::map<std::string, std::string, cppcheck::stricmp> &variables)
|
||||||
{
|
{
|
||||||
std::list<std::string> listInc;
|
std::set<std::string> found;
|
||||||
// only parse each includePath once - so remove duplicates
|
const std::list<std::string> copyIn(in);
|
||||||
std::list<std::string> uniqueIncludePaths = in;
|
includePaths.clear();
|
||||||
uniqueIncludePaths.sort();
|
for (const std::string &ipath : copyIn) {
|
||||||
uniqueIncludePaths.unique();
|
if (ipath.empty())
|
||||||
|
|
||||||
for (const std::string &it : uniqueIncludePaths) {
|
|
||||||
if (it.empty())
|
|
||||||
continue;
|
continue;
|
||||||
if (it.compare(0,2,"%(")==0)
|
if (ipath.compare(0,2,"%(")==0)
|
||||||
|
continue;
|
||||||
|
std::string s(Path::fromNativeSeparators(ipath));
|
||||||
|
if (!found.insert(s).second)
|
||||||
continue;
|
continue;
|
||||||
std::string s(Path::fromNativeSeparators(it));
|
|
||||||
if (s[0] == '/' || (s.size() > 1U && s.compare(1,2,":/") == 0)) {
|
if (s[0] == '/' || (s.size() > 1U && s.compare(1,2,":/") == 0)) {
|
||||||
if (!endsWith(s,'/'))
|
if (!endsWith(s,'/'))
|
||||||
s += '/';
|
s += '/';
|
||||||
listInc.push_back(s);
|
includePaths.push_back(s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,9 +176,8 @@ void ImportProject::FileSettings::setIncludePaths(const std::string &basepath, c
|
||||||
}
|
}
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
continue;
|
continue;
|
||||||
listInc.push_back(s + '/');
|
includePaths.push_back(s + '/');
|
||||||
}
|
}
|
||||||
includePaths.swap(listInc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportProject::Type ImportProject::import(const std::string &filename, Settings *settings)
|
ImportProject::Type ImportProject::import(const std::string &filename, Settings *settings)
|
||||||
|
@ -409,28 +407,38 @@ bool ImportProject::importCompileCommands(std::istream &istr)
|
||||||
|
|
||||||
const std::string directory = dirpath;
|
const std::string directory = dirpath;
|
||||||
|
|
||||||
std::ostringstream comm;
|
std::string command;
|
||||||
if (obj.find("arguments") != obj.end()) {
|
if (obj.count("arguments")) {
|
||||||
if (obj["arguments"].is<picojson::array>()) {
|
if (obj["arguments"].is<picojson::array>()) {
|
||||||
for (const picojson::value& arg : obj["arguments"].get<picojson::array>()) {
|
for (const picojson::value& arg : obj["arguments"].get<picojson::array>()) {
|
||||||
if (arg.is<std::string>()) {
|
if (arg.is<std::string>()) {
|
||||||
comm << arg.get<std::string>() << " ";
|
std::string str = arg.get<std::string>();
|
||||||
|
if (str.find(" ") != std::string::npos && str.find("=\"") > str.find(" "))
|
||||||
|
str = "\"" + str + "\"";
|
||||||
|
command += str + " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printError("'arguments' field in compilation database entry is not a JSON array");
|
printError("'arguments' field in compilation database entry is not a JSON array");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (obj.find("command") != obj.end()) {
|
} else if (obj.count("command")) {
|
||||||
if (obj["command"].is<std::string>()) {
|
if (obj["command"].is<std::string>()) {
|
||||||
comm << obj["command"].get<std::string>();
|
command = obj["command"].get<std::string>();
|
||||||
|
} else {
|
||||||
|
printError("'command' field in compilation database entry is not a string");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printError("no 'arguments' or 'command' field found in compilation database entry");
|
printError("no 'arguments' or 'command' field found in compilation database entry");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string command = comm.str();
|
if (!obj.count("file") || !obj["file"].is<std::string>()) {
|
||||||
|
printError("skip compilation database entry because it does not have a proper 'file' field");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string file = Path::fromNativeSeparators(obj["file"].get<std::string>());
|
const std::string file = Path::fromNativeSeparators(obj["file"].get<std::string>());
|
||||||
|
|
||||||
// Accept file?
|
// Accept file?
|
||||||
|
@ -466,15 +474,17 @@ bool ImportProject::importSln(std::istream &istr, const std::string &path, const
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
// skip magic word
|
|
||||||
if (!std::getline(istr,line)) {
|
if (!std::getline(istr,line)) {
|
||||||
printError("Visual Studio solution file is empty");
|
printError("Visual Studio solution file is empty");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::getline(istr, line) || line.find("Microsoft Visual Studio Solution File") != 0) {
|
if (line.find("Microsoft Visual Studio Solution File") != 0) {
|
||||||
printError("Visual Studio solution file header not found");
|
// Skip BOM
|
||||||
return false;
|
if (!std::getline(istr, line) || line.find("Microsoft Visual Studio Solution File") != 0) {
|
||||||
|
printError("Visual Studio solution file header not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string,std::string,cppcheck::stricmp> variables;
|
std::map<std::string,std::string,cppcheck::stricmp> variables;
|
||||||
|
|
|
@ -76,9 +76,9 @@ Settings::Settings()
|
||||||
certainty.setEnabled(Certainty::normal, true);
|
certainty.setEnabled(Certainty::normal, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::loadCppcheckCfg(const std::string &executable)
|
void Settings::loadCppcheckCfg()
|
||||||
{
|
{
|
||||||
std::string fileName = Path::getPathFromFilename(executable) + "cppcheck.cfg";
|
std::string fileName = Path::getPathFromFilename(exename) + "cppcheck.cfg";
|
||||||
#ifdef FILESDIR
|
#ifdef FILESDIR
|
||||||
if (Path::fileExists(FILESDIR "/cppcheck.cfg"))
|
if (Path::fileExists(FILESDIR "/cppcheck.cfg"))
|
||||||
fileName = FILESDIR "/cppcheck.cfg";
|
fileName = FILESDIR "/cppcheck.cfg";
|
||||||
|
@ -92,6 +92,10 @@ void Settings::loadCppcheckCfg(const std::string &executable)
|
||||||
if (!picojson::get_last_error().empty())
|
if (!picojson::get_last_error().empty())
|
||||||
return;
|
return;
|
||||||
picojson::object obj = json.get<picojson::object>();
|
picojson::object obj = json.get<picojson::object>();
|
||||||
|
if (obj.count("productName") && obj["productName"].is<std::string>())
|
||||||
|
cppcheckCfgProductName = obj["productName"].get<std::string>();
|
||||||
|
if (obj.count("about") && obj["about"].is<std::string>())
|
||||||
|
cppcheckCfgAbout = obj["about"].get<std::string>();
|
||||||
if (obj.count("addons") && obj["addons"].is<picojson::array>()) {
|
if (obj.count("addons") && obj["addons"].is<picojson::array>()) {
|
||||||
for (const picojson::value &v : obj["addons"].get<picojson::array>()) {
|
for (const picojson::value &v : obj["addons"].get<picojson::array>()) {
|
||||||
const std::string &s = v.get<std::string>();
|
const std::string &s = v.get<std::string>();
|
||||||
|
|
|
@ -97,7 +97,7 @@ private:
|
||||||
public:
|
public:
|
||||||
Settings();
|
Settings();
|
||||||
|
|
||||||
void loadCppcheckCfg(const std::string &executable);
|
void loadCppcheckCfg();
|
||||||
|
|
||||||
/** @brief addons, either filename of python/json file or json data */
|
/** @brief addons, either filename of python/json file or json data */
|
||||||
std::list<std::string> addons;
|
std::list<std::string> addons;
|
||||||
|
@ -156,6 +156,12 @@ public:
|
||||||
/** @brief include paths excluded from checking the configuration */
|
/** @brief include paths excluded from checking the configuration */
|
||||||
std::set<std::string> configExcludePaths;
|
std::set<std::string> configExcludePaths;
|
||||||
|
|
||||||
|
/** cppcheck.cfg: Custom product name */
|
||||||
|
std::string cppcheckCfgProductName;
|
||||||
|
|
||||||
|
/** cppcheck.cfg: About text */
|
||||||
|
std::string cppcheckCfgAbout;
|
||||||
|
|
||||||
/** @brief Are we running from DACA script? */
|
/** @brief Are we running from DACA script? */
|
||||||
bool daca;
|
bool daca;
|
||||||
|
|
||||||
|
|
|
@ -4945,6 +4945,8 @@ static void valueFlowForwardAssign(Token* const tok,
|
||||||
|
|
||||||
// Skip RHS
|
// Skip RHS
|
||||||
const Token * nextExpression = tok->astParent() ? nextAfterAstRightmostLeaf(tok->astParent()) : tok->next();
|
const Token * nextExpression = tok->astParent() ? nextAfterAstRightmostLeaf(tok->astParent()) : tok->next();
|
||||||
|
if (!nextExpression)
|
||||||
|
return;
|
||||||
|
|
||||||
for (ValueFlow::Value& value : values) {
|
for (ValueFlow::Value& value : values) {
|
||||||
if (value.isSymbolicValue())
|
if (value.isSymbolicValue())
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
#define STRINGIFY(x) STRING(x)
|
#define STRINGIFY(x) STRING(x)
|
||||||
#define STRING(VER) #VER
|
#define STRING(VER) #VER
|
||||||
#if CPPCHECK_MINOR == CPPCHECK_DEVMINOR
|
#if CPPCHECK_MINOR == CPPCHECK_DEVMINOR
|
||||||
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR) "." STRINGIFY(CPPCHECK_DEVMINOR)
|
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR) "." STRINGIFY(CPPCHECK_DEVMINOR) ".4"
|
||||||
#define CPPCHECK_VERSION CPPCHECK_MAJOR,CPPCHECK_MINOR,0,0
|
#define CPPCHECK_VERSION CPPCHECK_MAJOR,CPPCHECK_MINOR,4,0
|
||||||
#else
|
#else
|
||||||
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR) "." STRINGIFY(CPPCHECK_DEVMINOR) " dev"
|
#define CPPCHECK_VERSION_STRING STRINGIFY(CPPCHECK_MAJOR) "." STRINGIFY(CPPCHECK_DEVMINOR) " dev"
|
||||||
#define CPPCHECK_VERSION CPPCHECK_MAJOR,CPPCHECK_MINOR,99,0
|
#define CPPCHECK_VERSION CPPCHECK_MAJOR,CPPCHECK_MINOR,99,0
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
if (ENABLE_OSS_FUZZ AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if (ENABLE_OSS_FUZZ AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
add_executable(fuzz-client EXCLUDE_FROM_ALL
|
set(fuzz-client_SRC
|
||||||
main.cpp
|
main.cpp
|
||||||
type2.cpp
|
type2.cpp
|
||||||
|
)
|
||||||
|
if(USE_BUNDLED_TINYXML2)
|
||||||
|
list(APPEND fuzz-client_SRC $<TARGET_OBJECTS:tinyxml2_objs>)
|
||||||
|
endif()
|
||||||
|
add_executable(fuzz-client EXCLUDE_FROM_ALL
|
||||||
|
${fuzz-client_SRC}
|
||||||
$<TARGET_OBJECTS:simplecpp_objs>
|
$<TARGET_OBJECTS:simplecpp_objs>
|
||||||
$<TARGET_OBJECTS:tinyxml2_objs>
|
|
||||||
$<TARGET_OBJECTS:lib_objs>)
|
$<TARGET_OBJECTS:lib_objs>)
|
||||||
target_include_directories(fuzz-client PRIVATE ${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/externals/simplecpp ${CMAKE_SOURCE_DIR}/externals/tinyxml2 ${CMAKE_SOURCE_DIR}/externals)
|
target_include_directories(fuzz-client PRIVATE ${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/externals/simplecpp ${CMAKE_SOURCE_DIR}/externals)
|
||||||
|
if(USE_BUNDLED_TINYXML2)
|
||||||
|
target_include_directories(fuzz-client PRIVATE ${CMAKE_SOURCE_DIR}/externals/tinyxml2/)
|
||||||
|
endif()
|
||||||
target_compile_options(fuzz-client PRIVATE -fsanitize=fuzzer)
|
target_compile_options(fuzz-client PRIVATE -fsanitize=fuzzer)
|
||||||
# TODO: target_link_options() requires CMake >= 3.13
|
# TODO: target_link_options() requires CMake >= 3.13
|
||||||
#target_link_options(fuzz-client PRIVATE -fsanitize=fuzzer)
|
#target_link_options(fuzz-client PRIVATE -fsanitize=fuzzer)
|
||||||
|
@ -16,6 +24,9 @@ if (ENABLE_OSS_FUZZ AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
if (USE_Z3)
|
if (USE_Z3)
|
||||||
target_link_libraries(fuzz-client PRIVATE ${Z3_LIBRARIES})
|
target_link_libraries(fuzz-client PRIVATE ${Z3_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
||||||
|
target_link_libraries(fuzz-client PRIVATE ${tinyxml2_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(translate EXCLUDE_FROM_ALL
|
add_executable(translate EXCLUDE_FROM_ALL
|
||||||
translate.cpp
|
translate.cpp
|
||||||
|
|
|
@ -26,7 +26,7 @@ if (BUILD_TESTS)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
if(tinyxml2_FOUND AND NOT USE_BUNDLED_TINYXML2)
|
||||||
target_link_libraries(testrunner tinyxml2)
|
target_link_libraries(testrunner ${tinyxml2_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS)
|
if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS)
|
||||||
|
|
|
@ -70,9 +70,9 @@ ${CPPCHECK} ${CPPCHECK_OPT} --inconclusive ${DIR}std.cpp
|
||||||
# windows.cpp
|
# windows.cpp
|
||||||
# Syntax check via g++ does not work because it can not find a valid windows.h
|
# Syntax check via g++ does not work because it can not find a valid windows.h
|
||||||
#${CXX} ${CXX_OPT} ${DIR}windows.cpp
|
#${CXX} ${CXX_OPT} ${DIR}windows.cpp
|
||||||
${CPPCHECK} ${CPPCHECK_OPT} --inconclusive --platform=win32A ${DIR}windows.cpp
|
${CPPCHECK} ${CPPCHECK_OPT} --inconclusive --platform=win32A --library=windows ${DIR}windows.cpp
|
||||||
${CPPCHECK} ${CPPCHECK_OPT} --inconclusive --platform=win32W ${DIR}windows.cpp
|
${CPPCHECK} ${CPPCHECK_OPT} --inconclusive --platform=win32W --library=windows ${DIR}windows.cpp
|
||||||
${CPPCHECK} ${CPPCHECK_OPT} --inconclusive --platform=win64 ${DIR}windows.cpp
|
${CPPCHECK} ${CPPCHECK_OPT} --inconclusive --platform=win64 --library=windows ${DIR}windows.cpp
|
||||||
|
|
||||||
# wxwidgets.cpp
|
# wxwidgets.cpp
|
||||||
set +e
|
set +e
|
||||||
|
|
|
@ -58,6 +58,10 @@ private:
|
||||||
TEST_CASE(importCompileCommands6); // Windows/CMake/Ninja generated comile_commands.json with spaces
|
TEST_CASE(importCompileCommands6); // Windows/CMake/Ninja generated comile_commands.json with spaces
|
||||||
TEST_CASE(importCompileCommands7); // linux: "/home/danielm/cppcheck 2"
|
TEST_CASE(importCompileCommands7); // linux: "/home/danielm/cppcheck 2"
|
||||||
TEST_CASE(importCompileCommands8); // Windows: "C:\Users\danielm\cppcheck"
|
TEST_CASE(importCompileCommands8); // Windows: "C:\Users\danielm\cppcheck"
|
||||||
|
TEST_CASE(importCompileCommands9);
|
||||||
|
TEST_CASE(importCompileCommands10); // #10887: include path with space
|
||||||
|
TEST_CASE(importCompileCommands11); // include path order
|
||||||
|
TEST_CASE(importCompileCommands12); // defines
|
||||||
TEST_CASE(importCompileCommandsArgumentsSection); // Handle arguments section
|
TEST_CASE(importCompileCommandsArgumentsSection); // Handle arguments section
|
||||||
TEST_CASE(importCompileCommandsNoCommandSection); // gracefully handles malformed json
|
TEST_CASE(importCompileCommandsNoCommandSection); // gracefully handles malformed json
|
||||||
TEST_CASE(importCppcheckGuiProject);
|
TEST_CASE(importCppcheckGuiProject);
|
||||||
|
@ -209,7 +213,8 @@ private:
|
||||||
TestImporter importer;
|
TestImporter importer;
|
||||||
importer.importCompileCommands(istr);
|
importer.importCompileCommands(istr);
|
||||||
ASSERT_EQUALS(2, importer.fileSettings.size());
|
ASSERT_EQUALS(2, importer.fileSettings.size());
|
||||||
ASSERT_EQUALS("C:/Users/dan/git/test-cppcheck/mylib/second src/", importer.fileSettings.begin()->includePaths.front());
|
ASSERT_EQUALS("C:/Users/dan/git/test-cppcheck/mylib/src/", importer.fileSettings.begin()->includePaths.front());
|
||||||
|
ASSERT_EQUALS("C:/Users/dan/git/test-cppcheck/mylib/second src/", importer.fileSettings.begin()->includePaths.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -243,12 +248,85 @@ private:
|
||||||
}])";
|
}])";
|
||||||
std::istringstream istr(json);
|
std::istringstream istr(json);
|
||||||
TestImporter importer;
|
TestImporter importer;
|
||||||
|
importer.importCompileCommands(istr); // Do not crash
|
||||||
|
}
|
||||||
|
|
||||||
|
void importCompileCommands9() const {
|
||||||
|
// IAR output (https://sourceforge.net/p/cppcheck/discussion/general/thread/608af51e0a/)
|
||||||
|
const char json[] =
|
||||||
|
R"([{
|
||||||
|
"arguments" : [
|
||||||
|
"powershell.exe -WindowStyle Hidden -NoProfile -ExecutionPolicy Bypass -File d:\\Projekte\\xyz\\firmware\\app\\xyz-lib\\build.ps1 -IAR -COMPILER_PATH \"c:\\Program Files (x86)\\IAR Systems\\Embedded Workbench 9.0\" -CONTROLLER CC1310F128 -LIB LIB_PERMANENT -COMPILER_DEFINES \"CC1310_HFXO_FREQ=24000000 DEBUG\""
|
||||||
|
],
|
||||||
|
"directory" : "d:\\Projekte\\xyz\\firmware\\app",
|
||||||
|
"type" : "PRE",
|
||||||
|
"file": "1.c"
|
||||||
|
}])";
|
||||||
|
std::istringstream istr(json);
|
||||||
|
TestImporter importer;
|
||||||
importer.importCompileCommands(istr);
|
importer.importCompileCommands(istr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void importCompileCommands10() const { // #10887
|
||||||
|
const char json[] =
|
||||||
|
R"([{
|
||||||
|
"file": "/home/danielm/cppcheck/1/test folder/1.c" ,
|
||||||
|
"directory": "",
|
||||||
|
"arguments": [
|
||||||
|
"iccavr.exe",
|
||||||
|
"-I",
|
||||||
|
"/home/danielm/cppcheck/test folder"
|
||||||
|
]
|
||||||
|
}])";
|
||||||
|
std::istringstream istr(json);
|
||||||
|
TestImporter importer;
|
||||||
|
ASSERT_EQUALS(true, importer.importCompileCommands(istr));
|
||||||
ASSERT_EQUALS(1, importer.fileSettings.size());
|
ASSERT_EQUALS(1, importer.fileSettings.size());
|
||||||
ASSERT_EQUALS("FILESDIR=\"C:\\Program Files\\Cppcheck\"", importer.fileSettings.begin()->defines);
|
const ImportProject::FileSettings &fs = importer.fileSettings.front();
|
||||||
ASSERT_EQUALS(2, importer.fileSettings.begin()->includePaths.size());
|
ASSERT_EQUALS("/home/danielm/cppcheck/test folder/", fs.includePaths.front());
|
||||||
ASSERT_EQUALS("C:/Users/danielm/cppcheck/build/lib/", importer.fileSettings.begin()->includePaths.front());
|
}
|
||||||
ASSERT_EQUALS("C:/Users/danielm/cppcheck/lib/", importer.fileSettings.begin()->includePaths.back());
|
|
||||||
|
void importCompileCommands11() const { // include path order
|
||||||
|
const char json[] =
|
||||||
|
R"([{
|
||||||
|
"file": "1.c" ,
|
||||||
|
"directory": "/x",
|
||||||
|
"arguments": [
|
||||||
|
"cc",
|
||||||
|
"-I",
|
||||||
|
"def",
|
||||||
|
"-I",
|
||||||
|
"abc"
|
||||||
|
]
|
||||||
|
}])";
|
||||||
|
std::istringstream istr(json);
|
||||||
|
TestImporter importer;
|
||||||
|
ASSERT_EQUALS(true, importer.importCompileCommands(istr));
|
||||||
|
ASSERT_EQUALS(1, importer.fileSettings.size());
|
||||||
|
const ImportProject::FileSettings &fs = importer.fileSettings.front();
|
||||||
|
ASSERT_EQUALS("/x/def/", fs.includePaths.front());
|
||||||
|
ASSERT_EQUALS("/x/abc/", fs.includePaths.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
void importCompileCommands12() const { // define
|
||||||
|
const char json[] =
|
||||||
|
R"([{
|
||||||
|
"file": "1.c" ,
|
||||||
|
"directory": "/x",
|
||||||
|
"arguments": [
|
||||||
|
"cc",
|
||||||
|
"-D",
|
||||||
|
"X=1",
|
||||||
|
"-D",
|
||||||
|
"__VERSION__=\"IAR C/C++ Compiler V6.40.2.748 for Atmel AVR\""
|
||||||
|
]
|
||||||
|
}])";
|
||||||
|
std::istringstream istr(json);
|
||||||
|
TestImporter importer;
|
||||||
|
ASSERT_EQUALS(true, importer.importCompileCommands(istr));
|
||||||
|
ASSERT_EQUALS(1, importer.fileSettings.size());
|
||||||
|
const ImportProject::FileSettings &fs = importer.fileSettings.front();
|
||||||
|
ASSERT_EQUALS("X=1;__VERSION__=IAR C/C++ Compiler V6.40.2.748 for Atmel AVR", fs.defines);
|
||||||
}
|
}
|
||||||
|
|
||||||
void importCompileCommandsArgumentsSection() const {
|
void importCompileCommandsArgumentsSection() const {
|
||||||
|
|
|
@ -6259,6 +6259,13 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"};\n";
|
"};\n";
|
||||||
valueOfTok(code, "f.c");
|
valueOfTok(code, "f.c");
|
||||||
|
|
||||||
|
code = "int f(int value) { return 0; }\n"
|
||||||
|
"std::shared_ptr<Manager> g() {\n"
|
||||||
|
" static const std::shared_ptr<Manager> x{ new M{} };\n"
|
||||||
|
" return x;\n"
|
||||||
|
"}\n";
|
||||||
|
valueOfTok(code, "x");
|
||||||
}
|
}
|
||||||
|
|
||||||
void valueFlowHang() {
|
void valueFlowHang() {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Include>
|
<Include>
|
||||||
<?define ProductName = "Cppcheck $(var.Platform) 2.7" ?>
|
<?define ProductName = "Cppcheck $(var.Platform) 2.7.4" ?>
|
||||||
<?define ProductNameShort = "Cppcheck" ?>
|
<?define ProductNameShort = "Cppcheck" ?>
|
||||||
<?define ProductVersion = "2.7" ?>
|
<?define ProductVersion = "2.7.4" ?>
|
||||||
|
|
||||||
<?define ProductManufacturer = "The Cppcheck team" ?>
|
<?define ProductManufacturer = "The Cppcheck team" ?>
|
||||||
<?define ProductDescription = "Cppcheck is a tool for static analysis of C/C++ code" ?>
|
<?define ProductDescription = "Cppcheck is a tool for static analysis of C/C++ code" ?>
|
||||||
|
|
Loading…
Reference in New Issue