mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Merge branch 'master' into sd90
This commit is contained in:
commit
5e5f1a61f7
6 changed files with 145 additions and 200 deletions
|
@ -8,13 +8,12 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Alena Laskavaia - initial API and implementation
|
* Alena Laskavaia - initial API and implementation
|
||||||
* Patrick Hofer [bug 315528]
|
* Patrick Hofer [bug 315528]
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
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.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.DOMException;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
@ -33,183 +32,85 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
|
||||||
* @author Alena Laskavaia
|
* @author Alena Laskavaia
|
||||||
*/
|
*/
|
||||||
public class NonVirtualDestructor extends AbstractIndexAstChecker {
|
public class NonVirtualDestructor extends AbstractIndexAstChecker {
|
||||||
public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem"; //$NON-NLS-1$
|
public static final String PROBLEM_ID = "org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem"; //$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 OnEachClass());
|
ast.accept(new OnEachClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnEachClass extends ASTVisitor {
|
private static ICPPMethod getDestructor(ICPPClassType classType) {
|
||||||
private IASTName className;
|
for (ICPPMethod method : classType.getDeclaredMethods()) {
|
||||||
private IBinding virtualMethod;
|
if (method.isDestructor()) {
|
||||||
private IBinding destructor;
|
return method;
|
||||||
private IASTDeclSpecifier warningLocation;
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasVirtualDestructor(ICPPClassType classType) {
|
||||||
|
ICPPMethod destructor = getDestructor(classType);
|
||||||
|
if (destructor != null && destructor.isVirtual()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ICPPBase[] bases = classType.getBases();
|
||||||
|
for (ICPPBase base : bases) {
|
||||||
|
IBinding baseClass = base.getBaseClass();
|
||||||
|
if (baseClass instanceof ICPPClassType) {
|
||||||
|
if (hasVirtualDestructor((ICPPClassType) baseClass)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OnEachClass extends ASTVisitor {
|
||||||
OnEachClass() {
|
OnEachClass() {
|
||||||
shouldVisitDeclSpecifiers = true;
|
shouldVisitDeclSpecifiers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int visit(IASTDeclSpecifier decl) {
|
public int visit(IASTDeclSpecifier decl) {
|
||||||
if (isClassDecl(decl)) {
|
if (decl instanceof ICPPASTCompositeTypeSpecifier) {
|
||||||
try {
|
ICPPASTCompositeTypeSpecifier spec = (ICPPASTCompositeTypeSpecifier) decl;
|
||||||
boolean err = hasErrorCondition(decl);
|
IASTName className = spec.getName();
|
||||||
if (err) {
|
IBinding binding = className.resolveBinding();
|
||||||
String clazz = className.toString();
|
if (!(binding instanceof ICPPClassType)) {
|
||||||
String method = virtualMethod.getName();
|
return PROCESS_SKIP;
|
||||||
IASTNode node = decl;
|
|
||||||
if (destructor != null) {
|
|
||||||
if (destructor instanceof ICPPInternalBinding) {
|
|
||||||
IASTNode[] decls = ((ICPPInternalBinding) destructor).getDeclarations();
|
|
||||||
if (warningLocation == null) {
|
|
||||||
if (decls != null && decls.length > 0)
|
|
||||||
node = decls[0];
|
|
||||||
} else {
|
|
||||||
node = warningLocation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reportProblem(ER_ID, node, clazz, method);
|
|
||||||
}
|
|
||||||
} catch (DOMException e) {
|
|
||||||
// Ignore, not an error.
|
|
||||||
} catch (Exception e) {
|
|
||||||
CodanCheckersActivator.log(e);
|
|
||||||
}
|
}
|
||||||
|
ICPPClassType classType = (ICPPClassType) binding;
|
||||||
|
if (hasVirtualDestructor(classType)) {
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
ICPPMethod virtualMethod = null;
|
||||||
|
for (ICPPMethod method : classType.getAllDeclaredMethods()) {
|
||||||
|
if (!method.isDestructor() && method.isVirtual()) {
|
||||||
|
virtualMethod = method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (virtualMethod == null) {
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
ICPPMethod destructor = getDestructor(classType);
|
||||||
|
if (destructor != null &&
|
||||||
|
destructor.getVisibility() != ICPPASTVisibilityLabel.v_public &&
|
||||||
|
classType.getFriends().length == 0) {
|
||||||
|
// No error if the destructor is protected or private and there are no friends.
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
IASTNode node = decl;
|
||||||
|
if (destructor instanceof ICPPInternalBinding) {
|
||||||
|
IASTNode[] decls = ((ICPPInternalBinding) destructor).getDeclarations();
|
||||||
|
if (decls != null && decls.length > 0) {
|
||||||
|
node = decls[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reportProblem(PROBLEM_ID, node, className.getSimpleID().toString(),
|
||||||
|
virtualMethod.getName());
|
||||||
return PROCESS_SKIP;
|
return PROCESS_SKIP;
|
||||||
}
|
}
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param decl
|
|
||||||
* @throws DOMException
|
|
||||||
*/
|
|
||||||
private boolean hasErrorCondition(IASTDeclSpecifier decl) throws DOMException {
|
|
||||||
ICPPASTCompositeTypeSpecifier spec = (ICPPASTCompositeTypeSpecifier) decl;
|
|
||||||
className = spec.getName();
|
|
||||||
IBinding binding = className.resolveBinding();
|
|
||||||
if ((binding instanceof ICPPClassType) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ICPPClassType classType = (ICPPClassType) binding;
|
|
||||||
virtualMethod = null;
|
|
||||||
destructor = null;
|
|
||||||
warningLocation = null;
|
|
||||||
// Check for the following conditions:
|
|
||||||
// class has own virtual method and own non-virtual destructor
|
|
||||||
// class has own virtual method and base non-virtual destructor
|
|
||||||
// class has base virtual method and own non-virtual destructor
|
|
||||||
ICPPMethod[] declaredMethods = classType.getDeclaredMethods();
|
|
||||||
boolean hasOwnVirtualMethod = false;
|
|
||||||
boolean hasOwnNonVirtualDestructor = false; // implicit destructor
|
|
||||||
boolean hasDestructor = false;
|
|
||||||
boolean hasVirtualMethod = false;
|
|
||||||
for (ICPPMethod method : declaredMethods) {
|
|
||||||
if (method.isPureVirtual()) {
|
|
||||||
// Class has at least one pure virtual method, it is abstract and cannot be instantiated.
|
|
||||||
return false;
|
|
||||||
} else if (method.isVirtual() && !method.isDestructor()) {
|
|
||||||
hasOwnVirtualMethod = true;
|
|
||||||
virtualMethod = method;
|
|
||||||
}
|
|
||||||
if (method.isDestructor()) {
|
|
||||||
hasDestructor = true;
|
|
||||||
if (!method.isVirtual()) {
|
|
||||||
hasOwnNonVirtualDestructor = true;
|
|
||||||
destructor = method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
boolean hasVirtualDestructor = false;
|
|
||||||
// Class has own virtual method and own non-virtual destructor.
|
|
||||||
if (hasOwnVirtualMethod && hasOwnNonVirtualDestructor) {
|
|
||||||
if (classType.getFriends().length == 0) {
|
|
||||||
if (destructor instanceof ICPPMethod) {
|
|
||||||
// Check visibility of dtor. No error if it is protected or private.
|
|
||||||
if (((ICPPMethod) destructor).getVisibility() != ICPPASTVisibilityLabel.v_public) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if one of its base classes has a virtual destructor.
|
|
||||||
return !hasVirtualDtorInBaseClass(classType);
|
|
||||||
}
|
|
||||||
// Destructor can be called from a class declared as friend.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Class has virtual methods and implicit public destructor.
|
|
||||||
if (hasOwnVirtualMethod && !hasDestructor && classType.getBases().length == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Class does not have virtual methods but has virtual destructor
|
|
||||||
// - not an error
|
|
||||||
if (!hasOwnVirtualMethod && hasDestructor && !hasOwnNonVirtualDestructor) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Check inherited methods
|
|
||||||
ICPPMethod[] allDeclaredMethods = classType.getAllDeclaredMethods();
|
|
||||||
for (ICPPMethod method : allDeclaredMethods) {
|
|
||||||
if (method.isVirtual() && !method.isDestructor()) {
|
|
||||||
hasVirtualMethod = true;
|
|
||||||
if (virtualMethod == null)
|
|
||||||
virtualMethod = method;
|
|
||||||
}
|
|
||||||
if (method.isDestructor()) {
|
|
||||||
hasDestructor = true;
|
|
||||||
if (method.isVirtual()) {
|
|
||||||
hasVirtualDestructor = true;
|
|
||||||
} else if (destructor == null) {
|
|
||||||
destructor = method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hasOwnVirtualMethod) {
|
|
||||||
// Class has own virtual method and base non-virtual destructor.
|
|
||||||
if (hasDestructor && !hasVirtualDestructor) {
|
|
||||||
boolean noVirtualDtorInBase = !hasVirtualDtorInBaseClass(classType);
|
|
||||||
if (noVirtualDtorInBase) {
|
|
||||||
warningLocation = decl;
|
|
||||||
}
|
|
||||||
return noVirtualDtorInBase;
|
|
||||||
}
|
|
||||||
} else if (hasVirtualMethod) {
|
|
||||||
// Class has base virtual method and own non-virtual destructor.
|
|
||||||
if (hasOwnNonVirtualDestructor) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
boolean noVirtualDtorInBase = !hasVirtualDtorInBaseClass(classType);
|
|
||||||
if (noVirtualDtorInBase) {
|
|
||||||
warningLocation = decl;
|
|
||||||
}
|
|
||||||
return noVirtualDtorInBase;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasVirtualDtorInBaseClass(ICPPClassType classType) {
|
|
||||||
ICPPBase[] bases = classType.getBases();
|
|
||||||
for (ICPPBase base : bases) {
|
|
||||||
if (!(base.getBaseClass() instanceof ICPPClassType)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ICPPClassType testedBaseClass = (ICPPClassType) base.getBaseClass();
|
|
||||||
ICPPMethod[] declaredBaseMethods = testedBaseClass.getDeclaredMethods();
|
|
||||||
for (ICPPMethod method : declaredBaseMethods) {
|
|
||||||
if (method.isPureVirtual()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (method.isDestructor() && method.isVirtual()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hasVirtualDtorInBaseClass(testedBaseClass))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isClassDecl(IASTDeclSpecifier decl) {
|
|
||||||
return decl instanceof ICPPASTCompositeTypeSpecifier;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Patrick Hofer - Initial API and implementation
|
* Patrick Hofer - Initial API and implementation
|
||||||
|
* Tomasz Wesolowski
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.codan.core.internal.checkers;
|
package org.eclipse.cdt.codan.core.internal.checkers;
|
||||||
|
|
||||||
|
@ -14,7 +16,7 @@ import org.eclipse.cdt.codan.core.test.CheckerTestCase;
|
||||||
import org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructor;
|
import org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@see NonVirtualDestructor} class.
|
* Test for {@link NonVirtualDestructor} class.
|
||||||
*/
|
*/
|
||||||
public class NonVirtualDestructorCheckerTest extends CheckerTestCase {
|
public class NonVirtualDestructorCheckerTest extends CheckerTestCase {
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,7 +27,7 @@ public class NonVirtualDestructorCheckerTest extends CheckerTestCase {
|
||||||
@Override
|
@Override
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
enableProblems(NonVirtualDestructor.ER_ID);
|
enableProblems(NonVirtualDestructor.PROBLEM_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct A {
|
// struct A {
|
||||||
|
@ -86,7 +88,7 @@ public class NonVirtualDestructorCheckerTest extends CheckerTestCase {
|
||||||
// struct B {
|
// struct B {
|
||||||
// ~B(); // ok.
|
// ~B(); // ok.
|
||||||
// };
|
// };
|
||||||
public void testVirtualDtorInBaseClass() {
|
public void testVirtualDtorInBaseClass1() {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkNoErrors();
|
checkNoErrors();
|
||||||
}
|
}
|
||||||
|
@ -108,6 +110,22 @@ public class NonVirtualDestructorCheckerTest extends CheckerTestCase {
|
||||||
checkNoErrors();
|
checkNoErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// virtual ~A();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// class B : public A {
|
||||||
|
// public:
|
||||||
|
// ~B();
|
||||||
|
// virtual void m();
|
||||||
|
// friend class C;
|
||||||
|
// };
|
||||||
|
public void testVirtualDtorInBaseClass3() {
|
||||||
|
loadCodeAndRun(getAboveComment());
|
||||||
|
checkNoErrors();
|
||||||
|
}
|
||||||
|
|
||||||
// struct A {
|
// struct A {
|
||||||
// virtual void f() { };
|
// virtual void f() { };
|
||||||
// ~A(); // warn! public non-virtual dtor.
|
// ~A(); // warn! public non-virtual dtor.
|
||||||
|
@ -122,14 +140,12 @@ public class NonVirtualDestructorCheckerTest extends CheckerTestCase {
|
||||||
//
|
//
|
||||||
// struct E : public D {
|
// struct E : public D {
|
||||||
// };
|
// };
|
||||||
public void testNonVirtualDtorInBaseClass2() {
|
public void testNonVirtualDtorInBaseClass() {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkErrorLines(3, 7, 11, 13);
|
checkErrorLines(3, 7, 11, 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
// class A { // OK. Do _not_ warn here.
|
// class A {
|
||||||
// // A is an abstract class because it has one pure virtual method.
|
|
||||||
// // A cannot be instantiated.
|
|
||||||
// virtual void f1() { };
|
// virtual void f1() { };
|
||||||
// virtual void f2() = 0;
|
// virtual void f2() = 0;
|
||||||
// };
|
// };
|
||||||
|
@ -141,6 +157,28 @@ public class NonVirtualDestructorCheckerTest extends CheckerTestCase {
|
||||||
// };
|
// };
|
||||||
public void testAbstractBaseClass() {
|
public void testAbstractBaseClass() {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkNoErrors();
|
// It doesn't matter if the class is abstract or not - dtor can be called polymorphically.
|
||||||
|
checkErrorLines(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct Base {
|
||||||
|
// };
|
||||||
|
// struct Derived : Base {
|
||||||
|
// virtual void bar();
|
||||||
|
// };
|
||||||
|
public void testImplicitDtorInBaseClass() {
|
||||||
|
loadCodeAndRun(getAboveComment());
|
||||||
|
checkErrorLines(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct Base {
|
||||||
|
// ~Base();
|
||||||
|
// };
|
||||||
|
// struct Derived : Base {
|
||||||
|
// virtual void bar();
|
||||||
|
// };
|
||||||
|
public void testExplicitDtorInBaseClass() {
|
||||||
|
loadCodeAndRun(getAboveComment());
|
||||||
|
checkErrorLines(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
package org.eclipse.cdt.core.settings.model;
|
package org.eclipse.cdt.core.settings.model;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer;
|
import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer;
|
||||||
|
import org.eclipse.cdt.internal.core.SafeStringInterner;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ public abstract class ACSettingEntry implements ICSettingEntry {
|
||||||
String fName;
|
String fName;
|
||||||
|
|
||||||
ACSettingEntry(String name, int flags){
|
ACSettingEntry(String name, int flags){
|
||||||
fName = name;
|
fName = SafeStringInterner.safeIntern(name);
|
||||||
fFlags = flags;
|
fFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.settings.model;
|
package org.eclipse.cdt.core.settings.model;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.SafeStringInterner;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public final class CMacroEntry extends ACSettingEntry implements ICMacroEntry{
|
public final class CMacroEntry extends ACSettingEntry implements ICMacroEntry{
|
||||||
|
@ -17,7 +19,7 @@ public final class CMacroEntry extends ACSettingEntry implements ICMacroEntry{
|
||||||
|
|
||||||
public CMacroEntry(String name, String value, int flags) {
|
public CMacroEntry(String name, String value, int flags) {
|
||||||
super(name, flags);
|
super(name, flags);
|
||||||
fValue = value;
|
fValue = SafeStringInterner.safeIntern(value);
|
||||||
if(fValue == null)
|
if(fValue == null)
|
||||||
fValue = ""; //$NON-NLS-1$
|
fValue = ""; //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
||||||
public CPPMethod(IASTDeclarator declarator) {
|
public CPPMethod(IASTDeclarator declarator) {
|
||||||
super(declarator);
|
super(declarator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTDeclaration getPrimaryDeclaration() {
|
public IASTDeclaration getPrimaryDeclaration() {
|
||||||
//first check if we already know it
|
//first check if we already know it
|
||||||
if (declarations != null) {
|
if (declarations != null) {
|
||||||
|
@ -60,7 +60,7 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
||||||
if (decl.getParent() instanceof ICPPASTCompositeTypeSpecifier)
|
if (decl.getParent() instanceof ICPPASTCompositeTypeSpecifier)
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
final char[] myName = getASTName().getLookupKey();
|
final char[] myName = getASTName().getLookupKey();
|
||||||
ICPPClassScope scope = (ICPPClassScope) getScope();
|
ICPPClassScope scope = (ICPPClassScope) getScope();
|
||||||
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) ASTInternal.getPhysicalNodeOfScope(scope);
|
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) ASTInternal.getPhysicalNodeOfScope(scope);
|
||||||
|
@ -91,33 +91,34 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
||||||
*/
|
*/
|
||||||
public int getVisibility() {
|
public int getVisibility() {
|
||||||
IASTDeclaration decl = getPrimaryDeclaration();
|
IASTDeclaration decl = getPrimaryDeclaration();
|
||||||
if( decl == null ){
|
if (decl == null) {
|
||||||
IScope scope = getScope();
|
IScope scope = getScope();
|
||||||
if( scope instanceof ICPPClassScope ){
|
if (scope instanceof ICPPClassScope) {
|
||||||
ICPPClassType cls = ((ICPPClassScope)scope).getClassType();
|
ICPPClassType cls = ((ICPPClassScope)scope).getClassType();
|
||||||
if( cls != null )
|
if (cls != null)
|
||||||
return ( cls.getKey() == ICPPClassType.k_class ) ? ICPPASTVisibilityLabel.v_private : ICPPASTVisibilityLabel.v_public;
|
return (cls.getKey() == ICPPClassType.k_class) ? ICPPASTVisibilityLabel.v_private : ICPPASTVisibilityLabel.v_public;
|
||||||
}
|
}
|
||||||
return ICPPASTVisibilityLabel.v_private;
|
return ICPPASTVisibilityLabel.v_private;
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTCompositeTypeSpecifier cls = (IASTCompositeTypeSpecifier) decl.getParent();
|
IASTCompositeTypeSpecifier cls = (IASTCompositeTypeSpecifier) decl.getParent();
|
||||||
IASTDeclaration [] members = cls.getMembers();
|
IASTDeclaration [] members = cls.getMembers();
|
||||||
ICPPASTVisibilityLabel vis = null;
|
ICPPASTVisibilityLabel vis = null;
|
||||||
for (IASTDeclaration member : members) {
|
for (IASTDeclaration member : members) {
|
||||||
if( member instanceof ICPPASTVisibilityLabel )
|
if (member instanceof ICPPASTVisibilityLabel) {
|
||||||
vis = (ICPPASTVisibilityLabel) member;
|
vis = (ICPPASTVisibilityLabel) member;
|
||||||
else if( member == decl )
|
} else if (member == decl) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( vis != null ){
|
if (vis != null) {
|
||||||
return vis.getVisibility();
|
return vis.getVisibility();
|
||||||
} else if( cls.getKey() == ICPPASTCompositeTypeSpecifier.k_class ){
|
} else if (cls.getKey() == ICPPASTCompositeTypeSpecifier.k_class) {
|
||||||
return ICPPASTVisibilityLabel.v_private;
|
return ICPPASTVisibilityLabel.v_private;
|
||||||
}
|
}
|
||||||
return ICPPASTVisibilityLabel.v_public;
|
return ICPPASTVisibilityLabel.v_public;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICPPClassType getClassOwner() {
|
public ICPPClassType getClassOwner() {
|
||||||
ICPPClassScope scope = (ICPPClassScope)getScope();
|
ICPPClassScope scope = (ICPPClassScope)getScope();
|
||||||
return scope.getClassType();
|
return scope.getClassType();
|
||||||
|
@ -139,15 +140,15 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
||||||
public IScope getScope() {
|
public IScope getScope() {
|
||||||
return CPPVisitor.getContainingScope(getASTName());
|
return CPPVisitor.getContainingScope(getASTName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod#isVirtual()
|
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod#isVirtual()
|
||||||
*/
|
*/
|
||||||
public boolean isVirtual() {
|
public boolean isVirtual() {
|
||||||
IASTDeclaration decl = getPrimaryDeclaration();
|
IASTDeclaration decl = getPrimaryDeclaration();
|
||||||
if( decl != null ){
|
if (decl != null) {
|
||||||
ICPPASTDeclSpecifier declSpec = getDeclSpec(decl);
|
ICPPASTDeclSpecifier declSpec = getDeclSpec(decl);
|
||||||
if( declSpec != null ){
|
if (declSpec != null) {
|
||||||
return declSpec.isVirtual();
|
return declSpec.isVirtual();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,10 +157,11 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
||||||
|
|
||||||
protected ICPPASTDeclSpecifier getDeclSpec(IASTDeclaration decl) {
|
protected ICPPASTDeclSpecifier getDeclSpec(IASTDeclaration decl) {
|
||||||
ICPPASTDeclSpecifier declSpec = null;
|
ICPPASTDeclSpecifier declSpec = null;
|
||||||
if( decl instanceof IASTSimpleDeclaration )
|
if (decl instanceof IASTSimpleDeclaration) {
|
||||||
declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration)decl).getDeclSpecifier();
|
declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration)decl).getDeclSpecifier();
|
||||||
else if( decl instanceof IASTFunctionDefinition )
|
} else if (decl instanceof IASTFunctionDefinition) {
|
||||||
declSpec = (ICPPASTDeclSpecifier) ((IASTFunctionDefinition)decl).getDeclSpecifier();
|
declSpec = (ICPPASTDeclSpecifier) ((IASTFunctionDefinition)decl).getDeclSpecifier();
|
||||||
|
}
|
||||||
return declSpec;
|
return declSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,11 +171,11 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
||||||
@Override
|
@Override
|
||||||
public boolean isInline() {
|
public boolean isInline() {
|
||||||
IASTDeclaration decl = getPrimaryDeclaration();
|
IASTDeclaration decl = getPrimaryDeclaration();
|
||||||
if( decl instanceof IASTFunctionDefinition )
|
if (decl instanceof IASTFunctionDefinition)
|
||||||
return true;
|
return true;
|
||||||
if( decl == null )
|
if (decl == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration)decl).getDeclSpecifier();
|
IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration)decl).getDeclSpecifier();
|
||||||
return declSpec.isInline();
|
return declSpec.isInline();
|
||||||
}
|
}
|
||||||
|
@ -183,9 +185,9 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isMutable() {
|
public boolean isMutable() {
|
||||||
return hasStorageClass( this, IASTDeclSpecifier.sc_mutable );
|
return hasStorageClass(this, IASTDeclSpecifier.sc_mutable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isStatic(boolean resolveAll) {
|
public boolean isStatic(boolean resolveAll) {
|
||||||
IASTDeclaration decl = getPrimaryDeclaration();
|
IASTDeclaration decl = getPrimaryDeclaration();
|
||||||
|
@ -205,21 +207,21 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
||||||
char[] name = getNameCharArray();
|
char[] name = getNameCharArray();
|
||||||
if (name.length > 1 && name[0] == '~')
|
if (name.length > 1 && name[0] == '~')
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isImplicit() {
|
public boolean isImplicit() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod#isPureVirtual()
|
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod#isPureVirtual()
|
||||||
*/
|
*/
|
||||||
public boolean isPureVirtual() {
|
public boolean isPureVirtual() {
|
||||||
if (declarations != null) {
|
if (declarations != null) {
|
||||||
for (IASTDeclarator dtor : declarations) {
|
for (IASTDeclarator dtor : declarations) {
|
||||||
if (dtor == null)
|
if (dtor == null)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
dtor = ASTQueries.findOutermostDeclarator(dtor);
|
dtor = ASTQueries.findOutermostDeclarator(dtor);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IFolder;
|
import org.eclipse.core.resources.IFolder;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.resources.IProjectDescription;
|
import org.eclipse.core.resources.IProjectDescription;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
import org.eclipse.core.resources.IWorkspace;
|
import org.eclipse.core.resources.IWorkspace;
|
||||||
import org.eclipse.core.resources.ResourcesPlugin;
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
@ -143,7 +144,7 @@ public class StandardExecutableImporter implements IExecutableImporter {
|
||||||
for (int i = 0; i < segmentCount; i++) {
|
for (int i = 0; i < segmentCount; i++) {
|
||||||
currentFolder = currentFolder.getFolder(new Path(path.segment(i)));
|
currentFolder = currentFolder.getFolder(new Path(path.segment(i)));
|
||||||
if (!currentFolder.exists()) {
|
if (!currentFolder.exists()) {
|
||||||
((IFolder) currentFolder).create(false, true, new NullProgressMonitor());
|
((IFolder) currentFolder).create(IResource.VIRTUAL | IResource.DERIVED, true, new NullProgressMonitor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue