Warning "might be clobbered" on C++ object with setjmp - c++

#include <setjmp.h>
#include <vector>
int main(int argc, char**) {
std::vector<int> foo(argc);
jmp_buf env;
if (setjmp(env)) return 1;
}
Compiling the above code with GCC 4.4.1, g++ test.cc -Wextra -O1, gives this confusing warning:
/usr/include/c++/4.4/bits/stl_vector.h: In function ‘int main(int, char**)’:
/usr/include/c++/4.4/bits/stl_vector.h:1035: warning: variable ‘__first’ might be clobbered by ‘longjmp’ or ‘vfork’
Line 1035 of stl_vector.h is in a helper function used by the vector(n, value) constructor that I invoke while constructing foo. The warning disappears if the compiler can figure out the argument value (e.g. it is a numeric literal), so I use argc in this test case because the compiler cannot determine the value of that.
I guess the warning might be because of compiler optimizing the vector construction so that it actually happens after the setjmp landing point (which seems to be the case here when the constructor argument depends on a parameter of the function).
How can I avoid the problem, preferably without having to break the setjmp part to another function?
Not using setjmp is not an option because I am stuck with a bunch of C libraries that require using it for error handling.

The rule is that any non-volatile, non-static local variable in the stack frame calling setjmp might be clobbered by a call to longjmp. The easiest way to deal with it is to ensure that the frame you call setjmp doesn't contain any such variables you care about. This can usually be done by putting the setjmp into a function by itself and passing in references to things that have been declared in another function that doesn't call setjmp:
#include <setjmp.h>
#include <vector>
int wrap_libcall(std::vector<int> &foo)
{
jmp_buf env;
// no other local vars
if (setjmp(env)) return 1;
// do stuff with your library that might call longjmp
return 0;
}
int main(int argc, char**) {
std::vector<int> foo(argc);
return wrap_libcall(foo);
}
Note also that in this context, clobbering really just means resetting to the value it had when setjmp was called. So if longjmp can never be called after a modification of a local, you're ok too.
Edit
The exact quote from the C99 spec on setjmp is:
All accessible objects have values, and all other components of the abstract machine
have state, as of the time the longjmp function was called, except that the values of
objects of automatic storage duration that are local to the function containing the
invocation of the corresponding setjmp macro that do not have volatile-qualified type
and have been changed between the setjmp invocation and longjmp call are
indeterminate.

This is not a warning that you should ignore, longjmp() and C++ objects don't get along with each other. The problem is that the compiler automatically emits a destructor call for your foo object. A longjmp() can bypass the destructor call.
C++ exceptions unwind stack frames too but they guarantee that destructors of local objects will be called. No such guarantee from longjmp(). Finding out if longjmp() is going to byte you requires carefully analyzing the local variables in each function which might be terminated early due to the longjmp(). That's not easy.

As evidenced by the line number 1035 in the error message, your code snippet has considerably simplified the actual problem code. You went too far. There is no clue as to how you are using 'first'. The problem is that the compiler can't figure that out even in the real code. It is afraid that the value of 'first' after a non-zero return from 'setjmp' may not be what you think it is. This is because you changed its value both before and after the first call (zero return) to 'setjmp'. If the variable was stored in a register, the value will probably be different than if it were stored in memory. So the compiler is being conservative by giving you the warning.
To take a blind leap and answer the question, you may be able to get rid of the warning message by qualifying the declaration of 'first' with 'volatile'. You could also try making 'first' global. Perhaps by dropping the optimization level (-O flag), you could cause the compiler to keep variables in memory. These are quick fixes, and may actually hide a bug.
You should really take a look at your code, and how you are using 'first'. I'll take another wild guess, and say you may be able to eliminate that variable. Could that name, 'first', mean you are using it to indicate a first call (zero return) to 'setjmp'? If so, get rid of it - redesign your logic.
If the real code just exits on a non-zero return from 'setjmp' (as in the snippet), then the value of 'first' doesn't matter in that logic path. Don't use it on both sides of the 'setjmp'.

The quick answer: drop the -O1 flag or regress the compiler to an earlier version. Either one made the warning disappear on my system. I had to build and use gcc4.4 to get the warning in the first place. (darn that's a huge system)
No? I thought not.
I really don't understand everything C++ does with its objects, and exactly how they are deallocated. Yet OP's comment that the problem didn't occur if a constant value were used in place of 'argc' for the vector size gives me an opportunity to stick my neck out. I'll hazard a guess that C++ uses the '__first' pointer on deallocation only when the initial allocation is not a constant. At the higher level of optimization, the compiler uses the registers more and there is a conflict between the pre- and post-setjmp allocations ... I don't know, it makes no sense.
The general meaning of this warning is "Are you sure you know what you are doing?" The compiler doesn't know if you know what the value of '__first' will be when you do the longjmp, and get a non-zero return from 'setjmp'. The question is whether its value after the (non-zero) return is the value that was put into the save buffer, or the value that you created after the save. In this case, it's confusing because you didn't know you were using '__first', and because in such a simple program, there is no (explicit) change to '__first'
The compiler can't analyze logic flow in a complex program, so it apparently doesn't even try for any program. It allows for the possibility that you did change the value. So it just gives you a friendly 'heads-up'. The compiler is second guessing you, trying to be helpful.
If you are stubborn with your choice of compiler and optimization, there is a programming fix. Save the environment before the allocation of the vector. Move the 'setjmp' up to the top of the program. Depending on the vector use and the error logic in the real program, this may require other changes.
edit 1/21 -------
my justification (using g++-mp-4.4 -Wextra -O1 main.cpp):
#include <setjmp.h>
#include <vector>
#include <iostream>
int main(int argc, char**) {
jmp_buf env;
int id = -1, idd = -2;
if ((id=setjmp(env)))
idd = 1;
else
idd = 0;
std::cout<<"Start with "<< id << " " << idd <<std::endl;
std::vector<int> foo(argc );
if(id != 4)
longjmp(env, id+1);
std::cout<<"End with "<< id << " " << idd <<std::endl;
}
No warnings; a.out produced:
Start with 0 0
Start with 1 1
Start with 2 1
Start with 3 1
Start with 4 1
End with 4 1

Related

c++, how do I create thread-restricted/protected variables and functions?

I have three threads in an application I'm building, all of which remain open for the lifetime of the application. Several variables and functions should only be accessed from specific threads. In my debug compile, I'd like a check to be run and an error to be thrown if one of these functions or variables is accessed from an illegal thread, but I don't want this as overhead in my final compilation. I really just want this so I the programmer don't make stupid mistakes, not to protect my executing program from making mistakes.
Originally, I had a 'thread protected' class template that would wrap around return types for functions, and run a check on construction before implicitly converting to the intended return type, but this didn't seem to work for void return types without disabling important warnings, and it didn't resolve my issue for protected variables.
Is there a method of doing this, or is it outside the scope of the language? 'If you need this solution, you're doing it wrong' comments not appreciated, I managed to near halve my program's execution time with this methodology, but it's just too likely I'm going to make a mistake that results in a silent race condition and ultimately undefined behavior.
What you described is exactly what assert macro is for.
assert(condition)
In a debug build condition is checked. If it is false, the program will throw an exception at that line. In a release build, the assert and whatever is inside the parentheses aren't compiled.
Without being harsh, it would have been more helpful if you had explained the variables you are trying to protect. What type are they? Where do they come from? What's their lifetime? Are they global? Why do you need to protect a returned type if it's void? How did you end up in a situation where one thread might accidentally access something. I kinda have to guess but I'll throw out some ideas here:
#include <thread>
#include <cassert>
void protectedFunction()
{
assert(std::this_thread::get_id() == g_thread1.get_id());
}
// protect a global singleton (full program lifetime)
std::string& protectedGlobalString()
{
static std::string inst;
assert(std::this_thread::get_id() == g_thread1.get_id());
return inst;
}
// protect a class member
int SomeClass::protectedInt()
{
assert(std::this_thread::get_id() == g_thread1.get_id());
return this->m_theVar;
}
// thread protected wrapper
template <typename T>
class ThreadProtected
{
std::thread::id m_expected;
T m_val;
public:
ThreadProtected(T init, std::thread::id expected)
: m_val(init), m_expected(expected)
{ }
T Get()
{
assert(std::this_thread::get_id() == m_expected);
return m_val;
}
};
// specialization for void
template <>
class ThreadProtected<void>
{
public:
ThreadProtected(std::thread::id expected)
{
assert(std::this_thread::get_id() == expected);
}
};
assert is oldschool. We were actually told to stop using it at work because it was causing resource leaks (the exception was being caught high up in the stack). It has the potential to cause debugging headaches because the debug behavior is different from the release behavior. A lot of the time if the asserted condition is false, there isn't really a good choice of what to do; you usually don't want to continue running the function but you also don't know what value to return. assert is still very useful when developing code. I personally use assert all the time.
static_assert will not help here because the condition you are checking for (e.g. "Which thread is running this code?") is a runtime condition.
Another note:
Don't put things that you want to be compiled inside an assert. It seems obvious now, but it's easy to do something dumb like
int* p;
assert(p = new(nothrow) int); // check that `new` returns a value -- BAD!!
It's good to check the allocation of new, but the allocation won't happen in a release build, and you won't even notice until you start release testing!
int* p;
p = new(nothrow) int;
assert(p); // check that `new` returns a value -- BETTER...
Lastly, if you write the protected accessor functions in a class body or in a .h, you can goad the compiler into inlining them.
Update to address the question:
The real question though is where do I PUT an assert macro? Is a
requirement that I write setters and getters for all my thread
protected variables then declare them as inline and hope they get
optimised out in the final release?
You said there are variables that should be checked (in the debug build only) when accessed to make sure the correct thread is accessing them. So, theoretically, you would want an assert macro before every such access. This is easy if there are only a few places (if this is the the case, you can ignore everything I'm about to say). However, if there are so many places that it starts to violate the DRY Principal, I suggest writing getters/setters and putting the assert inside (This is what I've casually given examples of above). But while the assert won't add overhead in release mode (since it's conditionally compiled), using extra functions (probably) adds function call overhead. However, if you write them in the .h, there's a good chance they'll be inlined.
Your requirement for me was to come up with a way to do this without release overhead. Now that I've mentioned inlining I'm obligated to say that the compiler knows best. There usually are compiler-specific ways to force inlining (since the compiler is allowed to ignore the inline keyword). You should be profiling the code before trying to inline things. See the answer to this question. Is it good practice to make getters and setters inline?. You can easily see if the compiler is inlining the function by looking at the assembly. Don't worry, you don't have to be good at assembly. Just find the calling function and look for a call to the getter/setter. If the function was inlined, you won't see a call and you'll see probably a mov instead.

C++ `if` seems to be taking the wrong branch?

I'm struggling with a non-sensical if statement...
Consider this code in a C++ file
if (coreAudioDevice) {
delete coreAudioDevice;
coreAudioDevice = nullptr;
}
coreAudioDevice = AudioDevice::GetDevice(defaultOutputDeviceID, false, coreAudioDevice, true);
if (coreAudioDevice)
{
coreAudioDevice->setDefaultDevice(true);
// we use the quick mode which skips initialisation; cache the device name (in AudioDevice)
// using an immediate, blocking look-up.
char devName[256];
coreAudioDevice->GetName(devName, 256);
AUDINFO ("Using default output device %p #%d=\"%s\".\n",
defaultOutputDeviceID, coreAudioDevice, coreAudioDevice->GetName());
}
else
AUDERR ("Failed to obtain a handle on the default device (%p)\n", coreAudioDevice);
calling a function in an ObjC++ file:
AudioDevice *AudioDevice::GetDevice(AudioObjectID devId, bool forInput, AudioDevice *dev, bool quick)
{
if (dev) {
if (dev->ID() != devId) {
delete dev;
} else {
return nullptr;
}
}
dev = new AudioDevice(devId, quick, forInput);
return dev;
}
Which leads to the following terminal output:
ERROR coreaudio.cc:232 [init]: Failed to obtain a handle on the default device (0x7f81a1f1f1b0)
Evidently the if shouldn't fail because coreAudioDevice supposedly is NULL and then print a non-null value for this variable in the else branch.
I tried different compiler options and a different compiler (clang 4.0.1 vs. 5.0.1), apparently there is really something fishy in my code. Any thoughts?
Reaching the end of the function without returning a value is undefined behavior in C++.
See http://en.cppreference.com/w/cpp/language/ub and What are all the common undefined behaviours that a C++ programmer should know about?.
So the call setDefaultDevice() can legally result in anything. The compiler is free to compile the program into an executable that can do anything, when the program's control flow leads to undefined behavior (i.e. the call to setDefaultDevice()).
In this case, entering the if block with coreAudioDevice non-zero leads to UB. So the optimizing compiler foresees this and chooses to then make it go into the else branch instead. Like this it can remove the first branch and the if entirely, to produce more optimized code.
See https://blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p=633
Without optimizations the program should normally run as expected.
Well, at least I found a reason, but no understanding (yet).
I had defined this method, without noticing the compiler warning (amidst a bunch of deprecation warnings printed multiple times because of concurrent compilation...):
bool setDefaultDevice(bool isDefault)
{
mDefaultDevice = isDefault;
}
Indeed, no return value.
Notice that I call this method inside the skipped if block - so theoretically I never got the chance to do that. BTW, it's what led me to discover this strange issue.
The issue goes away when I remove the call or when I make the method void as intended.
I think this also explains the very strange way of crashing I've seen: somehow the optimiser gets completely confused because of this. I'm tempted to call this a compiler bug; I don't use the return value from the method, so flow shouldn't be affected at all IMHO.
Ah, right. Should I read that as "free to build an exec that can do anything EXCEPT the sensical thing"? If so, that former boss of mine had a point banning C++ as an anomaly (the exact word was French, "saleté")...
Anyway, I can understand why the behaviour would be undefined when you don't know a function doesn't actually put a return value on the stack. You'd be popping bytes off the stack after the return, messing things up. (Read heap for stack if necessary =] ). I'm guessing that's what would happen when you run this kind of code without optimisation, in good ole C or with the bugggy method defined out of line (so the optimiser cannot know that it's buggy).
But once you know that a function doesn't actually return a value and you see that the value wouldn't be used anyway, you should be able to emit code that doesn't pop the corresponding number of bytes. IOW, code that behaves as expected. With a big fat compile-time warning. Presuming the standard allows this that'd be the sensical thing to do, rather than optimise the entire tainted block away because that'd be faster. If that's indeed the reasoning followed in clang it doesn't actually inspire confidence...
Does the standard say this cannot be an error by default? I'd certainly prefer that over the current behaviour!

C++ implicit return type in recursive function, how does this work [duplicate]

I was shown a sample program to demonstrate recursion which looks like it should not work but does. The logic is pretty clear but why does it work even when the recursed function call is not returned? It seems like the return command breaks out of the stack even if it isn't requested to. Is this a language standard or a gcc thing? I saw it with C and C++ compiled with gcc on Windows and Linux.
#include <iostream>
#include <cstdlib>
using namespace std;
int isprime(int num, int i)
{
if (i == 1) {
return 1;
}
else {
if (num % i == 0)
return 0;
else
isprime(num, i-1); // should be returned
}
}
int main(int argc, char** argv)
{
int input = atoi(argv[1]);
cout << input << "\t" << isprime(input, input/2) << "\n";
}
Things like that only work if accidentally the return value happens to be in the register where the caller expects it. This only works if this is realized by your compiler as a recursive function. Technically it is undefined behavior to use the return value of a function that doesn't provide one.
Edit: On modern architectures the return value of a function for values for which it is possible is passed in a specific hardware register. When you call your function recursively, on the bottom in all cases that hardware register is set to the expect value. If by chance when popping up from recursion that hardware register is never changed, you end up with the correct value.
All of this pattern wouldn't work, if the return value would be placed at some location of the stacks of the (recursive) callers.
In any case, all of that should be captured by any modern compiler and give you a warning. If it doesn't you don't have a good compiler, or you are using too defensive command line options.
New year's eve special: In the real world, code like this (with the return) wouldn't even be realized as a recursive function. With not too much effort you will find an iterative variant of that function, and any modern decent compiler should be able to find it as well if you ask for maximal optimization.
A lot here depends what you mean by "it works"?
to try and answer the main point of your question, functions will return when the end of the function is reached, whether or not a return statement is met.
I would expect to see compiler warnings telling you the possible controls paths may not return a value, in C++ at any rate. Resulting in undefined behaviour, see this question:
not returning a value from a non-void returning function
I would say that this example "works" as after a prime is found and isPrime has returned, then the next function up the stack is also free to return. Nothing depends on the return value of isPrime either, so the program will run back up the stack and output something.
...but as behaviour is undefined, the value that actually gets output is likely to be junk. If you are seeing 0 & 1 consistent with primes as input, then wow.
If you think this is working, I would look at testing more broadly with different values.
Also have you been building with any "debug" settings? if so try this again with debug settings off, as thiese sometimes do extra work to keep things uninitialised memory clean.
I can explain exactly what happens:
The function is called, and it recurses back into itself until it reaches the return at either modulo (return 0) or end of recursion (return 1). At this point the function reuturns to the caller, which is is_prime. But there is no more code in the function to execute, so it immediately returns without any further action.
However, you could easily break this by, for example, add printf("Done for %d, %d\n", num, i); behind the call of is_prime() [doesn't have to be in the if-statement]. Or adding a C++ object that is created and destroyed on entry/exit of the function, as another example.
You're just being lucky that it works. And it's very fragile and easy to break - compile it with a different compiler (or with different optimization settings, or a new version of the compiler, or a million other things), and it may well break.
Aren't you forgetting a return statement? For normal recursion you need to put a return before isprime(num,i-1); as well.
I guess this even should give a compile warning if you compile this using strict rules, because the function must always return an int, now it does not (at least if your compiler does not fix this).

c++ recursive return function Without return [duplicate]

I was shown a sample program to demonstrate recursion which looks like it should not work but does. The logic is pretty clear but why does it work even when the recursed function call is not returned? It seems like the return command breaks out of the stack even if it isn't requested to. Is this a language standard or a gcc thing? I saw it with C and C++ compiled with gcc on Windows and Linux.
#include <iostream>
#include <cstdlib>
using namespace std;
int isprime(int num, int i)
{
if (i == 1) {
return 1;
}
else {
if (num % i == 0)
return 0;
else
isprime(num, i-1); // should be returned
}
}
int main(int argc, char** argv)
{
int input = atoi(argv[1]);
cout << input << "\t" << isprime(input, input/2) << "\n";
}
Things like that only work if accidentally the return value happens to be in the register where the caller expects it. This only works if this is realized by your compiler as a recursive function. Technically it is undefined behavior to use the return value of a function that doesn't provide one.
Edit: On modern architectures the return value of a function for values for which it is possible is passed in a specific hardware register. When you call your function recursively, on the bottom in all cases that hardware register is set to the expect value. If by chance when popping up from recursion that hardware register is never changed, you end up with the correct value.
All of this pattern wouldn't work, if the return value would be placed at some location of the stacks of the (recursive) callers.
In any case, all of that should be captured by any modern compiler and give you a warning. If it doesn't you don't have a good compiler, or you are using too defensive command line options.
New year's eve special: In the real world, code like this (with the return) wouldn't even be realized as a recursive function. With not too much effort you will find an iterative variant of that function, and any modern decent compiler should be able to find it as well if you ask for maximal optimization.
A lot here depends what you mean by "it works"?
to try and answer the main point of your question, functions will return when the end of the function is reached, whether or not a return statement is met.
I would expect to see compiler warnings telling you the possible controls paths may not return a value, in C++ at any rate. Resulting in undefined behaviour, see this question:
not returning a value from a non-void returning function
I would say that this example "works" as after a prime is found and isPrime has returned, then the next function up the stack is also free to return. Nothing depends on the return value of isPrime either, so the program will run back up the stack and output something.
...but as behaviour is undefined, the value that actually gets output is likely to be junk. If you are seeing 0 & 1 consistent with primes as input, then wow.
If you think this is working, I would look at testing more broadly with different values.
Also have you been building with any "debug" settings? if so try this again with debug settings off, as thiese sometimes do extra work to keep things uninitialised memory clean.
I can explain exactly what happens:
The function is called, and it recurses back into itself until it reaches the return at either modulo (return 0) or end of recursion (return 1). At this point the function reuturns to the caller, which is is_prime. But there is no more code in the function to execute, so it immediately returns without any further action.
However, you could easily break this by, for example, add printf("Done for %d, %d\n", num, i); behind the call of is_prime() [doesn't have to be in the if-statement]. Or adding a C++ object that is created and destroyed on entry/exit of the function, as another example.
You're just being lucky that it works. And it's very fragile and easy to break - compile it with a different compiler (or with different optimization settings, or a new version of the compiler, or a million other things), and it may well break.
Aren't you forgetting a return statement? For normal recursion you need to put a return before isprime(num,i-1); as well.
I guess this even should give a compile warning if you compile this using strict rules, because the function must always return an int, now it does not (at least if your compiler does not fix this).

small classes how to pass by value and register

I need to use small classes formed essentially from just an integer "handle" and be able to treat that as a class in order to be able to attach methods to it.
At the same time I want also to avoid to pass from one function to the other just the address of the handle ( the "this" pointer) because doing so means that in order to read a handle that should just be there I would need to read a memory location to have it.
So I need essentially to have the "handle" passed by value eventually in registers ( depending on calling convention ).
Some clarifying code is:
struct F{
int aa,bb,cc;};
F A[0x100];
struct handle{
int hhh;
void elaborateHandle(){ ... operations ;}
};
int main(){
handle h;h.hhh=3;
h.elaborateHandle();
// I need that call to pass on the stack essentially the number 3 and not the address of where the number 3 was saved on the stack.
}
I think, that you shouldn't think about it, because here you are having a very very small performance lose, dereferencing one pointer is a cheap operation.
If you use optimizing compiler, there is a chance, that your method call will be inlined inside caller func.
Anyways, if you trying to optimize your performance, you should search in other place.
But if you really thinking that it causes troubles there is a way:
Declare the function outside your class (not as member), and if you want to access private data declare it as friend.
First, print the assembly language of the code that calls your function and the first part of your function.
The assembly language will show how the registers are used. Normally, compilers try to make best use of registers when passing values to functions.
To help the compiler better use registers:
Limit parameter quantities in functions.
The compiler reserves a limited quantity of registers for passing to functions. The more parameters a function has, the less probability that all parameters will be in registers.
Also, the compiler may need to save registers before calling a function in order to pass more parameters to the function.
Pass values that fit inside registers.
If the compiler can't fit a data type in one register, it may use two registers (such as passing 64 bit values on a 32-bit processor).
If the compiler can't fit the data type in two registers, it may push the data on the stack rather than passing by register. This means that the receiving function will have to copy the values from the stack.
Pass large items by reference or pointer. On most platforms, the compiler can store a pointer into a register and pass the register to the receiving function. A lot faster that pushing and popping values with a stack. Also, compilers may use pointers to implement references.
Suggest to the compiler to place values in registers.
Although the register keyword may not be available in more recent language versions, using the register keyword with variables suggests to the compiler that you would like to have the variable in a register. It is only a suggestion and the compiler can ignore it and you.
Define variables as close to their point of usage. This allows the compiler to allocate registers when needed rather than reserving them for a while.
Create scope blocks. Using { and } to create new scope blocks will help the compiler allocate and deallocate registers that are used only in a limited area. So if variables are only used in a limited area in a function, place that area in a new scope block. You can even tag those local variable with the register keyword.
Compile with high optimization levels.
Set your compiler's optimization levels high, then check the assembly language.
The compiler may use memory for variable storage when optimization is at the lowest setting (debugging). At higher optimization levels, the compiler starts using registers more effectively.
Remember, print the assembly language of the functions and the calling code before and after playing with optimization levels.
Using the g++ compiler on the x86 platform, I found that the flag "-freg-struct-return" has a different effect that described in the documentation. According to my tests, that flag, obliges the compiler to pass structures by value ( I didn't checked it but it will be probably be valid when structures have a size smaller than a specific size -- I checked up to 64 bits and it works compiling using -m32 ).
Differently from what the documentation says, structs aren't passed in registers, unless a register passing convention in used.
That behaviour is valid also for declared or compiler recognized const methods of structures ( or classes ).
So if a method doesn't change the structure, than the structure is passed by value ( in stack allocated space or in registers depending e.g. on defining a function using the __attributes__ (( regparam(3) )) .
Instead as it should be, if a structure is modified by a method, than the address is passed to the method instead of the value of the struct ( as it should be ).
The documentation of that flag is misleading because it says: "Return struct and union values in registers when possible. This is more efficient for small structures than -fpcc-struct-return.
If you specify neither -fpcc-struct-return nor -freg-struct-return, GCC defaults to whichever convention is standard for the target. If there is no standard convention, GCC defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler. In those cases, we can choose the standard, and we chose the more efficient register return alternative."
The testing code I used is bellow, the effects may be seen by seeing what the disassemler shows.
#include <stdio.h>
int a;
int aa[100];
struct Token{
short int ind; short int ind1; short int ind2;
int v() const{return aa[ind];}
__attribute((noinline)) void setind(int i){ind=i;}
__attribute((noinline)) int tok() {return ind;}
};
__attribute__ ((noinline)) void showIt(Token t){
t.ind+=t.ind;
a+=t.ind;
t.ind=8;
}
Token t0 = {.ind=15};
Token t1 = {.ind=99};
int main(int argc, char **argv)
{
t0.setind(10);
int x=19;
x=t0.tok();
showIt(t0);
t1.setind(20+x);
showIt(t1);
printf("%i\n",a);
return 0;
}