Is there a simple way to take the general arguments of a function (Pointer, Array, Integer) and get the values backing the expression, when writing a custom checker? As in, I match against a function such as:
Pointer p;
Integer i;
CallSite f("func");
if(MATCH( f(p,i) ))
//get function arguments
Is there a simple way of getting the values backing p and i? Thanks.
**Language is C++ to make a custom checker
There is no way to get run-time value from these variables statically.
Maybe it's more accurate to say that this is beyond the scope of what a simple static analysis checker can do.
The exception would be if you are passing a literal value or constant.
Related
I need to get information from a class function. Said class has overloaded operators for basically any standard type. Therefore
double foo = exampleObject.getInformation();
and
std::string faa = exampleObject.getInformation();
Would both work. If the information can not be transformed into a double, foo will be set to 0. The initialization of faa will always work. (It can always be expressed as a string)
My problem is: I want to get the information and save it as a double variable, if that can not be done as the information is not of numeric type, I want the variable to be a string. I basically need a variable that can change its type. How do I do this? I'm sorry if that is a very basic question, C++ is not my main programming language.
Have you tried using Function Templates?
They won't change the type of a variable but will allow you to write your code in a way that works with more than 1 data type.
If c++ is not your main, I would recommend checking the checking the documentation for Function Templates on cplusplus.com
Here => https://cplusplus.com/doc/oldtutorial/templates/
I've been given a bunch of dummy functions, each one with its own return type, number (and types) of arguments and I'm trying to figure out a way to create function pointers of the correct type to them automatically, then store them inside a map to be retrieved at will. In a nutshell, I'm stuck at creating the actual function pointers. The way of storing them in a map is a separate, follow-up question, due to their variable types.
I think that templates are the way to go, and I've tried creating a templated function that returns the appropriately-typed pointer given the address and types of a function. I think it could not be possible though, so any input is appreciated.
Code for the aforementioned function:
template <typename retType, typename ... argTypes> retType makeFuncPtr(void* funcAddr) {
retType (*ptr)(argTypes) = funcAddr;
return ptr;
}
I'm getting an error "Declaration type contains unexpanded parameter pack 'argTypes'". What am I doing wrong and also which is the appropriate return type for this function, as I'm not actually sure about it?
The error you ask about is because in the line:
retType (*ptr)(argTypes) = funcAddr;
there is no ... after argTypes. Note this would not actually fix the situation because a void pointer can not be converted to some other kind of pointer without a cast. And also you could not convert the function pointer to retType.
If the functions have different signatures this is a fairly tricky problem, I suggest you take a look at libffi, the tricky part here is not storing the function pointers (so long as they are not non-static member functions you can simply cast to void * and store that), the tricky part is using the stored pointer value to make a call.
libffi gives you the ability to describe a function's calling convention, return type and expected arguments. You could then write code that compares the arguments you actually received and either convert or produce an error as appropriate. With C++ it would even be possible to produce that description programmatically (your template function would take a function pointer as a parameter then use the parameter pack to map to the libffi argument type values).
If i understand correctly, static analysis can guess what values a variable can have, and deduce, for example, what path in the control flow graph will never be executed.
I have an array of constants strings CStr. A method GetValue takes an index in parameters and do some computation to find the actual index in CStr array and return the const string pointed at that index.
edit: The actual index is unique and constant for each parameter given to GetValue
Can static analysis guess that GetValue(x) will have a constant value ? If yes, how is it done ?
"Can static analysis guess that GetValue(x) will have a constant value ?"
That totally depends on the capabilities and quality of your static code analysis tool.
From theory that's possible to detect, yes.
If you meant what the compiler can deduce about constant expressions, it also depends on the compiler's actual implementation.
The best hint you can give it, is using the constexpr keyword, e.g.
constexpr int GetValue(int x);
"If yes, how is it done ?"
That's a very broad field, and hard to give a concise answer here.
Basically a static code analysis tool keeps track about the call references of particular functions. If the result of these functions can be deduced being a value that is specified at compile time (e.g. due to static initialization), the actual valid size/index of an accessed address from a calling function is known, and can be marked as issue if it's out of bounds.
I have a data class (struct actually) two variables: a void pointer and a string containing the type of the object being pointed to.
struct data{
void* index;
std::string type;
data(): index(0), type("null"){}
data(void* index, std::string type): index(index), type(type){}};
Now I need to use the object being pointed to, by casting the void pointer to a type that is specified by the string, so I thought of using an std::map with strings and functions.
std::unordered_map<std::string, function> cast;
The problem is that the functions must always have the exact same return-type and can't return a type itself.
Edit:
Because I use the data class as a return-type and as arguments, templates won't suffice.
(also added some code to show what I mean)
data somefunction(data a){
//do stuff
return data();}
Currently, I use functions like this to do the trick, but I thought it could be done more easily:
void functionforstring(data a){
dynamic_cast<string*>(data.index)->function();}
Neither thing is possible in C++:
Functions cannot return types (that is to say, types are not values).
Code cannot operate on objects whose type it doesn't know at compile-time (that is to say, C++ is statically typed). Of course there is dynamic polymorphism via virtual functions, but even with that, the type of the pointer you use to call them is known at compile time by the calling code.
So the operation you want, "convert to the pointer type indicated by a string" is not possible. If it were possible, then the result would be a pointer whose type is not known at compile time, and that cannot be.
There's nothing you could do with this "pointer of type unknown at compile time", that you can't do using the void* you started with. void* pretty much already is what C++ has in place of a pointer to unknown type.
While it's not possible to return a type from a function, you could use typeid to get information about the object, and use the string returned by typeid(*obj).name() as an argument to your constructor.
Keep in mind that this string would be implementation defined, so you would have to generate this string at runtime for every type that you might possibly use in the program in order to make your unordered_map useful.
There is almost certainly a much simpler and more idiomatic way to accomplish your goal in C++, however. Perhaps if you explained more about the goals of the program, someone might be able to suggest an alternative approach.
I'm trying to fix something in some Objective C++ (?!) code. I don't know either of those languages, or any of the relevant APIs or the codebase, so I'm getting stymied left and right.
Say I have:
Vector<char, sizeof 'a'>& sourceData();
sourceData->append('f');
When i try to compile that, I get:
error: request for member 'append' in 'WebCore::sourceData', which is of non-class type 'WTF::Vector<char, 1ul >& ()();
In this case, Vector is WTF::Vector (from WebKit or KDE or something), not STD::Vector. append() very much is supposed to be a member of class generated from this template, as seen in this documentation. It's a Vector. It takes the type the template is templated on.
Now, because I never write programs in Real Man's programming languages, I'm hella confused about the notations for references and pointers and dereferences and where we need them.
I ultimately want a Vector reference, because I want to pass it to another function with the signature:
void foobar(const Vector<char>& in, Vector<char>& out)
I'm guessing the const in the foobar() sig is something I can ignore, meaning 'dont worry, this won't be mangled if you pass it in here'.
I've also tried using .append rather than -> because isn't one of the things of C++ references that you can treat them more like they aren't pointers? Either way, its the same error.
I can't quite follow the error message: it makes it sound like sourceData is of type WTF:Vector<char, 1ul>&, which is what I want. It also looks from the those docs of WTF::Vector that when you make a Vector of something, you get an .append(). But I'm not familiar with templates, either, so I can't really tell i I'm reading that right.
EDIT:
(This is a long followup to Pavel Minaev)
WOW THANKS PROBLEM SOLVED!
I was actually just writing an edit to this post that I semi-figured out your first point after coming across a reference on the web that that line tells the compiler your forward declaring a func called sourceData() that takes no params and returns a Vector of chars. so a "non-class type" in this case means a type that is not an instance of a class. I interpreted that as meaning that the type was not a 'klass', i.e. the type of thing you would expect you could call like .addMethod(functionPointer).
Thanks though! Doing what you suggest makes this work I think. Somehow, I'd gotten it into my head (idk from where) that because the func sig was vector&, I needed to declare those as &'s. Like a stack vs. heap pass issue.
Anyway, that was my REAL problem, because I tried what you'd suggested about but that doesn't initialize the reference. You need to explicitly call the constructor, but then when I put anything in the constructor's args to disambiguate from being a forward decl, it failed with some other error about 'temporary's.
So in a sense, I still don't understand what is going on here fully, but I thank you heartily for fixing my problem. if anyone wants to supply some additional elucidation for the benefit of me and future google people, that would be great.
This:
Vector<char, sizeof 'a'>& sourceData();
has declared a global function which takes no arguments and returns a reference to Vector. The name sourceData is therefore of function type. When you try to access a member of that, it rightfully complains that it's not a class/struct/union, and operator-> is simply inapplicable.
To create an object instead, you should omit the parentheses (they are only required when you have any arguments to pass to the constructor, and must be omitted if there are none):
Vector<char, sizeof 'a'> sourceData;
Then you can call append:
sourceData.append('f');
Note that dot is used rather than -> because you have an object, not a pointer to object.
You do not need to do anything special to pass sourceData to a function that wants a Vector&. Just pass the variable - it will be passed by reference automatically:
foobar(sourceData, targetData);
Dipping your toes in C++ is never much fun. In this case, you've run into a couple of classic mistakes. First, you want to create an instance of Vector on the stack. In this case the empty () is interpreted instead as a declaratiton of a function called sourceData that takes no agruments and returns a reference to a Vector. The compiler is complaining that the resulting function is not a class (it's not). To create an instance of Vector instead, declare the instance without the () and remove the &. The parentheses are only required if you are passing arguments to the instance constructor and must be omitted if there are no arguments.
You want
Vector<char, sizeof 'a'> sourceData;
sourceData.append('f');
Vector<char, sizeof 'a'> outData; //if outData is not instantiated already
foobar(sourceData, outData);
This Wikipedia article gives a decent introduction to C++ references.