From 94cb067beb7f8bb204499b0a7e36592967961304 Mon Sep 17 00:00:00 2001 From: Alena Laskavaia Date: Thu, 13 May 2010 02:06:38 +0000 Subject: [PATCH] Refactored common function to utility class --- .../internal/checkers/CatchByReference.java | 51 +++++++++++-------- .../cdt/codan/core/cxx/CxxAstUtils.java | 42 +++++++++++++++ 2 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtils.java diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java index c149fa70762..ac9e852f85d 100644 --- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java +++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java @@ -11,37 +11,41 @@ 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.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.IBinding; +import org.eclipse.cdt.core.dom.ast.IPointerType; 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.ICPPASTNamedTypeSpecifier; 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". + * 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"; + public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.CatchByReference"; //$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; @@ -51,26 +55,26 @@ public class CatchByReference extends AbstractIndexAstChecker { if (stmt instanceof ICPPASTTryBlockStatement) { try { ICPPASTTryBlockStatement tblock = (ICPPASTTryBlockStatement) stmt; - ICPPASTCatchHandler[] catchHandlers = tblock.getCatchHandlers(); - next: for (int i = 0; i < catchHandlers.length; i++) { + 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 ICPPASTNamedTypeSpecifier) { - IBinding typeName = ((ICPPASTNamedTypeSpecifier) spec).getName().getBinding(); - // unwind typedef chain - while (typeName instanceof ITypedef) { - IType t = ((ITypedef) typeName).getType(); - if (t instanceof IBasicType) - continue next; - if (t instanceof IBinding) - typeName = (IBinding) t; - else - break; - } + 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; reportProblem(ER_ID, decl); } } @@ -86,16 +90,19 @@ public class CatchByReference extends AbstractIndexAstChecker { /** * 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(); + IASTDeclarator[] declarators = ((IASTSimpleDeclaration) declaration) + .getDeclarators(); for (int i = 0; i < declarators.length; i++) { IASTDeclarator d = declarators[i]; - IASTPointerOperator[] pointerOperators = d.getPointerOperators(); + IASTPointerOperator[] pointerOperators = d + .getPointerOperators(); for (int j = 0; j < pointerOperators.length; j++) { IASTPointerOperator po = pointerOperators[j]; if (po instanceof ICPPASTReferenceOperator) { diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtils.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtils.java new file mode 100644 index 00000000000..11670790826 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtils.java @@ -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; + } +}