diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/UnusedSymbolInFileScopeChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/UnusedSymbolInFileScopeChecker.java index ebb2fca2dbc..607a1e6f63e 100644 --- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/UnusedSymbolInFileScopeChecker.java +++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/UnusedSymbolInFileScopeChecker.java @@ -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 externFunctionDeclarations = new HashMap(); private Map staticFunctionDeclarations = new HashMap(); private Map staticFunctionDefinitions = new HashMap(); private Map externVariableDeclarations = new HashMap(); private Map staticVariableDeclarations = new HashMap(); + private Set 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; diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java index 693c06435f5..270a66a7283 100644 --- a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java @@ -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() {