mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 389577 - False positive "Unused static function"
Add handling of constructor/destructor attributes and some improvement when functions were previously declared but not defined as used. Change-Id: I7537bc87c6c4bc5b294d8e15fe5b42c92b3f2974 Signed-off-by: Marc-Andre Laperle <malaperle@gmail.com>
This commit is contained in:
parent
8492296d24
commit
efbda46cba
2 changed files with 47 additions and 8 deletions
|
@ -13,10 +13,12 @@ package org.eclipse.cdt.codan.internal.checkers;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.codan.checkers.CodanCheckersActivator;
|
||||
import org.eclipse.cdt.codan.core.cxx.CxxAstUtils;
|
||||
|
@ -26,6 +28,7 @@ import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
|
|||
import org.eclipse.cdt.codan.core.param.ListProblemPreference;
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
|
@ -62,13 +65,17 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
|
|||
public static final String ER_UNUSED_STATIC_FUNCTION_ID = "org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem"; //$NON-NLS-1$
|
||||
public static final String PARAM_MACRO_ID = "macro"; //$NON-NLS-1$
|
||||
public static final String PARAM_EXCEPT_ARG_LIST = "exceptions"; //$NON-NLS-1$
|
||||
private static final String[] ATTRIBUTE_UNUSED = new String[] { "__unused__", "unused" }; //$NON-NLS-1$//$NON-NLS-2$
|
||||
/*
|
||||
* Various attributes that when present for a symbol should make it considered as used.
|
||||
*/
|
||||
private static final String[] USAGE_ATTRIBUTES = new String[] { "__unused__", "unused", "constructor", "destructor" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
|
||||
|
||||
private Map<IBinding, IASTDeclarator> externFunctionDeclarations = new HashMap<IBinding, IASTDeclarator>();
|
||||
private Map<IBinding, IASTDeclarator> staticFunctionDeclarations = new HashMap<IBinding, IASTDeclarator>();
|
||||
private Map<IBinding, IASTDeclarator> staticFunctionDefinitions = new HashMap<IBinding, IASTDeclarator>();
|
||||
private Map<IBinding, IASTDeclarator> externVariableDeclarations = new HashMap<IBinding, IASTDeclarator>();
|
||||
private Map<IBinding, IASTDeclarator> staticVariableDeclarations = new HashMap<IBinding, IASTDeclarator>();
|
||||
private Set<IBinding> declarationsWithUsageAttributes = new HashSet<>();
|
||||
private IProblemWorkingCopy unusedVariableProblem = null;
|
||||
|
||||
@Override
|
||||
|
@ -118,6 +125,7 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
|
|||
filterOutUsedElements(ast);
|
||||
reportProblems();
|
||||
}
|
||||
declarationsWithUsageAttributes.clear();
|
||||
}
|
||||
|
||||
private void collectCandidates(IASTTranslationUnit ast) {
|
||||
|
@ -134,16 +142,15 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
|
|||
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) element;
|
||||
|
||||
IASTDeclSpecifier declSpec = simpleDeclaration.getDeclSpecifier();
|
||||
if (AttributeUtil.hasAttribute(declSpec, ATTRIBUTE_UNUSED)) {
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
boolean hasUsageAttrib = hasUsageAttribute(declSpec);
|
||||
IASTDeclarator[] declarators = simpleDeclaration.getDeclarators();
|
||||
for (IASTDeclarator decl : declarators) {
|
||||
if (AttributeUtil.hasAttribute(decl, ATTRIBUTE_UNUSED))
|
||||
continue;
|
||||
IASTName astName = decl.getName();
|
||||
if (astName != null) {
|
||||
IBinding binding = astName.resolveBinding();
|
||||
if (hasUsageAttrib || hasUsageAttribute(decl)) {
|
||||
declarationsWithUsageAttributes.add(binding);
|
||||
}
|
||||
int storageClass = simpleDeclaration.getDeclSpecifier().getStorageClass();
|
||||
|
||||
if (binding instanceof IFunction) {
|
||||
|
@ -206,10 +213,12 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
|
|||
IASTName astName = declarator.getName();
|
||||
if (astName != null) {
|
||||
IBinding binding = astName.resolveBinding();
|
||||
if (hasUsageAttribute(definition.getDeclSpecifier())) {
|
||||
declarationsWithUsageAttributes.add(binding);
|
||||
}
|
||||
|
||||
if (definition.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_static &&
|
||||
!(astName instanceof ICPPASTQualifiedName) &&
|
||||
!AttributeUtil.hasAttribute(declarator, ATTRIBUTE_UNUSED)) {
|
||||
!(astName instanceof ICPPASTQualifiedName)) {
|
||||
staticFunctionDefinitions.put(binding, declarator);
|
||||
}
|
||||
|
||||
|
@ -222,6 +231,9 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
|
|||
return PROCESS_SKIP;
|
||||
}
|
||||
|
||||
private boolean hasUsageAttribute(IASTAttributeOwner attributeOwner) {
|
||||
return AttributeUtil.hasAttribute(attributeOwner, USAGE_ATTRIBUTES);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
CodanCheckersActivator.log(e);
|
||||
|
@ -283,6 +295,14 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
|
|||
staticVariableDeclarations.remove(binding);
|
||||
}
|
||||
|
||||
if (declarationsWithUsageAttributes.contains(binding)) {
|
||||
staticFunctionDeclarations.remove(binding);
|
||||
externFunctionDeclarations.remove(binding);
|
||||
staticFunctionDefinitions.remove(binding);
|
||||
externVariableDeclarations.remove(binding);
|
||||
staticVariableDeclarations.remove(binding);
|
||||
}
|
||||
|
||||
if (!isAnyCandidate())
|
||||
return PROCESS_ABORT;
|
||||
|
||||
|
|
|
@ -315,9 +315,16 @@ public class UnusedSymbolInFileScopeCheckerTest extends CheckerTestCase {
|
|||
// int f1() __attribute__((__unused__));
|
||||
// extern int f2() __attribute__((unused));
|
||||
// static void f3() __attribute__((unused));
|
||||
// void f3() {}
|
||||
// static void f4() __attribute__((unused));
|
||||
// static void f4() __attribute__((unused)) {}
|
||||
// static void __attribute__((unused)) f5();
|
||||
// static void f6() __attribute__((unused));
|
||||
// static void f6() {}
|
||||
// static void __attribute__((unused)) f7();
|
||||
// void f7() {}
|
||||
// static void __attribute__((unused)) f8();
|
||||
// static void f8() {}
|
||||
public void testAttributeUnused() throws Exception {
|
||||
loadCodeAndRunC(getAboveComment());
|
||||
checkNoErrors();
|
||||
|
@ -326,6 +333,18 @@ public class UnusedSymbolInFileScopeCheckerTest extends CheckerTestCase {
|
|||
checkNoErrors();
|
||||
}
|
||||
|
||||
// static void __attribute__((constructor)) Ctor() {}
|
||||
// static void __attribute__((destructor)) Dtor();
|
||||
// static void Dtor2() __attribute__((destructor));
|
||||
// static void Dtor3() __attribute__((destructor));
|
||||
// static void Dtor() {}
|
||||
// static void Dtor2() {}
|
||||
// void Dtor3() {}
|
||||
public void testAttributeConstructorDestructor_bug389577() throws Exception {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// extern int* pxCurrentTCB;
|
||||
//
|
||||
// int main() {
|
||||
|
|
Loading…
Add table
Reference in a new issue