In a llvm pass, how can I create a function of a char* parameter and insert a function call to it before the terminator instruction of a basic block? Please be specific.
Thanks,
Bo
The LLVM online demo should be able to help you: http://llvm.org/demo/index.cgi
With it, you can not only see the LLVM IR generated for a program you type in, but you can also have it show the LLVM C++ code needed to generate the IR. For example, I tried:
void f(char *);
int main(int argc, char **argv) {
char *p;
int i = 1;
if (i)
f(p);
return i;
}
The results are fairly easy to decipher.
Related
I want to be able to pass an integer via command line argument that I will call length. I need to make this constant, because it will be used to determine the size of several bitsets. I have tried doing this many ways, for example:
int main(int arc, const char* argv[]){
const int * ptr;
if (!(istringstream{argv[1]} >> ptr)) { return 1;}
const int length = *ptr;
bitset<length> right_ones = 1;
return 0;
}
I also tried it this way:
int main(int arc, const char* argv[]){
int test_int;
if (!(istringstream{argv[1]} >> test_int)) { return 1;}
const int length = argv[1];
bitset<length> right_ones = 1;
return 0;
}
But none of the ways I have tried it worked. How can I accomplish this?
If it is going to be passed as a command line argument, then you cannot make it a constant.
By the way, this is relevant to your case: Define bitset size at initialization?
The length of the bitset is needed at compile time so no matter how you try it there is no way to pass that value at runtime.
The following code snippet (correctly) gives a warning in C and an error in C++ (using gcc & g++ respectively, tested with versions 3.4.5 and 4.2.1; MSVC does not seem to care):
char **a;
const char** b = a;
I can understand and accept this.
The C++ solution to this problem is to change b to be a const char * const *, which disallows reassignment of the pointers and prevents you from circumventing const-correctness (C++ FAQ).
char **a;
const char* const* b = a;
However, in pure C, the corrected version (using const char * const *) still gives a warning, and I don't understand why.
Is there a way to get around this without using a cast?
To clarify:
Why does this generate a warning in C? It should be entirely const-safe, and the C++ compiler seems to recognize it as such.
What is the correct way to go about accepting this char** as a parameter while saying (and having the compiler enforce) that I will not be modifying the characters it points to?
For example, if I wanted to write a function:
void f(const char* const* in) {
// Only reads the data from in, does not write to it
}
And I wanted to invoke it on a char**, what would be the correct type for the parameter?
I had this same problem a few years ago and it irked me to no end.
The rules in C are more simply stated (i.e. they don't list exceptions like converting char** to const char*const*). Consequenlty, it's just not allowed. With the C++ standard, they included more rules to allow cases like this.
In the end, it's just a problem in the C standard. I hope the next standard (or technical report) will address this.
To be considered compatible, the source pointer should be const in the immediately anterior indirection level. So, this will give you the warning in GCC:
char **a;
const char* const* b = a;
But this won't:
const char **a;
const char* const* b = a;
Alternatively, you can cast it:
char **a;
const char* const* b = (const char **)a;
You would need the same cast to invoke the function f() as you mentioned. As far as I know, there's no way to make an implicit conversion in this case (except in C++).
However, in pure C, this still gives a warning, and I don't understand why
You've already identified the problem -- this code is not const-correct. "Const correct" means that, except for const_cast and C-style casts removing const, you can never modify a const object through those const pointers or references.
The value of const-correctness -- const is there, in large part, to detect programmer errors. If you declare something as const, you're stating that you don't think it should be modified -- or at least, those with access to the const version only should not be able to modifying it. Consider:
void foo(const int*);
As declared, foo doesn't have permission to modify the integer pointed to by its argument.
If you're not sure why the code you posted isn't const-correct, consider the following code, only slightly different from HappyDude's code:
char *y;
char **a = &y; // a points to y
const char **b = a; // now b also points to y
// const protection has been violated, because:
const char x = 42; // x must never be modified
*b = &x; // the type of *b is const char *, so set it
// with &x which is const char* ..
// .. so y is set to &x... oops;
*y = 43; // y == &x... so attempting to modify const
// variable. oops! undefined behavior!
cout << x << endl;
Non-const types can only convert to const types in particular ways to prevent any circumvention of const on a data-type without an explicit cast.
Objects initially declared const are particularly special -- the compiler can assume they never change. However, if b can be assigned the value of a without a cast, then you could inadvertently attempt to modify a const variable. This would not only break the check you asked the compiler to make, to disallow you from changing that variables value -- it would also allow you break the compiler optimizations!
On some compilers, this will print 42, on some 43, and others, the program will crash.
Edit-add:
HappyDude: Your comment is spot on. Either the C langauge, or the C compiler you're using, treats const char * const * fundamentally differently than the C++ language treats it. Perhaps consider silencing the compiler warning for this source line only.
This is annoying, but if you're willing to add another level of redirection, you can often do the following to push down into the pointer-to-pointer:
char c = 'c';
char *p = &c;
char **a = &p;
const char *bi = *a;
const char * const * b = &bi;
It has a slightly different meaning, but it's usually workable, and it doesn't use a cast.
I'm not able to get an error when implicitly casting char** to const char * const *, at least on MSVC 14 (VS2k5) and g++ 3.3.3. GCC 3.3.3 issues a warning, which I'm not exactly sure if it is correct in doing.
test.c:
#include <stdlib.h>
#include <stdio.h>
void foo(const char * const * bar)
{
printf("bar %s null\n", bar ? "is not" : "is");
}
int main(int argc, char **argv)
{
char **x = NULL;
const char* const*y = x;
foo(x);
foo(y);
return 0;
}
Output with compile as C code: cl /TC /W4 /Wp64 test.c
test.c(8) : warning C4100: 'argv' : unreferenced formal parameter
test.c(8) : warning C4100: 'argc' : unreferenced formal parameter
Output with compile as C++ code: cl /TP /W4 /Wp64 test.c
test.c(8) : warning C4100: 'argv' : unreferenced formal parameter
test.c(8) : warning C4100: 'argc' : unreferenced formal parameter
Output with gcc: gcc -Wall test.c
test2.c: In function `main':
test2.c:11: warning: initialization from incompatible pointer type
test2.c:12: warning: passing arg 1 of `foo' from incompatible pointer type
Output with g++: g++ -Wall test.C
no output
I'm pretty sure that the const keyword does not imply the data can't be changed/is constant, only that the data will be treated as read-only. Consider this:
const volatile int *const serial_port = SERIAL_PORT;
which is valid code. How can volatile and const co-exist? Simple. volatile tells the compiler to always read the memory when using the data and const tells the compiler to create an error when an attempt is made to write to the memory using the serial_port pointer.
Does const help the compiler's optimiser? No. Not at all. Because constness can be added to and removed from data through casting, the compiler cannot figure out if const data really is constant (since the cast could be done in a different translation unit). In C++ you also have the mutable keyword to complicate matters further.
char *const p = (char *) 0xb000;
//error: p = (char *) 0xc000;
char **q = (char **)&p;
*q = (char *)0xc000; // p is now 0xc000
What happens when an attempt is made to write to memory that really is read only (ROM, for example) probably isn't defined in the standard at all.
This code does not compile on VS2010:
struct Point {
float x;
float y;
};
void do_something(Point p) {
// something happens here
}
int main(int argc, char **argv) {
do_something({10, 11});
}
Are there any versions of C++ where this is legal syntax?
This looks like aggregate initialization to me. It should work in VS2013.
EDIT: Confirmed, this should work on a c++11 compiler.
Also, it isn't an array literal, it's aggregate initialization. You can find the rules on it here and here.
You might be able to download a newer compiler and run it on the older IDE, but short of that I don't think VS2010 can run this.
This code was provided by my c++ instructor on a sample midterm. We covered argc and argv on a very basic level, so I understand what those expressions alone mean. However, any additions to those like the dereference operator and '++' confuse me and what I've googled hasn't been clear enough for me to apply it to this specific example. Also, when I try to compile, it provides this error:
In function 'int summer(int*, char**)':
Line 9: error: cannot convert 'char**' to 'const char*' for argument '1' to 'int atoi(const char*)'
compilation terminated due to -Wfatal-errors.
We haven't officially covered pointers, but I think I understand them well enough. char** means you're dereferencing twice, so the value of the pointer char, which is a pointer to something else, so the second * means we want the value of that. Is it constant because we are relying on something input in the command line and that can't be changed? I don't understand this.
#include <iostream>
using namespace std;
int summer(int *acc, char * ptr[])
{
register int n;
n = atoi(ptr);
*acc = *acc + n;
}
main(int argc, char * argv [])
{
int sum = 0;
while (--argc)
summer(&sum, *++argv);
cout << "sum is " << sum << endl;
}
Another question: When passing *++argv to summer(), does that mean the value of (argv[] + 1)? What would that even be? Adding the value one to the entire vector? I know that atoi(array) means changing the string into a numerical value, and then we are storing that in register int 'n', and then adding that to the sum which is directly changed in main. And that's about the only part of this code I really understand. Sorry if my questions/this post is kind of a mess.
To sum up what my questions are:
What does the compiling error message mean?
What does ++argv do?
Thank you.
Edited:
Okay, I've made the changes you guys have suggested (thank you!!):
#include <iostream>
using namespace std;
int summer(int *acc, char * ptr)
{
register int n;
n = atoi(ptr);
*acc = *acc + n;
return 0;
}
int main(int argc, char * argv[])
{
int sum = 0;
while (--argc)
summer(&sum, *++argv);
cout << "sum is " << sum << endl;
return 0;
}
I also added the returns because the compiler gave a new error due to no return value for the function type. On Codepad it compiles and prints "the sum is zero," however, it still does not compile on Dev C++ 5.7.1 which is what I am using. It doesn't display error messages (the ones I have been reading are from Codepad online compiler), or at least I can't find where to turn them on. It just highlights the lines it seems to have a problem with, and that is still the line with atoi(ptr).
*argv is equivalent to argv[0], so ++argv; would make *argv equivalent to what was originally argv[1]. So *++argv evaluates to the same thing as argv[1] (the first command line argument, after the name of the program itself), except it increments argv whereas argv[1] obviously does not.
For your error, you should change:
int summer(int *acc, char * ptr[])
{
to:
int summer(int *acc, char * ptr)
{
When you dereference a char **, which is the type of argv, you get a char *. char * is what atoi() is expecting.
Your program is essentially equivalent to this:
#include <iostream>
#include <cstdlib>
using namespace std;
void summer(int * acc, char * ptr)
{
*acc += atoi(ptr);
}
int main(int argc, char * argv [])
{
int sum = 0;
for ( int i = 1; i < argc; ++i ) {
summer(&sum, argv[i]);
}
cout << "sum is " << sum << endl;
}
except that your's doesn't check for troublesome values of argc.
The ++ is called the increment operator. It usually adds 1 to something.
The argv decays to a pointer that points to a container of arguments to your program.
The expression ++argv points to next parameter, if there is one.
Incrementing a pointer means to make it point to the next item in the list.
argv has type char ** (don't be distracted by the square brackets), meaning it points to a char * which is in a list of adjacent char *s. The argc parameter lets us know where to find the end of said list.
So, doing ++argv means that argv will now point to the next char * in the list. Applying * to that (and passing the result to a function) means that we send the value of the next char * in the list to that function.
The result of all this is that the function is called once for each argument, excluding the first one (since we ++'d before dereferencing the first time).
NB. This code actually has a bug; if argc == 0 it will go off into la-la land. It should check for this case before entering the loop.
Is it constant because we are relying on something input in the command line and that can't be changed?
No, the const char * bit refers to the type of argument that atoi() accepts. It is a pointer to a constant char. Note that char * is implicitly convertible to const char *, but not the opposite.
All this means is that atoi() accepts a pointer to a character, and it promises that it will not modify the target of the pointer.
My guess is that the ptr argument should have been char * ptr instead of char * ptr[]. If you change that, the code should compile.
Is there a way to define a global variable by user input?
Lets say I use
#include...
#define N 12
double array[N][N];
void main();...
But I would like the user to be able to choose what N is.
Do I have to have N as a local variable or is there a way around this(without macros)?
I've a pretty small program but with a lot of different variables that need the N value.
Alternatively,
is there a way I could send a group of variables into a function without having to explicitly write them out every time.
for example
myfunction(var1,var2,var3...)
and instead write something like
myfunction(Allvariables)
Thanks a lot for Your answers!
This is a great forum.
int* data;
int main()
{
int n;
// get n from the user.
data = new int[n];
// use data.
.
.
delete[] data;
}
or just forget pointers for ever and use vector!
std::vector<int> data;
data.push_back(55);
// just push_back data!
=======================================================================
EDIT ::
If you want to use Edouard A. way :)
#include <iostream>
#include <sstream>
#include <vector>
int main(int argc, char* argv[])
{
std::vector<double>::size_type dataSize = 0;
std::stringstream convertor(argv[1]);
{
if(argc > 1)
{
convertor >> dataSize;
if(convertor.fail() == true)
{
// do whatever you want here in case
// the user didn't input a number.
}
}
}
std::vector<double> data(dataSize);
// use the vector here.
return 0;
}
I prefere to use lexical_cast in this case, but I am not sure if you have Boost.
#include <iostream>
#include <vector>
#include <boost/lexical_cast.hpp>
int main(int argc, char* argv[])
{
typedef std::vector<double>::size_type vectorSize;
if(argc < 2)
{
// err! The user didn't input anything.
}
vectorSize dataSize = boost::lexical_cast<vectorSize>(argv[1]);
std::vector<double> data(dataSize);
// use the vector here.
return 0;
}
1/ Yes but you need dynamic memory allocation. The program parameters are passed as argc and argv to the main function
int main(int argc, char **argv)
argc is the number of parameters
argv is the array of null terminated strings representing these arguments
argv[0] is the program itself.
2/You can either use variadic function va_start & the like, or functions overriding, or group your data in a structure and pass that to the function
No, that can't be done this way. You need to use dynamic (runtime) memory allocation (new[]). To perform static (compile-time) memory allocation the compiler needs to know the memory block size at compile time.
I'm not really sure what you're trying to do with myFunction but it sounds like you want to look at either creating a struct or pass a std::vector
Make a class (or struct) AllVariables and pass that in.
You don't say whether you want N defined at run time or compile time. If you want it defined at compile time, you can define N as a compiler command line arguement.