Merge pull request #18849 from michaelnebel/csharp/tupledefaulttostring

C#: Proper handling of value tuples in `cs/call-to-object-tostring`.
This commit is contained in:
Michael Nebel
2025-02-25 10:24:02 +01:00
committed by GitHub
4 changed files with 22 additions and 1 deletions

View File

@@ -46,6 +46,7 @@ private predicate alwaysInvokesToString(ParameterRead pr) {
* method from `System.Object` or `System.ValueType`.
*/
predicate alwaysDefaultToString(ValueOrRefType t) {
not t instanceof TupleType and
exists(ToStringMethod m | t.hasMethod(m) |
m.getDeclaringType() instanceof SystemObjectClass or
m.getDeclaringType() instanceof SystemValueTypeClass
@@ -55,6 +56,11 @@ predicate alwaysDefaultToString(ValueOrRefType t) {
overriding.getABaseType+() = t
) and
((t.isAbstract() or t instanceof Interface) implies not t.isEffectivelyPublic())
or
exists(ValueOrRefType elem |
elem = t.(TupleType).getElementType(_) and
alwaysDefaultToString(elem)
)
}
class DefaultToStringType extends ValueOrRefType {

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* C#: Improve precision of the query `cs/call-to-object-tostring` for value tuples.

View File

@@ -35,6 +35,16 @@ public class DefaultToString
IPublic g = null;
Console.WriteLine(g); // GOOD
Console.WriteLine(new ValueTuple<int, int>(1, 2)); // GOOD
Console.WriteLine((1, 2)); // GOOD
var t1 = new ValueTuple<int, DefaultToString>(1, new DefaultToString());
Console.WriteLine(t1); // BAD
var t2 = new ValueTuple<A, D>(new A(), new D());
Console.WriteLine(t2); // GOOD
}
class A

View File

@@ -2,7 +2,8 @@
| DefaultToString.cs:10:28:10:28 | access to local variable d | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | DefaultToString.cs:4:14:4:28 | DefaultToString | DefaultToString |
| DefaultToString.cs:16:27:16:30 | access to local variable ints | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | file://:0:0:0:0 | Int32[] | Int32[] |
| DefaultToString.cs:19:24:19:27 | access to local variable ints | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | file://:0:0:0:0 | Int32[] | Int32[] |
| DefaultToString.cs:34:27:34:27 | access to local variable f | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | DefaultToString.cs:62:23:62:30 | IPrivate | IPrivate |
| DefaultToString.cs:34:27:34:27 | access to local variable f | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | DefaultToString.cs:72:23:72:30 | IPrivate | IPrivate |
| DefaultToString.cs:44:27:44:28 | (...) ... | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | file://:0:0:0:0 | (Int32,DefaultToString) | (Int32,DefaultToString) |
| DefaultToStringBad.cs:8:35:8:35 | access to local variable p | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | DefaultToStringBad.cs:14:11:14:16 | Person | Person |
| DefaultToStringBad.cs:11:38:11:41 | access to local variable ints | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | file://:0:0:0:0 | Int32[] | Int32[] |
| WriteLineArray.cs:7:23:7:26 | access to parameter args | Default 'ToString()': $@ inherits 'ToString()' from 'Object', and so is not suitable for printing. | file://:0:0:0:0 | String[] | String[] |