1
0
Fork 0
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:
Marc-Andre Laperle 2018-09-22 00:46:25 -04:00 committed by Marc-André Laperle
parent 8492296d24
commit efbda46cba
2 changed files with 47 additions and 8 deletions

View file

@ -13,10 +13,12 @@ package org.eclipse.cdt.codan.internal.checkers;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.cdt.codan.checkers.CodanCheckersActivator; import org.eclipse.cdt.codan.checkers.CodanCheckersActivator;
import org.eclipse.cdt.codan.core.cxx.CxxAstUtils; 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.codan.core.param.ListProblemPreference;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration; 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.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; 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 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_MACRO_ID = "macro"; //$NON-NLS-1$
public static final String PARAM_EXCEPT_ARG_LIST = "exceptions"; //$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> externFunctionDeclarations = new HashMap<IBinding, IASTDeclarator>();
private Map<IBinding, IASTDeclarator> staticFunctionDeclarations = 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> staticFunctionDefinitions = new HashMap<IBinding, IASTDeclarator>();
private Map<IBinding, IASTDeclarator> externVariableDeclarations = new HashMap<IBinding, IASTDeclarator>(); private Map<IBinding, IASTDeclarator> externVariableDeclarations = new HashMap<IBinding, IASTDeclarator>();
private Map<IBinding, IASTDeclarator> staticVariableDeclarations = new HashMap<IBinding, IASTDeclarator>(); private Map<IBinding, IASTDeclarator> staticVariableDeclarations = new HashMap<IBinding, IASTDeclarator>();
private Set<IBinding> declarationsWithUsageAttributes = new HashSet<>();
private IProblemWorkingCopy unusedVariableProblem = null; private IProblemWorkingCopy unusedVariableProblem = null;
@Override @Override
@ -118,6 +125,7 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
filterOutUsedElements(ast); filterOutUsedElements(ast);
reportProblems(); reportProblems();
} }
declarationsWithUsageAttributes.clear();
} }
private void collectCandidates(IASTTranslationUnit ast) { private void collectCandidates(IASTTranslationUnit ast) {
@ -134,16 +142,15 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) element; IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) element;
IASTDeclSpecifier declSpec = simpleDeclaration.getDeclSpecifier(); IASTDeclSpecifier declSpec = simpleDeclaration.getDeclSpecifier();
if (AttributeUtil.hasAttribute(declSpec, ATTRIBUTE_UNUSED)) { boolean hasUsageAttrib = hasUsageAttribute(declSpec);
return PROCESS_SKIP;
}
IASTDeclarator[] declarators = simpleDeclaration.getDeclarators(); IASTDeclarator[] declarators = simpleDeclaration.getDeclarators();
for (IASTDeclarator decl : declarators) { for (IASTDeclarator decl : declarators) {
if (AttributeUtil.hasAttribute(decl, ATTRIBUTE_UNUSED))
continue;
IASTName astName = decl.getName(); IASTName astName = decl.getName();
if (astName != null) { if (astName != null) {
IBinding binding = astName.resolveBinding(); IBinding binding = astName.resolveBinding();
if (hasUsageAttrib || hasUsageAttribute(decl)) {
declarationsWithUsageAttributes.add(binding);
}
int storageClass = simpleDeclaration.getDeclSpecifier().getStorageClass(); int storageClass = simpleDeclaration.getDeclSpecifier().getStorageClass();
if (binding instanceof IFunction) { if (binding instanceof IFunction) {
@ -206,10 +213,12 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
IASTName astName = declarator.getName(); IASTName astName = declarator.getName();
if (astName != null) { if (astName != null) {
IBinding binding = astName.resolveBinding(); IBinding binding = astName.resolveBinding();
if (hasUsageAttribute(definition.getDeclSpecifier())) {
declarationsWithUsageAttributes.add(binding);
}
if (definition.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_static && if (definition.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_static &&
!(astName instanceof ICPPASTQualifiedName) && !(astName instanceof ICPPASTQualifiedName)) {
!AttributeUtil.hasAttribute(declarator, ATTRIBUTE_UNUSED)) {
staticFunctionDefinitions.put(binding, declarator); staticFunctionDefinitions.put(binding, declarator);
} }
@ -222,6 +231,9 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
return PROCESS_SKIP; return PROCESS_SKIP;
} }
private boolean hasUsageAttribute(IASTAttributeOwner attributeOwner) {
return AttributeUtil.hasAttribute(attributeOwner, USAGE_ATTRIBUTES);
}
}); });
} catch (Exception e) { } catch (Exception e) {
CodanCheckersActivator.log(e); CodanCheckersActivator.log(e);
@ -283,6 +295,14 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
staticVariableDeclarations.remove(binding); staticVariableDeclarations.remove(binding);
} }
if (declarationsWithUsageAttributes.contains(binding)) {
staticFunctionDeclarations.remove(binding);
externFunctionDeclarations.remove(binding);
staticFunctionDefinitions.remove(binding);
externVariableDeclarations.remove(binding);
staticVariableDeclarations.remove(binding);
}
if (!isAnyCandidate()) if (!isAnyCandidate())
return PROCESS_ABORT; return PROCESS_ABORT;

View file

@ -315,9 +315,16 @@ public class UnusedSymbolInFileScopeCheckerTest extends CheckerTestCase {
// int f1() __attribute__((__unused__)); // int f1() __attribute__((__unused__));
// extern int f2() __attribute__((unused)); // extern int f2() __attribute__((unused));
// static void f3() __attribute__((unused)); // static void f3() __attribute__((unused));
// void f3() {}
// static void f4() __attribute__((unused)); // static void f4() __attribute__((unused));
// static void f4() __attribute__((unused)) {} // static void f4() __attribute__((unused)) {}
// static void __attribute__((unused)) f5(); // 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 { public void testAttributeUnused() throws Exception {
loadCodeAndRunC(getAboveComment()); loadCodeAndRunC(getAboveComment());
checkNoErrors(); checkNoErrors();
@ -326,6 +333,18 @@ public class UnusedSymbolInFileScopeCheckerTest extends CheckerTestCase {
checkNoErrors(); 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; // extern int* pxCurrentTCB;
// //
// int main() { // int main() {