Invalid type conversion while using ANSI c - misra

I am facing this problem as when I am trying to build the code using ANSI C, as I was practicing writing in it and dealing with its rules, it tells me invalid type conversion and I don't know what to do.
this is the code line that makes the error, it is a pointer to function:
((CanIf_FuncTypeCanSpecial)(entry->CanIfUserRxIndication))(
entry->CanIfCanRxPduHrhRef->CanIfCanControllerHrhIdRef,
entry->CanIfCanRxPduId,
CanSduPtr,
CanDlc,
CanId);
and this is howentry->CanIfUserRxIndication is declared, as void *CanIfUserRxIndication;
and this is how CanIf_FuncTypeCanSpecial is declared, as
typedef void (*CanIf_FuncTypeCanSpecial)
(uint8 channel, PduIdType pduId, const uint8 *sduPtr, uint8 dlc, Can_IdType canId);
every parameter in the conversion type is the same type as the input parameters except the first one entry->CanIfCanRxPduHrhRef->CanIfCanControllerHrhIdRef it is from type enum not uint8.
You can find the code on GitHub.
and also the MISRA Rule is telling me this:
#1398-D (MISRA-C:2004 11.1/R) Conversions shall not be performed between a pointer to a function and any type other than an integral type
I tried to convert from enum to uint8 to make all of the parameters as what the type conversion CanIf_FuncTypeCanSpecial takes, but nothing happened.

If I understand correctly, you are trying to cast an existing function to match a function pointer declaration that has a differing argument type. You can cast the parameters and call such a function, but because function pointers themselves may be used anywhere in the program, at the places where they would be used the code would not know what to cast (which may result in a size difference) this is illegal.

Related

Why can't I initialize a "const" variable with a primitive value received as a function argument in Dart?

I understand that, in Dart, primitives are passed by value and Objects are passed by reference.
So, I expected that
void test(String phrase) {
const _phrase = phrase;
}
would result in error, but
void test(int amount) {
const _amount = amount;
}
wouldn't.
However, both of them throws the same compile-time error: Const variables must be initialized with a constant value.
Is this some not implemented feature or there's a reason behind not accepting function arguments in const variables initialization?
Dart constant variables must be initialized with compile-time constant expressions.
A compile-time constant expression must always have the same value—precisely one value per source location.
Dart doesn't have "constant values" as such. It has constant expressions, which are known to evaluate to precisely one value, and for which it's possible to know this value at compile-time. That allows the compiler to canonicalize those constants values, so different constant expressions evaluating to constant objects with the same state are canonicalized to be the same object.
Your amount variable is not a compile-time constant expression. It can have different values at different times (because it's a function parameter and people might call the function with different arguments), so it cannot be a constant expression.
And therefore it cannot be used to initialize a constant variable, because constant variables can only have one value.
void test(int amount) {
const _amount = amount;
const list = [_amount]; // <- MUST ALWAYS HAVE SAME VALUE
}
In short: Dart constant variables must be initialized with a compile-time constant expression. A constant expression must always have the same value. This is the fundamental rule about Dart constant expressions which most other restrictions are derived from. (For example, a constant variable being used is a constant expression, so it must always be bound to the same value, which is why it must be initialized with a constant expression.)
I believe the answer is that constants are fixed at compile time rather than run time so function arguments cannot be passed to them as the function only gets executed at runtime.
See also here for example https://stackoverflow.com/a/58877374
A final modifier instead of const would work however.
By the way a String is also a primitive I think. See here https://stackoverflow.com/a/58568542

Abstract over int and double using num is broken with new Dart version

The following code used to work in Dart 2.6 (very simplified example!):
T plus<T extends num>(T a, T b) => a + b;
Now it fails with: A value of type 'num' can't be returned from method 'plus' because it has a return type of 'T'.
Is there a way to abstract over double/int like intended in the example?
I'm assuming you are passing the --no-implicit-casts flag to the analyzer in order to get this error. The code is correct in the current Dart language, but it contains an implicit cast, so if you choose to disable those, the code will not be accepted.
The reason the code does not work is that the static type of a + b is num (both have type T which is only known to extend num, so they are treated as num, and num.operator+ returns num), and the return type is T which may extend num.
So, the code does an implicit cast from num to T if you allow it.
To make the code compile even without implicit casts, you have to turn it into an explicit cast:
T plus<T extends num>(T a, T b) => (a + b) as T;

How to match the 2d array datatype between swift and objective-c?

I am calling a .mm (objective-c / c++) class method from my swift viewController via linked headers. They are successfully linked. However, I am struggling to pass correct data types that match as parameters.
Here is where I call the function in swift
OpenCVWrapper.thefunc(array1, otherstuff);
...array1 is of type [[Int]]
and here is the definition in objective-c
+(NSString*) thefunc: (int[][2])array1 otherstuff(int)other{
but i get the error
Cannot convert value of type '[[Int]]' to expected argument type 'UnsafeMutablepointer<(Int32)(Int32)>!'
My question is, how can I match the data types so they both handle a basic 2D array of type Int?
UPDATE:
value / structure issues:
structure passed from swift:
structure received in OC:
First of all, you may need to know that C-array and Swift Array are different things. C-array represents a contiguous region of memory and uses the pointer to the first element when passed.
Second, if you want to use imported Objective-C method from Swift, you'd better check the generated header of the method.
(Press the "four square icon" and choose "Generated Interface" while editor is showing the .h file.)
Tested with a small sample project, your method is imported as:
open class func thefunc(_ array1: UnsafeMutablePointer<(Int32, Int32)>!, otherstuff other: Int32) -> String!
(The corresponding type to int in Swift is Int32, not Int.)
So, you may need to pass a mutable pointer to tuple (Int32, Int32), to do that you need to declare a Swift Array of Element type (Int32, Int32) and pass it as an inout argument (using &).
So, you may need to write something like this:
//Assuming all inner Array of `array1` have two elements.
var convertedArray = array1.map {(Int32($0[0]), Int32($0[1]))}
MyClass.thefunc(&convertedArray, otherstuff: someInt32Value)
But the conversion of huge array may take some amount of time, in some cases, which is critical.
You may declare your Swift side array1 as Array of (Int32, Int32) and modify other parts according to this change, and use it as:
//Somewhere in your code...
var array1: [(Int32, Int32)] = []
//...
//And call `thefunc` as:
MyClass.thefunc(&array1, otherstuff: someInt32Value)

Why does lacking explicit type declaration in parameter work when function is used directly, but not when it is passed to another function?

Have this function defined in your module:
module Data
int inc(x) = x + 1;
Type this in the console:
rascal> import Data;
rascal> import List;
This works:
rascal> inc(1);
int: 2
But this does not:
rascal> list[int] y = [1,2,3];
rascal> mapper(y, inc);
|rascal://<path>|: insert into collection not supported on value and int
☞ Advice
But it works if inc(...)'s parameter type is declared:
int inc(int x) = x + 1;
So why does not having this type declaration work for using the inc(...) function directly, but not for passing that function to mapper(...)?
Because Rascal's type checker is still under development, you are not warned if you make a small mistake like forgetting to provide a type for a function parameter. It may still work, accidentally, in some circumstances but you are guaranteed to run into trouble somewhere as you've observed. The reason is that type inference for function parameters is simply not implemented as a feature. This is a language design decision with the intent of keeping error messages understandable.
So, this is not allowed:
int f(a) = a + 1;
And, it should be written like this:
int f(int a) = a + 1;
I consider it a bug that the interpreter doesn't complain about an untyped parameter. It is caused by the fact that we reuse the pattern matching code for both function parameters and inline patterns. [edit: issue has been registered at https://github.com/cwi-swat/rascal/issues/763]
In your case the example works because dynamically the type of the value is int and addition does not check the parameter types. The broken example breaks because the interpreter does checks the type of the function parameter at the call-site (which defaulted to value for the untyped parameter).

E2099 Overflow in conversion or arithmetic operation

I want to compare an int64 with a variable like this:
const GB=1073741824;
if DiskFile.Size< 1*GB then
It works with 1 but not with 3:
if DiskFile.Size< 3*GB then
This post (Strange Delphi integer multiplication behavior) explains why. I agree with that explanation. The result of 2*GB cannot fit in 'integer'. What I don't understand is why the compiler chooses integer instead the int64? As in the case of:
if DiskFile.Size< 3073741824 then <--------- almost 3GB
that works.
There is any way to write the last line of code in the 3*GB style (using constants) BUT without defining a new constant for 1GB, 2GB, 3GB, 4GB, etc ?
The first thing to be clear of here is that the integer overflow occurs in the compiler. The compiler has to evaluate your expression because it is a constant expression and they are evaluated by the compiler.
The documentation is a little sparse (and I am being kind here) on how the compiler treats your expression. We can infer, at least empirically, that the compiler attempts to perform 3*GB in a signed integer context. That is clear from the error message.
You need to force the compiler to evaluate the expression in an Int64 context. A cast will force that:
if DiskFile.Size< Int64(3)*GB then
....
Another option is to make the constant have type Int64:
const
GB = Int64(1073741824);
Although I think I'd write it like this:
const
KB = Int64(1024);
MB = 1024*KB;
GB = 1024*MB;
So long as GB is a 64 bit type then you can revert to:
if DiskFile.Size < 3*GB then
....
I'd like to elaborate on my second paragraph above. How can we tell that the compiler performs the arithmetic in 32 bit signed integer context? The following program suggests that this is so:
{$APPTYPE CONSOLE}
const
C1 = 715827882; // MaxInt div 3
C2 = C1+1;
begin
Writeln(3*C1);
Writeln(3*C2);
Readln;
end.
The first expression, 3*C1 compiles, the second fails with E2099. The first expression does not overflow a signed 32 bit integer, the second does.
When looking at the documentation, it is unclear whether the true constant 1073741824 should be of type Integer or Cardinal. The compiler could choose either. It seems that the compiler, when presented with a choice between signed and unsigned types, chooses signed types.
But then one might imagine that the following program would behave in the same way, but with Smallint and Word taking the place of Integer and Cardinal:
{$APPTYPE CONSOLE}
const
C1 = 10922; // high(Smallint) div 3
C2 = C1+1;
begin
Writeln(3*C1);
Writeln(3*C2);
Readln;
end.
But no, this program compiles. So, at this point I am giving up on the documentation which appears to bear little relationship to the actual behaviour of the compiler.
My best guess is that a integral true constant is handled as follows:
If it is within the range of Integer, it is of type Integer.
Otherwise, if it is within the range of Cardinal, it is of type Cardinal.
Otherwise, if it is within the range of Int64, it is of type Int64.
Otherwise, if it is within the range of UInt64, it is of type UInt64.
Otherwise it is a compiler error.
Of course, all of this assumes that the compilers rules for evaluating constant expressions follow the same rules as the rest of the language. I'm not certain that is the case.

Resources