1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-21 21:52:10 +02:00

Bug 534420 - Added check for nodiscard for classes and enums

Change-Id: I3932f4d23f18f96f8d1c15c18d7d4d991154aca1
This commit is contained in:
Marco Stornelli 2020-04-06 17:29:40 +02:00
parent 77790012cc
commit dd88f8ffca
2 changed files with 92 additions and 6 deletions

View file

@ -28,14 +28,20 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFunctionCall;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
public class NoDiscardChecker extends AbstractAstFunctionChecker {
public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.NoDiscardProblem"; //$NON-NLS-1$
@ -101,12 +107,17 @@ public class NoDiscardChecker extends AbstractAstFunctionChecker {
} else {
return Optional.empty();
}
IBinding binding = name.resolveBinding();
if (binding instanceof IFunction && ((IFunction) binding).isNoDiscard()) {
if (expr instanceof ICPPASTExpression) {
if (checkEvaluation((ICPPASTExpression) expr)) {
return Optional.of(name);
} else if ((binding instanceof ICPPClassType || binding instanceof ICPPVariable)
&& expr instanceof ICPPASTExpression && checkEvaluation((ICPPASTExpression) expr)) {
}
return Optional.empty();
}
// For C, the only thing we need to check is IFunction
IBinding binding = name.resolveBinding();
if (binding instanceof IFunction && ((IFunction) binding).isNoDiscard()) {
return Optional.of(name);
}
@ -138,8 +149,24 @@ public class NoDiscardChecker extends AbstractAstFunctionChecker {
}
} else if (eval instanceof EvalFunctionCall) {
ICPPFunction evalFunc = ((EvalFunctionCall) eval).resolveFunctionBinding();
if (evalFunc != null && evalFunc.isNoDiscard()) {
if (evalFunc == null)
return false;
if (evalFunc.isNoDiscard()) {
return true;
} else {
ICPPFunctionType fType = evalFunc.getType();
IType retType = SemanticUtil.getNestedType(fType.getReturnType(), SemanticUtil.TDEF);
if (CPPTemplates.isDependentType(retType)) {
return false;
}
if (retType instanceof ICPPReferenceType || retType instanceof IPointerType)
return false;
retType = SemanticUtil.getUltimateType(retType, true);
if (retType instanceof ICPPClassType) {
return ((ICPPClassType) retType).isNoDiscard();
} else if (retType instanceof ICPPEnumeration) {
return ((ICPPEnumeration) retType).isNoDiscard();
}
}
}
return false;

View file

@ -12,6 +12,7 @@ package org.eclipse.cdt.codan.core.internal.checkers;
import org.eclipse.cdt.codan.core.tests.CheckerTestCase;
import org.eclipse.cdt.codan.internal.checkers.NoDiscardChecker;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
/**
* Test for {@link NoDiscardChecker} class
@ -384,4 +385,62 @@ public class NoDiscardCheckerTest extends CheckerTestCase {
loadCodeAndRun(getAboveComment());
checkErrorLine(6, ER_ID);
}
//struct [[nodiscard]] error_info { };
//error_info enable_missile_safety_mode();
//void launch_missiles();
//void test_missiles() {
// enable_missile_safety_mode();
// launch_missiles();
//}
public void testClassNoDiscardType() throws Exception {
loadCodeAndRun(getAboveComment());
checkErrorLine(5, ER_ID);
}
//struct [[nodiscard]] error_type {};
//error_info& foo();
//void f1() {
// foo();
//}
public void testClassNoDiscardTypesByRef() throws Exception {
loadCodeAndRun(getAboveComment());
checkNoErrorsOfKind(ER_ID);
}
//struct [[nodiscard]] error_type { error_type(int) {} };
//template<class T>
//typename T::E foo() {return static_cast<typename T::E>(0);}
//template<class F>
//struct trait { typedef typename F E; }
//void f1() {
// foo<trait<error_type>>();
//}
public void testClassNoDiscardTypesTemplate() throws Exception {
CPPASTNameBase.sAllowNameComputation = true;
loadCodeAndRun(getAboveComment());
checkNoErrorsOfKind(ER_ID);
}
//enum [[nodiscard]] error_type { FAILURE };
//error_type enable_missile_safety_mode();
//void launch_missiles();
//void test_missiles() {
// enable_missile_safety_mode();
// launch_missiles();
//}
public void testEnumNoDiscardType() throws Exception {
loadCodeAndRun(getAboveComment());
checkErrorLine(5, ER_ID);
}
//enum [[nodiscard]] error_type { FAILURE };
//error_type& foo();
//void f1() {
// foo();
//}
public void testEnumNoDiscardTypesByRef() throws Exception {
loadCodeAndRun(getAboveComment());
checkNoErrorsOfKind(ER_ID);
}
}