1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-09 19:43:27 +02:00

Refactored common function to utility class

This commit is contained in:
Alena Laskavaia 2010-05-13 02:06:38 +00:00
parent 4f2aa8c7db
commit 94cb067beb
2 changed files with 71 additions and 22 deletions

View file

@ -11,37 +11,41 @@
package org.eclipse.cdt.codan.internal.checkers; package org.eclipse.cdt.codan.internal.checkers;
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.model.AbstractIndexAstChecker; import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
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;
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.IASTPointer;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement; 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". * 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. * For one thing, this avoids copying and potentially slicing the exception.
* *
*/ */
public class CatchByReference extends AbstractIndexAstChecker { public class CatchByReference extends AbstractIndexAstChecker {
public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.CatchByReference"; public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.CatchByReference"; //$NON-NLS-1$
public void processAst(IASTTranslationUnit ast) { public void processAst(IASTTranslationUnit ast) {
// traverse the ast using the visitor pattern. // traverse the ast using the visitor pattern.
ast.accept(new OnCatch()); ast.accept(new OnCatch());
} }
class OnCatch extends ASTVisitor { class OnCatch extends ASTVisitor {
OnCatch() { OnCatch() {
shouldVisitStatements = true; shouldVisitStatements = true;
@ -51,26 +55,26 @@ public class CatchByReference extends AbstractIndexAstChecker {
if (stmt instanceof ICPPASTTryBlockStatement) { if (stmt instanceof ICPPASTTryBlockStatement) {
try { try {
ICPPASTTryBlockStatement tblock = (ICPPASTTryBlockStatement) stmt; ICPPASTTryBlockStatement tblock = (ICPPASTTryBlockStatement) stmt;
ICPPASTCatchHandler[] catchHandlers = tblock.getCatchHandlers(); ICPPASTCatchHandler[] catchHandlers = tblock
next: for (int i = 0; i < catchHandlers.length; i++) { .getCatchHandlers();
for (int i = 0; i < catchHandlers.length; i++) {
ICPPASTCatchHandler catchHandler = catchHandlers[i]; ICPPASTCatchHandler catchHandler = catchHandlers[i];
IASTDeclaration decl = catchHandler.getDeclaration(); IASTDeclaration decl = catchHandler.getDeclaration();
if (decl instanceof IASTSimpleDeclaration) { if (decl instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) decl; IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) decl;
IASTDeclSpecifier spec = sdecl.getDeclSpecifier(); IASTDeclSpecifier spec = sdecl.getDeclSpecifier();
if (!usesReference(catchHandler)) { if (!usesReference(catchHandler)) {
if (spec instanceof ICPPASTNamedTypeSpecifier) { if (spec instanceof IASTNamedTypeSpecifier) {
IBinding typeName = ((ICPPASTNamedTypeSpecifier) spec).getName().getBinding(); IASTName tname = ((IASTNamedTypeSpecifier) spec)
// unwind typedef chain .getName();
while (typeName instanceof ITypedef) { IType typeName = (IType) tname
IType t = ((ITypedef) typeName).getType(); .resolveBinding();
if (t instanceof IBasicType) typeName = CxxAstUtils.getInstance()
continue next; .unwindTypedef(typeName);
if (t instanceof IBinding) if (typeName instanceof IBasicType
typeName = (IBinding) t; || typeName instanceof IPointerType
else || typeName == null)
break; continue;
}
reportProblem(ER_ID, decl); reportProblem(ER_ID, decl);
} }
} }
@ -86,16 +90,19 @@ public class CatchByReference extends AbstractIndexAstChecker {
/** /**
* If it uses reference or ponter * If it uses reference or ponter
*
* @param catchHandler * @param catchHandler
* @return * @return
*/ */
private boolean usesReference(ICPPASTCatchHandler catchHandler) { private boolean usesReference(ICPPASTCatchHandler catchHandler) {
IASTDeclaration declaration = catchHandler.getDeclaration(); IASTDeclaration declaration = catchHandler.getDeclaration();
if (declaration instanceof IASTSimpleDeclaration) { if (declaration instanceof IASTSimpleDeclaration) {
IASTDeclarator[] declarators = ((IASTSimpleDeclaration) declaration).getDeclarators(); IASTDeclarator[] declarators = ((IASTSimpleDeclaration) declaration)
.getDeclarators();
for (int i = 0; i < declarators.length; i++) { for (int i = 0; i < declarators.length; i++) {
IASTDeclarator d = declarators[i]; IASTDeclarator d = declarators[i];
IASTPointerOperator[] pointerOperators = d.getPointerOperators(); IASTPointerOperator[] pointerOperators = d
.getPointerOperators();
for (int j = 0; j < pointerOperators.length; j++) { for (int j = 0; j < pointerOperators.length; j++) {
IASTPointerOperator po = pointerOperators[j]; IASTPointerOperator po = pointerOperators[j];
if (po instanceof ICPPASTReferenceOperator) { if (po instanceof ICPPASTReferenceOperator) {

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* 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.core.cxx;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
/**
* Useful functions for doing code analysis on c/c++ AST
*/
public final class CxxAstUtils {
private static CxxAstUtils instance;
private CxxAstUtils(){
// private constructor
}
public synchronized static CxxAstUtils getInstance(){
if (instance==null) instance = new CxxAstUtils();
return instance;
}
public IType unwindTypedef(IType type) {
if (!(type instanceof IBinding)) return type;
IBinding typeName = (IBinding) type;
// unwind typedef chain
while (typeName instanceof ITypedef) {
IType t = ((ITypedef) typeName).getType();
if (t instanceof IBinding)
typeName = (IBinding) t;
else
return t;
}
return (IType)typeName;
}
}