Implementing exceptions of C++ in C

B

Bernard

Hi All,

I am not sure if I should be asking this question on clc or clc++. Let me try on
both. I hope that this is not too trivial for the brilliant minds over here.
I know that OOP questions have been asked on clc before so it is probably OK.

I am a newbie to C++. BS 3rd edition states:

% The throw transfers control to a handler for exceptions ....
%
% ... the implementation will unwind the function call stack as needed to get
% back to the context of that caller. Thus throw acts as a multilevel return.

My mind is so C-ish that I totally fail to comprehend what is going on.
My dumb brain has these pre-reqs. Explain the usage and idea of

throw
exception
try
catch

with a C++ code and a parallel code in C. If it must involve goto's, go ahead.
But the translation must be as highly parallel as possible. Furthermore, if
you have some way to depict this, and supplement by "function call stack"
diagrams, all the better.

Thanks++,

--

,--. Bernard Klein, Berlin, Germany ,= ,-_-. =.
/ ,- ) ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. \_/
 
I

Ian

Bernard said:
Hi All,

I am not sure if I should be asking this question on clc or clc++. Let me try on
both. I hope that this is not too trivial for the brilliant minds over here.
I know that OOP questions have been asked on clc before so it is probably OK.

I am a newbie to C++. BS 3rd edition states:

% The throw transfers control to a handler for exceptions ....
%
% ... the implementation will unwind the function call stack as needed to get
% back to the context of that caller. Thus throw acts as a multilevel return.

My mind is so C-ish that I totally fail to comprehend what is going on.
My dumb brain has these pre-reqs. Explain the usage and idea of

throw
exception
try
catch

with a C++ code and a parallel code in C. If it must involve goto's, go ahead.
But the translation must be as highly parallel as possible. Furthermore, if
you have some way to depict this, and supplement by "function call stack"
diagrams, all the better.
I don't think there is a clean way of replicating this in C. Otherwise
we'd all be doing it! It requires run time support in C++, so you can't
make a stand alone C++ app with exceptions, you have to link a run time.

Also C doen't create "Objects" in the C++ sense (no concept of a
destructor), so you can't destroy them as the stack is unwound.

Ian
 
M

Malcolm

Ian said:
I don't think there is a clean way of replicating this in C. Otherwise
we'd all be doing it! It requires run time support in C++, so you
can't make a stand alone C++ app with exceptions, you have to
link a run time.
That might be true on your platform, because exceptions require a lot of
extra code which might be in a library somewhere. However there is no
inherent reason why C++ program including exceptions can't be standalone
exectutables.
Also C doen't create "Objects" in the C++ sense (no concept of a
destructor), so you can't destroy them as the stack is unwound.
This is the problem. It is extremely difficult to implement exception
handling in C, certainly in any form that is human-usable.
 
J

James Hu

I am a newbie to C++. BS 3rd edition states:

% The throw transfers control to a handler for exceptions ....
%
% ... the implementation will unwind the function call stack as needed to get
% back to the context of that caller. Thus throw acts as a multilevel return.

My mind is so C-ish that I totally fail to comprehend what is going on.

My dumb brain has these pre-reqs. Explain the usage and idea of

throw
exception
try
catch

with a C++ code and a parallel code in C.

See: http://www.nicemice.net/cexcept/

-- James
 
B

Bernard

Thus far, all replies are useful but let me explain ...

OK, if you cannot write translation of the C++ code in parallel
C for whatever reason - that I will try to understand later - can
you explain program flow. This is what is not clear to me. If you
put some verrry simple C++ code (for learning syntax) and words
or flowchart to explain
program flow. I mean C books have those railroad diagrams for
trivial things like sequence-selection-iteration-continue-break
etc. Can we see a clear program flow for this statement? As well
as a note to describe the side-effects of this stack?

You gotta make lucid what is not. Not make lucid what already is
simple, like sequence-selection-iteration-continue-break.

I totally fail to comprehend what is going on. Explain the usage and idea of

throw
exception
try
catch

with a C++ code and arrows or words to show program flow.

From: http://www.nicemice.net/cexcept/

\begin{quotation}

cexcept
Cosmin Truta and I have developed a try/catch/throw exception-handling interface for C. It basically works the way you would expect:

Try {
/* Maybe a Throw statement will be executed */
/* (maybe within a deeply nested function): */
/* Throw e; */
/* If so, execution jumps to the catch clause. */
}
Catch (e) {
/* An exception was thrown and copied into e. */
}

The interface of the latest release is fully implemented and documented in cexcept.h.

\end{quotation}

does have try-catch but not throw syntax. I want to first absorb the
syntax and then its semantic meaning in terms of program flow. C code,
requested in original post, was just a language that I knew well.

Thanks++,

--

,--. Bernard Klein, Berlin, Germany ,= ,-_-. =.
/ ,- ) ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. \_/
 
D

David Harmon

On Sat, 17 Apr 2004 07:27:40 PST in comp.lang.c++,
(e-mail address removed) (Bernard) wrote,
Thus far, all replies are useful but let me explain ...

OK, if you cannot write translation of the C++ code in parallel
C for whatever reason - that I will try to understand later - can
you explain program flow. This is what is not clear to me. If you
put some verrry simple C++ code (for learning syntax) and words
or flowchart to explain

Nobody can explain it to you as long as you crosspost between
comp.lang.c and comp.lang.c++, because any correct answer is
going to be off-topic in at least one of those groups.
 
C

Chris Torek

This is not quite what you have asked for, and I dropped comp.lang.c++
from the list because it has no direct C++ implications. I also
include a bit of detail on setjmp() and longjmp().

... words or flowchart to explain program flow. I mean C books have
those railroad diagrams for trivial things like sequence-selection-
iteration-continue-break etc. Can we see a clear program flow for
[exceptions]?

This is somewhat difficult, as part of the point of exceptions is
to obscure program flow. :) (Not really, but sort of.)

Languages with exceptions often, but not always, have some kind
of "exception protection" mechanism. C++ has one but it mostly
hidden. Lisps tend to have an explicit version called "unwind
protect". The explicit version is relatively easy to explain,
simply by pretending that *every* function call *always* has one
of these things going on -- even if the function does not have
a return value.

Take any ordinary C function, with a return value of type T (if
the function has type "void" pretend it returns "int" for the moment).
Replace:

T f(parameters) {
...
if (cond) return val1;
...
return val2;
}

with:

struct T2 { int normal_return; T val; };

struct T2 f(parameters) {
struct T2 rval;
rval.normal_return = 1;
...
if (cond) { rval.val = val1; return rval; }
...
rval.val = val2; return val2;
}

Notice that *every* "return" from f() now returns *two* values,
one indicating "normal return" and the other giving the actual
value.

Now, every call to f() has to change as well. Instead of:

T result;
...
result = f(arguments);
...

we have:

struct T2 result_pair;
...
result_pair = f(arguments);
if (result_pair.normal_return == 0) {
/* this new code is for exceptions */
...
}
result = result_pair.val;

In other words, we now have to test, after every call, to see
whether the function "returned normally" -- in which case we go
on with normal program flow and everything works as before -- or
whether f() had some kind of exception occur.

If f() chooses to use the new exception mechanism, it "throws" by
doing this:

struct T2 f(parameters) {
struct T2 rval;
rval.normal_return = 1;
...
if (decide_to_bail_out) {
rval.normal_return = 0; /* "exception" return */
return T2;
}
...
rval.val = val2; return val2; /* "normal" return */
}

Now suppose f() itself calls some other function g(). Function g()
has a normal-return value, and also an exception-return:

struct T3 g(params);

struct T2 f(parameters) {
struct T2 rval;
struct T3 g_value;
rval.normal_return = 1;
...
g_value = g(args);
if (g_value.normal_return == 0) {
/* g() "threw an exception" */
/* we have a chance to catch it here, but by default we just: */
rval.normal_return = 0;
return rval;
}
...
if (decide_to_bail_out) {
rval.normal_return = 0; /* this time we do the "throw" */
return rval;
}
...
rval.val = val2; return val2; /* "normal" return */
}

Again, *every call*, everywhere in the program, *always* has to
check to see if the function it just called is using one of these
"sideways" exception-return tricks. If so, it has a chance to
"catch" the exception right then and there, or to continue to
"throw" it up to its own caller.

Even functions that know or care nothing about exceptions have
to check, because any function *they* call could use exceptions
-- they are built into the language. Every time a function
returns, it either "returns normally" and the program goes on,
or it "returns sideways" with an exception and you get a chance
to clean up.

The "chance to clean up" is the unwind-protect:

unwind_protect {
f();
g();
h();
} on_exception {
something;
}
more;

turns into:

if (f() returns sideways) goto unwind_protect;
if (g() returns sideways) goto unwind_protect;
if (h() returns sideways) goto unwind_protect;
goto around;
unwind_protect:
something;
around:
more;

The unwind-protect sequence is often spelled "catch". In languages
that have "catch", they may (or may not) require you to list the
particular exception(s) caught. Ultimately, however, it means that
every function call everywhere in the program has two ways out of
it: the normal one, and the "sideways" exception.

The problem with this kind of explicit implementation (which you-the-
programmer can do in C, as long as you get to rewrite every function
call) is that it tends to run significantly slower than one in
which functions do not have "rval.normal_return = 1"s everywhere.
Thus, much of the effort in implementing exceptions goes into
inventing tricks that avoid slowing down every function call and
return. As it turns out, in languages like C++ (with destructors
for class objects that are allocated at function entry), this does
not always buy as much of a speed improvement as one might like,
because -- in effect -- every function already uses exceptions,
just so that it can catch them with an unwind-protect, destroy any
local objects, then continue up the "sideways exception return"
chain to the next function that is actually catching exceptions --
which is in fact the very next function up.

(I have occasionally thought that simply dedicating one more
machine register to every function call, for a "sideways exception
return" flag, might be easier than all the gimmicks one finds
in actual compilers, which tend to leave massive tables for
the exception code to pore over at runtime just to avoid
explicit "<r1,r2> = f(); if (r2) goto unwind; else val = r1;"
code. With branch prediction, one could even label the "goto if
r2" as a predicted-false branch, and have it disappear into the
CPU's parallelism on non-exception returns.)

C++'s "try" is an explicit unwind-protect, while C++'s object
destructors require an automatic, implicit unwind-protect. Either
way, it causes every sub-function to be able to "return" in one
of two ways: the normal way, or the "sideways" unwind way.

Languages that provide exception *values* (there are some with that
offer no "value" component) have to pass the value up the call
chain somehow. If one were using a machine register (like r2 in
my example above), one might dedicate the integer value 0 to mean
"no exception" and allow any other integer or pointer value as the
exception-value. In C, we might express this by replacing the
"struct"s that functions return with:

struct T2 {
int exception; /* 0 => normal return, nonzero => exception value */
T val;
};

and instead of setting "rval.normal_return = 1", set
"rval.exception = 0". To use a pointer, change this to "void *"
instead of "int". Now:

throw 72;

becomes:

rval.exception = 72;
return rval;

or:

throw("oops");

becomes:

rval.exception = "oops";
return rval;

Again, all it really means is "set the flag that says we want to
`return sideways' instead of returning normally, then return normally
and force the caller to deal with it all". The caller *has* to
deal with it, even if that caller is not using exceptions. Any
sneaky trick that a compiler-writer uses to try to speed this up
is merely an optimization -- logically, each caller gets a chance
to "protect" against this "unwinding" of the call stack.

The simulations people write in C using setjmp/longjmp tend to use
a global variable or two to keep linked list of "places that catch"
(longjmp labels) and "caught exception-value".

Note that C compilers could -- though few if any do -- even implement
setjmp() and longjmp() in terms of this same sort of "regular" vs
"sideways" return. The reason most do not is that longjmp is
*extremely* restricted, so that it can often be implemented by an
ugly hack: have setjmp() save the machine's program counter(s) and
stack/frame pointer(s), and have longjmp() restore those. The
problem with this hack is that it can interfere badly wth things
like variable-length arrays, alloca() functions (which are not part
of Standard C), and optimization. This problem is the reason the
C standard goes all wobbly on the programmer:

7.10.2.1 The longjmp function
...
[#3] All accessible objects have values as of the time
longjmp 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.
...
Examples

[#5] The longjmp function that returns control back to the
point of the setjmp invocation might cause memory associated
with a variable length array object to be squandered.

#include <setjmp.h>
jmp_buf buf;
void g(int n);
void h(int n);
int n = 6;

void f(void)
{
int x[n]; // OK, f is not terminated.
setjmp(buf);
g(n);
}

void g(int n)
{
int a[n]; // a may remain allocated.
h(n);
}

void h(int n)
{
int b[n]; // b may remain allocated.
longjmp(buf,2); // might cause memory loss.
}

In short, longjmp() is the goto they told you not to use in Pascal,
if you were took computer programming / informatics classes at a
University where they used Pascal.

If longjmp() were to be implemented as an exception, with the
functions involved doing "unwind-protect"s, these issues would go
away -- but then C would be heavier-weight than it is, because (as
I explained above) adding exceptions usually means that *every*
function call in *every* program has to go a little bit slower, to
account for "sideways" exception-returns. The trickery you may
read about in C++ books -- describing "searching up a call stack",
for instance -- is all about trying to pay the speed cost only when
an exception is actually used. In C, this might pay off, because
setjmp() and longjmp() are (one hopes) rarely used. In C++, with
object destructors causing implicit "catch"es, it is not at all
obvious to me when this is worthwhile.
 
M

Mark A. Gibbs

Bernard said:
Thus far, all replies are useful but let me explain ...

OK, if you cannot write translation of the C++ code in parallel
C for whatever reason - that I will try to understand later - can
you explain program flow. This is what is not clear to me. If you

int foo1()
{
int bar = 1;
throw bar;
return 2;
}

int foo2()
{
float bar = 1.0f;
throw bar;
return 2;
}

int main()
{
int result = EXIT_FAILURE;

try
{
foo1();
foo2();
result = EXIT_SUCCESS;
}
catch(int x)
{
printf("int exception caught: %d", x);
}
catch(...)
{
printf("unknown exception caught");
}

return result;
}

OK, it works like this. main() starts as usual, and executes as usual up
until it hits the "try". At that point, the compiler has noted that any
exceptions thrown inside that block are handled by one of the handlers
immediately following it. Then execution continues.

When it gets to foo1(), foo1() throws an exception of type int.
Immediately normal execution stops, and the program starts looking for
the exception handler that will be responsible for handling the int
exception. There is no "try" block in foo1(), so it just leaves it
(cleaning up anything that needs to be cleaned up along the way) without
executing the return statement and climbs back up the call stack up a
step. Then it's in main(), and main *does* contain a "try" block. So it
checks the handlers ("catch" statements) at the end of the try block to
see if any matches. Note, it does NOT call foo2() or the next statement,
it goes immediately to the handler.

Because there is a handler for int, it goes there, and inside the
exception, it prints "int exception caught: 1" (I hope, I don't use
printf anymore). Once it gets to the end of the catch block, it skips to
the end of all the exception handlers, and executes the return statement.

So linearly, this is what happened:

main starts:
main: int result = EXIT_FAILURE;
main: foo1();
foo1 starts:
foo1: int bar = 1;
foo1: throw bar;
int exception thrown (value: 1), immediately leaves foo1
jumps to int exception handler
main: sets x = 1 (from the exception)
main: printf("int exception caught: %d", x);
finished exception handler
main: return result;
main ends:

Now if you comment out the throw statement in foo1, you get this instead:

main starts:
main: int result = EXIT_FAILURE;
main: foo1();
foo1 starts:
foo1: int bar = 1;
foo1: return 2;
foo1 ends:
foo2 starts:
int exception thrown (value: 1), immediately leaves foo2
looks for float exception handler, can't find it, sees a "catch-all"
handler, jumps there
main: printf("int exception caught: %d", x);
finished exception handler
main: return result;
main ends:

The mechanics of it are pretty complex, and that without nesting try
blocks or other complexities. It's probably better to think of
exceptions in terms of what they are there for. Consider the following
example:

vector3d shrink_vector(vector3d v, int scale_factor)
{
v.x /= scale_factor;
v.y /= scale_factor;
v.z /= scale_factor;
return v;
}

vector3d make_unit_vector(vector3d v)
{
// calculates vector's length. not important, so not included
int length = get_vector_length(v);
return shrink_vector(v, length);
}

void high_level_function()
{
vector3d v = get_vector_somehow();
vector3d u = make_unit_vector();

printf("Your unit vector is: (%d, %d, %d)", u.x, u.y, u.z);
}

Now, take a look at shrink_vector(). What if the scale_factor is 0? You
can't divide by zero, that would be a disaster. But what on earth is
shrink_vector() supposed to do if you send it a 0? Should it silently
convert it to 1? No, that makes no sense. Return vector (0, 0, 0)? No,
that also makes no sense, mathematically. It could call some kind of
error function, but which one? You won't be able to reuse the function
easily if you have to use it with the same error function.

Clearly, the best think for shrink_vector to do is pass the buck. After
all, it wasn't responsible for the 0 and it couldn't fix it. So rewrite
it as:

vector3d shrink_vector(vector3d v, int scale_factor)
{
if (scale_factor == 0)
{
divide_by_zero_exception dbz;
throw dbz;
}

v.x /= scale_factor;
v.y /= scale_factor;
v.z /= scale_factor;
return v;
}

Now, what about make_unit_vector()? It would know if it was trying to
make a zero-vector a unit vector after it finds the length, but what
should it do about it? Again, you *could* put the error handling in
there, but that would limit the reuse. So, do nothing.

Now, high_level_function should know what to do if there is a problem.
So rewrite it like this:

void high_level_function()
{
try
{
vector3d v = get_vector_somehow();
vector3d u = make_unit_vector();

printf("Your unit vector is: (%d, %d, %d)", u.x, u.y, u.z);
}
catch (divide_by_zero_exception x)
{
printf("You entered a zero vector.");
}
// NOTE: any exceptions that high_level_function does
// not need to know how to handle, get passed up to whoever
// called it (eg. an out of memory exception)
}

So all the exception handling is in one place, and that's in a high
level function that knows what to do about it. As your program gets
smarter, it scales nicely. For example, suppose that in the
get_vector_length() function, calculating the length turns out to cause
integer overflow. No problem, just throw an integer_overflow_exception
there, and add a catch block in high_level_function to handle it.

I have tried to keep the examples as C-like as possible, but obviously,
this is a C++ phenomenon. That opens up a whole new world of
constructors and destructors, and the possiblity of using polymorphic
objects as exception types (in the example above, both
divide_by_zero_exception and integer_overflow_exception could derive
from math_exception, then you would only need to catch that, unless you
were interested in the specifics), among other things. Some aspects of
exception handling can be mimed in C, but since C is not polymorphic
object aware and does not know about destructors, there would be a
forbidding amount of work to get the full power without introducing a
whole whack of bugs (and by that I mean work not only on the side of the
guy making them, I mean also work by the guy trying to use them).

mark
 
R

Régis Troadec

Bernard said:
Hi All,
Hi,


I am not sure if I should be asking this question on clc or clc++. Let me try on
both. I hope that this is not too trivial for the brilliant minds over here.
I know that OOP questions have been asked on clc before so it is probably OK.

I am a newbie to C++. BS 3rd edition states:

% The throw transfers control to a handler for exceptions ....
%
% ... the implementation will unwind the function call stack as needed to get
% back to the context of that caller. Thus throw acts as a multilevel return.

My mind is so C-ish that I totally fail to comprehend what is going on.
My dumb brain has these pre-reqs. Explain the usage and idea of

throw
exception
try
catch

with a C++ code and a parallel code in C. If it must involve goto's, go ahead.
But the translation must be as highly parallel as possible. Furthermore, if
you have some way to depict this, and supplement by "function call stack"
diagrams, all the better.

Laurent Deniau provides a basic but very nice implementation in C of
C++-style exceptions with his library OOPC (Object Oriented Programming in
C). It's well documented and easy to use.

http://ldeniau.home.cern.ch/ldeniau/html/oopc/oopc.html

Regis
 
C

CBFalconer

Chris said:
.... snip ...

(I have occasionally thought that simply dedicating one more
machine register to every function call, for a "sideways exception
return" flag, might be easier than all the gimmicks one finds
in actual compilers, which tend to leave massive tables for
the exception code to pore over at runtime just to avoid
explicit "<r1,r2> = f(); if (r2) goto unwind; else val = r1;"
code. With branch prediction, one could even label the "goto if
r2" as a predicted-false branch, and have it disappear into the
CPU's parallelism on non-exception returns.)

In other words the simple rule many assembly language programmers
have used:

IF carry THEN exceptionoccured;

implying
call foo
jc handler; if handled
or
call foo
rc; if not handled
or even
call foo
rnc
<handler>

All that is left to be done is to translate this sort of set of
rules into the actions of the code generator. Handling here may
include error translation.
 
J

James Hu

From: http://www.nicemice.net/cexcept/

\begin{quotation}

cexcept
Cosmin Truta and I have developed a try/catch/throw exception-handling
interface for C. It basically works the way you would expect:

Try {
/* Maybe a Throw statement will be executed */
/* (maybe within a deeply nested function): */
/* Throw e; */
/* If so, execution jumps to the catch clause. */
}
Catch (e) {
/* An exception was thrown and copied into e. */
}

The interface of the latest release is fully implemented and
documented in cexcept.h.

\end{quotation}

does have try-catch but not throw syntax. I want to first absorb the
syntax and then its semantic meaning in terms of program flow. C code,
requested in original post, was just a language that I knew well.

It doesn't seem like you tried to read the source code in the
cexcept.h file. If you understand C, then read the code. If
you don't understand the C code, post your C question to
comp.lang.c.

-- James
 
C

CBFalconer

James said:
.... snip ...

It doesn't seem like you tried to read the source code in the
cexcept.h file. If you understand C, then read the code. If
you don't understand the C code, post your C question to
comp.lang.c.

Since people seem to refuse to cut the cross-postings out, the
only thing left to do is to PLONK this thread.
 
P

Peter Pichler

[12KB of interesting and useful stuff snipped]
struct T2 f(parameters) {
struct T2 rval;
rval.normal_return = 1;
...
if (decide_to_bail_out) {
rval.normal_return = 0; /* "exception" return */
return T2;

Is there an English equivalent for an old Czech saying,
"even the master carpenter can hit himself sometimes?" :)
}
...
rval.val = val2; return val2; /* "normal" return */
}

Peter
 
J

James Hu

Since people seem to refuse to cut the cross-postings out, the
only thing left to do is to PLONK this thread.

I was only going on what the original poster asked. Presumably, there
are those in C land that don't know what the semantics or "try, throw,
and catch" are, but would know how to implement the semantics given
that someone in C++ land would explain the semantics.

-- James
 
A

Allin Cottrell

Chris said:
This is not quite what you have asked for, and I dropped comp.lang.c++
from the list because it has no direct C++ implications. I also
include a bit of detail on setjmp() and longjmp()...

Thank you -- an excellent tutorial explaining the whole catch - try -
throw deal from a C point of view. Now I have some idea what this
terminology denotes.

Allin Cottrell.
 
B

Bradley Bungmunch

I was only going on what the original poster asked. Presumably, there
are those in C land that don't know what the semantics or "try, throw,
and catch" are,

Why would they? They're not part of C.
but would know how to implement the semantics given
that someone in C++ land would explain the semantics.

-- James


=====================



Pussie sHaveMo
reFunMeow MeowMeowPus
siesHaveMore FunMeowMeowMeo
wPussiesHaveMo reFunMeowMeowMeo
wPussiesHaveMor eFunMeowMeowMeowP
ussiesHaveMoreFu nMeowMeowMeowPussi
esHaveMoreFunMeo wMeowMeowPussiesHav
eMoreFunMeowMeowM eowPussiesHaveMor
eFunMeowMeowMeowP ussiesHaveMoreFunM
eowMeowMeowPussie sHaveMoreFunMeowMe owMeowPus
siesHaveM oreFunMeowMeowMe owPussiesHaveMore FunMeowMeowMe
owPussiesHave MoreFunMeowMeowM eowPussiesHaveM oreFunMeowMeowM
eowPussiesHaveM oreFunMeowMeow MeowPussiesHa veMoreFunMeowMeow
MeowPussiesHave MoreFunMeow MeowMeow PussiesHaveMoreFun
MeowMeowMeowPussi esHa veMoreFunMeowMeowMe
owPussiesHaveMoreF unMeowMeowM eowPussiesHaveMoreFu
nMeowMeowMeowPussie sHaveMoreFunMe owMeowMeowPussiesHav
eMoreFunMeowMeowMeo wPussiesHaveMoreFu nMeowMeowMeowPussie
sHaveMoreFunMeowMeo wMeowPussiesHaveMoreFu nMeowMeowMeowPussi
esHaveMoreFunMeowM eowMeowPussiesHaveMoreFu nMeowMeowMeowPuss
iesHaveMoreFunMe owMeowMeowPussiesHaveMoreFu nMeowMeowMeowP
ussiesHaveMor eFunMeowMeowMeowPussiesHaveMore FunMeowMeow
MeowPussi esHaveMoreFunMeowMeowMeowPussiesHave MoreF
unMe owMeowM eowPuss
iesHave MoreF unMeowMeowM
eowPussies Ha veMoreFunMeo
wMeowMeowP us si esHaveMoreFu
nMeowMeowM eow Pus siesHaveMore
FunMeowMeo wMeow Pussi esHaveMoreFu
nMeowMeow MeowPu ssiesH aveMoreFun
Meow MeowMeow Pussie
sHaveMoreFunMeowMeowMeowPussiesHaveM
oreFunMeowMeowMeowPussiesHaveMo
reFunMeowMeowMeowPussies
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,142
Messages
2,570,819
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top