1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-09 09:15:38 +02:00

Bug 534420 - Add initial support for [[nodiscard]] attribute

Change-Id: I3bb7e1b4068c5e95a8247be152b9e428f9207bdc
This commit is contained in:
Marco Stornelli 2020-03-13 13:03:57 +01:00
parent 67b441b120
commit 5f316f4045
22 changed files with 165 additions and 4 deletions

View file

@ -152,6 +152,12 @@ public class CPPFunctionTests extends PDOMTestBase {
assertTrue(((ICPPFunction) bindings[0]).isNoReturn());
}
private void assertNoDiscardFunction(String functionName) throws CoreException {
IBinding[] bindings = findQualifiedName(pdom, functionName);
assertEquals(1, bindings.length);
assertTrue(((ICPPFunction) bindings[0]).isNoDiscard());
}
public void testNoReturnCPPFunction() throws Exception {
assertNoReturnFunction("noReturnCPPFunction");
assertNoReturnFunction("trailingNoReturnStdAttributeDecl");
@ -160,6 +166,14 @@ public class CPPFunctionTests extends PDOMTestBase {
assertNoReturnFunction("leadingNoReturnStdAttributeDef");
}
public void testNoDiscardCPPFunction() throws Exception {
assertNoDiscardFunction("noDiscardCPPFunction");
assertNoDiscardFunction("trailingNoDiscardStdAttributeDecl");
assertNoDiscardFunction("leadingNoDiscardStdAttributeDecl");
assertNoDiscardFunction("trailingNoDiscardStdAttributeDef");
assertNoDiscardFunction("leadingNoDiscardStdAttributeDef");
}
public void testForwardDeclarationType() throws Exception {
assertType(pdom, "forwardDeclaration", ICPPFunction.class);
}

View file

@ -10,6 +10,12 @@ void leadingNoReturnStdAttributeDecl() [[noreturn]];
[[noreturn]] void trailingNoReturnStdAttributeDef(){}
void leadingNoReturnStdAttributeDef() [[noreturn]]{}
int noDiscardCPPFunction() __attribute__((warn_unused_result));
[[nodiscard]] int trailingNoDiscardStdAttributeDecl();
int leadingNoDiscardStdAttributeDecl() [[nodiscard]];
[[nodiscard]] int trailingNoDiscardStdAttributeDef(){return 0;}
int leadingNoDiscardStdAttributeDef() [[nodiscard]]{return 0;}
void voidCPPFunction();
int intCPPFunction();
double doubleCPPFunction();

View file

@ -65,4 +65,12 @@ public interface IFunction extends IBinding {
* @since 5.4
*/
public boolean isNoReturn();
/**
* Returns {@code true} if return value of this function must not be discarded.
* Based on 'nodiscard' attribute in the function declaration or in C using
* the flag 'warn_unused_result'
* @since 6.12
*/
public boolean isNoDiscard();
}

View file

@ -26,6 +26,8 @@ import org.eclipse.cdt.core.parser.StandardAttributes;
*/
public class AttributeUtil {
private static final String[] ATTRIBUTE_NORETURN = new String[] { "__noreturn__", StandardAttributes.NORETURN }; //$NON-NLS-1$
private static final String[] ATTRIBUTE_NODISCARD = new String[] { "warn_unused_result", //$NON-NLS-1$
StandardAttributes.NODISCARD };
// Not instantiatable.
private AttributeUtil() {
@ -54,6 +56,14 @@ public class AttributeUtil {
return hasAttribute(node, ATTRIBUTE_NORETURN);
}
/**
* Returns {@code true} if the node has a "nodiscard" attribute.
* @since 6.12
*/
public static boolean hasNodiscardAttribute(IASTAttributeOwner node) {
return hasAttribute(node, ATTRIBUTE_NODISCARD);
}
/**
* Returns character representation of the attribute argument, or {@code null} if the attribute
* has zero or more than one argument.

View file

@ -496,6 +496,12 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
return dtor != null && AttributeUtil.hasNoreturnAttribute(dtor);
}
@Override
public boolean isNoDiscard() {
IASTFunctionDeclarator dtor = getPreferredDtor();
return dtor != null && AttributeUtil.hasNodiscardAttribute(dtor);
}
protected IASTFunctionDeclarator getPreferredDtor() {
IASTFunctionDeclarator dtor = getDefinition();
if (dtor != null)

View file

@ -161,6 +161,11 @@ public class CPPClassSpecialization extends CPPSpecialization
public boolean isConstexpr() {
return false;
}
@Override
public boolean isNoDiscard() {
return false;
}
}
public final static class RecursionResolvingConstructor extends RecursionResolvingMethod

View file

@ -159,6 +159,11 @@ public class CPPDeferredFunction extends CPPUnknownBinding
return false;
}
@Override
public boolean isNoDiscard() {
return false;
}
@Override
public int getRequiredArgumentCount() {
return 0;

View file

@ -104,6 +104,11 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
public int getRequiredArgumentCount() {
return 0;
}
@Override
public boolean isNoDiscard() {
return false;
}
}
public static final ICPPFunction UNINITIALIZED_FUNCTION = new CPPFunction(null) {
@ -739,6 +744,11 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
return isNoReturn(getPreferredDtor());
}
@Override
public boolean isNoDiscard() {
return isNoDiscard(getPreferredDtor());
}
public static boolean isNoReturn(ICPPASTFunctionDeclarator dtor) {
if (dtor == null) {
return false;
@ -753,6 +763,20 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
return false;
}
public static boolean isNoDiscard(ICPPASTFunctionDeclarator dtor) {
if (dtor == null) {
return false;
}
if (AttributeUtil.hasNodiscardAttribute(dtor)) {
return true;
}
IASTNode parent = dtor.getParent();
if (parent instanceof IASTAttributeOwner) {
return AttributeUtil.hasNodiscardAttribute((IASTAttributeOwner) parent);
}
return false;
}
public static ICPPExecution getFunctionBodyExecution(ICPPFunction function) {
if (function instanceof ICPPComputableFunction) {
return ((ICPPComputableFunction) function).getFunctionBodyExecution();

View file

@ -341,4 +341,12 @@ public class CPPFunctionSpecialization extends CPPSpecialization
}
return CPPTemplates.instantiateFunctionBody(this);
}
@Override
public boolean isNoDiscard() {
ICPPFunction f = (ICPPFunction) getSpecializedBinding();
if (f != null)
return f.isNoDiscard();
return false;
}
}

View file

@ -392,6 +392,11 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition implements ICPPFu
return CPPFunction.isNoReturn(getFirstFunctionDtor());
}
@Override
public boolean isNoDiscard() {
return CPPFunction.isNoDiscard(getFirstFunctionDtor());
}
private IASTDeclarator getDeclaratorByName(IASTNode node) {
// Skip qualified names and nested declarators.
while (node != null) {

View file

@ -174,4 +174,9 @@ public class CPPUnknownMethod extends CPPUnknownMember implements ICPPMethod {
public boolean isConstexpr() {
return false;
}
@Override
public boolean isNoDiscard() {
return false;
}
}

View file

@ -183,4 +183,9 @@ class AutoTypeResolver implements ICPPFunctionTemplate {
public boolean isNoReturn() {
throw new UnsupportedOperationException(UNEXPECTED_CALL);
}
@Override
public boolean isNoDiscard() {
throw new UnsupportedOperationException(UNEXPECTED_CALL);
}
}

View file

@ -83,4 +83,9 @@ class CompositeCFunction extends CompositeCBinding implements IFunction {
public boolean isNoReturn() {
return ((IFunction) rbinding).isNoReturn();
}
@Override
public boolean isNoDiscard() {
return ((IFunction) rbinding).isNoDiscard();
}
}

View file

@ -152,4 +152,9 @@ class CompositeCPPFunction extends CompositeCPPBinding implements ICPPFunction,
public ICPPExecution getFunctionBodyExecution() {
return CPPFunction.getFunctionBodyExecution((ICPPFunction) rbinding);
}
@Override
public boolean isNoDiscard() {
return ((ICPPFunction) rbinding).isNoDiscard();
}
}

View file

@ -302,10 +302,13 @@ public class PDOM extends PlatformObject implements IPDOM {
*
* CDT 9.9 development (version not supported on the 9.8.x branch)
* 215.0 - Corruption due to wrong record size in field/variable template partial specialization, bug 549028.
*
* CDT 9.12 development (version not supported on the 9.11.x branch)
* 216.0 - Added nodiscard function information, bug 534420
*/
private static final int MIN_SUPPORTED_VERSION = version(215, 0);
private static final int MAX_SUPPORTED_VERSION = version(215, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(215, 0);
private static final int MIN_SUPPORTED_VERSION = version(216, 0);
private static final int MAX_SUPPORTED_VERSION = version(216, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(216, 0);
private static int version(int major, int minor) {
return (major << 16) + minor;

View file

@ -32,6 +32,9 @@ class PDOMCAnnotations {
private static final int NO_RETURN_OFFSET = 4;
private static final int REGISTER_OFFSET = 5;
private static final int AUTO_OFFSET = 6;
private static final int NO_DISCARD_OFFSET = 7;
//NOTE: we are writing these annotations on a "byte" so if we need
//to add another value we need to use at least a short.
/**
* Encodes annotations applicable to functions.
@ -55,6 +58,8 @@ class PDOMCAnnotations {
annotation |= 1 << REGISTER_OFFSET;
if (function.isAuto())
annotation |= 1 << AUTO_OFFSET;
if (function.isNoDiscard())
annotation |= 1 << NO_DISCARD_OFFSET;
return annotation;
}
@ -114,6 +119,13 @@ class PDOMCAnnotations {
return (annotation & (1 << NO_RETURN_OFFSET)) != 0;
}
/**
* Checks if the "no discard" annotation is set.
*/
public static boolean isNoDiscardFunction(short annotation) {
return (annotation & (1 << NO_DISCARD_OFFSET)) != 0;
}
/**
* Checks if the "register" annotation is set.
*/

View file

@ -208,4 +208,9 @@ class PDOMCFunction extends PDOMBinding implements IFunction {
public IScope getFunctionScope() {
return null;
}
@Override
public boolean isNoDiscard() {
return PDOMCAnnotations.isNoDiscardFunction(getAnnotations());
}
}

View file

@ -45,6 +45,7 @@ class PDOMCPPAnnotations {
private static final int PARAMETER_PACK_OFFSET = 7;
private static final int DELETED_OFFSET = 8;
private static final int NO_RETURN_OFFSET = 9;
private static final int NO_DISCARD_OFFSET = 10;
// Method annotations that don't fit on the first 16 bits of annotations.
private static final int VIRTUAL_OFFSET = 0;
@ -82,6 +83,8 @@ class PDOMCPPAnnotations {
annotation |= 1 << PARAMETER_PACK_OFFSET;
if (function.isDeleted())
annotation |= 1 << DELETED_OFFSET;
if (function.isNoDiscard())
annotation |= 1 << NO_DISCARD_OFFSET;
return annotation;
}
@ -226,6 +229,13 @@ class PDOMCPPAnnotations {
return (annotation & (1 << NO_RETURN_OFFSET)) != 0;
}
/**
* Checks if the "no discard" annotation is set.
*/
public static boolean isNoDiscardFunction(short annotation) {
return (annotation & (1 << NO_DISCARD_OFFSET)) != 0;
}
/**
* Checks if the "virtual" annotation is set.
*/

View file

@ -449,4 +449,9 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl
return null;
}
}
@Override
public boolean isNoDiscard() {
return PDOMCPPAnnotations.isNoDiscardFunction(getAnnotations());
}
}

View file

@ -342,4 +342,9 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization
return null;
}
}
@Override
public boolean isNoDiscard() {
return PDOMCPPAnnotations.isNoDiscardFunction(getAnnotations());
}
}

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name.1
Bundle-SymbolicName: org.eclipse.cdt.core.lrparser;singleton:=true
Bundle-Version: 5.2.300.qualifier
Bundle-Version: 5.2.400.qualifier
Bundle-ClassPath: .
Require-Bundle: org.eclipse.cdt.core,
net.sourceforge.lpg.lpgjavaruntime;bundle-version="1.1.0";visibility:=reexport,

View file

@ -39,6 +39,7 @@ public class C99Function extends PlatformObject implements IC99Binding, IFunctio
private boolean isStatic;
private boolean isVarArgs;
private boolean isNoReturn;
private boolean isNoDiscard;
// the scope that the function is in (must be the global scope, no?)
private IScope scope;
@ -181,4 +182,13 @@ public class C99Function extends PlatformObject implements IC99Binding, IFunctio
public IBinding getOwner() {
return null;
}
@Override
public boolean isNoDiscard() {
return isNoDiscard;
}
public void setNoDiscard(boolean isNoDiscard) {
this.isNoDiscard = isNoDiscard;
}
}