diff options
author | Elliott Baron <ebaron@fedoraproject.org> | 2010-06-26 22:27:34 -0400 |
---|---|---|
committer | Elliott Baron <ebaron@fedoraproject.org> | 2010-06-26 22:27:34 -0400 |
commit | 4e112eca7750a4f530c986be55c178c43c16d3ea (patch) | |
tree | db140c4fe4db9945502398e4869707ca0346353e /org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java | |
parent | aa73b3f2503808e4b4029a73368a75b258d6f0dc (diff) | |
download | codan-master.tar.gz codan-master.tar.xz codan-master.zip |
* org.eclipse.cdt.codan.checkers.ui: Updated.
* org.eclipse.cdt.codan.checkers: Updated.
* org.eclipse.cdt.codan.core: Updated.
* org.eclipse.cdt.codan.ui: Updated.
* org.eclipse.cdt.codan.core.cxx: Added.
* org.eclipse.cdt.codan.extension/META-INF/MANIFEST.MF: Import org.eclipse.cdt.codan.core.cxx.model.
* org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/AbstractPropSimChecker.java: Superclass moved.
Diffstat (limited to 'org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java')
-rw-r--r-- | org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java new file mode 100644 index 0000000..6f0afc8 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Alena Laskavaia + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers; + +import org.eclipse.cdt.codan.checkers.CodanCheckersActivator; +import org.eclipse.cdt.codan.core.cxx.CxxAstUtils; +import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker; +import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTPointer; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBasicType; +import org.eclipse.cdt.core.dom.ast.IPointerType; +import org.eclipse.cdt.core.dom.ast.IProblemBinding; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement; + +/** + * Catching by reference is recommended by C++ experts, for example Herb + * Sutter/Andrei Alexandresscu "C++ Coding Standards", Rule 73 + * "Throw by value, catch by reference". + * For one thing, this avoids copying and potentially slicing the exception. + * + */ +public class CatchByReference extends AbstractIndexAstChecker { + public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.CatchByReference"; //$NON-NLS-1$ + public static final String PARAM_EXCEPT_ARG_LIST = "exceptions"; //$NON-NLS-1$ + public static final String PARAM_UNKNOWN_TYPE = "unknown"; //$NON-NLS-1$ + + public void processAst(IASTTranslationUnit ast) { + // traverse the ast using the visitor pattern. + ast.accept(new OnCatch()); + } + + class OnCatch extends ASTVisitor { + OnCatch() { + shouldVisitStatements = true; + } + + public int visit(IASTStatement stmt) { + if (stmt instanceof ICPPASTTryBlockStatement) { + try { + ICPPASTTryBlockStatement tblock = (ICPPASTTryBlockStatement) stmt; + ICPPASTCatchHandler[] catchHandlers = tblock + .getCatchHandlers(); + for (int i = 0; i < catchHandlers.length; i++) { + ICPPASTCatchHandler catchHandler = catchHandlers[i]; + IASTDeclaration decl = catchHandler.getDeclaration(); + if (decl instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) decl; + IASTDeclSpecifier spec = sdecl.getDeclSpecifier(); + if (!usesReference(catchHandler)) { + if (spec instanceof IASTNamedTypeSpecifier) { + IASTName tname = ((IASTNamedTypeSpecifier) spec) + .getName(); + IType typeName = (IType) tname + .resolveBinding(); + typeName = CxxAstUtils.getInstance() + .unwindTypedef(typeName); + if (typeName instanceof IBasicType + || typeName instanceof IPointerType + || typeName == null) + continue; + if (typeName instanceof IProblemBinding && !shouldReportForUnknownType()) + continue; + String arg = spec.getRawSignature(); + if (!isFilteredArg(arg)) { + reportProblem(ER_ID, decl, arg); + } + } + } + } + } + } catch (Exception e) { + CodanCheckersActivator.log(e); + } + return PROCESS_SKIP; + } + return PROCESS_CONTINUE; + } + + /** + * If it uses reference or ponter + * + * @param catchHandler + * @return + */ + private boolean usesReference(ICPPASTCatchHandler catchHandler) { + IASTDeclaration declaration = catchHandler.getDeclaration(); + if (declaration instanceof IASTSimpleDeclaration) { + IASTDeclarator[] declarators = ((IASTSimpleDeclaration) declaration) + .getDeclarators(); + for (int i = 0; i < declarators.length; i++) { + IASTDeclarator d = declarators[i]; + IASTPointerOperator[] pointerOperators = d + .getPointerOperators(); + for (int j = 0; j < pointerOperators.length; j++) { + IASTPointerOperator po = pointerOperators[j]; + if (po instanceof ICPPASTReferenceOperator) { + return true; + } + if (po instanceof IASTPointer) { + return true; + } + } + } + } + return false; + } + } + + @Override + public void initPreferences(IProblemWorkingCopy problem) { + super.initPreferences(problem); + addPreference(problem, PARAM_UNKNOWN_TYPE, + CheckersMessages.CatchByReference_ReportForUnknownType, Boolean.FALSE); + addListPreference(problem, PARAM_EXCEPT_ARG_LIST, + CheckersMessages.GenericParameter_ParameterExceptions, + CheckersMessages.GenericParameter_ParameterExceptionsItem); + } + + public boolean isFilteredArg(String arg) { + Object[] arr = (Object[]) getPreference( + getProblemById(ER_ID, getFile()), PARAM_EXCEPT_ARG_LIST); + for (int i = 0; i < arr.length; i++) { + String str = (String) arr[i]; + if (arg.equals(str)) + return true; + } + return false; + } + + /** + * @return + */ + public boolean shouldReportForUnknownType() { + return (Boolean) getPreference(getProblemById(ER_ID, getFile()), + PARAM_UNKNOWN_TYPE); + } +} |