You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
569 lines
9.5 KiB
569 lines
9.5 KiB
/*
|
|
* COMMAND LINE: -Ox -GX
|
|
*/
|
|
|
|
/*
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
EhThrow.cxx
|
|
|
|
Abstract:
|
|
|
|
Tests some throw and rethrow situations (mostly CRT a test)
|
|
|
|
Author:
|
|
|
|
Louis Lafreniere (louisl) 1997
|
|
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
#define FALSE 0
|
|
#define TRUE 1
|
|
#define NO_CTOR_THROW 1
|
|
#define NO_DTOR_THROW 2
|
|
|
|
|
|
int Object[100];
|
|
int CurrentObjectNumber, Test;
|
|
int MaxTest = 10;
|
|
int MaxObjectCount = 1;
|
|
int Fail;
|
|
|
|
|
|
void FAIL(int i)
|
|
{
|
|
printf("FAILED on %d\n", i);
|
|
Fail++;
|
|
}
|
|
|
|
void dealloc(int i, int no_throw)
|
|
{
|
|
/* Make sure i is valid, and object exists */
|
|
if(i<0 || i>=MaxObjectCount || !Object[i])
|
|
FAIL(i);
|
|
|
|
Object[i] = 0;
|
|
}
|
|
|
|
void alloc(int i, int no_throw)
|
|
{
|
|
if(CurrentObjectNumber > MaxObjectCount)
|
|
MaxObjectCount = CurrentObjectNumber;
|
|
|
|
/* Object already exists? */
|
|
if(Object[i]) FAIL(i);
|
|
|
|
Object[i] = 1;
|
|
}
|
|
|
|
class B
|
|
{
|
|
public:
|
|
int i;
|
|
int flag;
|
|
B();
|
|
B(int);
|
|
B(const B &b);
|
|
~B();
|
|
};
|
|
|
|
B::B()
|
|
{
|
|
i = CurrentObjectNumber++;
|
|
printf("B ctor. i = %d\n", i);
|
|
alloc(i, FALSE);
|
|
}
|
|
|
|
B::B(int f)
|
|
{
|
|
i = CurrentObjectNumber++;
|
|
flag = f;
|
|
printf("B ctor. i = %d\n", i);
|
|
alloc(i, flag==NO_CTOR_THROW);
|
|
}
|
|
|
|
B::B(const B &b)
|
|
{
|
|
i = CurrentObjectNumber++;
|
|
printf("B copy ctor. i = %d\n", i);
|
|
alloc(i, FALSE);
|
|
}
|
|
|
|
B::~B()
|
|
{
|
|
printf("B dtor. i = %d\n", i);
|
|
dealloc(i, flag==NO_DTOR_THROW);
|
|
}
|
|
|
|
class A
|
|
{
|
|
public:
|
|
int i;
|
|
A();
|
|
A(int)
|
|
{
|
|
i = CurrentObjectNumber++;
|
|
printf("A(int) ctor. i = %d\n", i);
|
|
alloc(i, FALSE);
|
|
}
|
|
A operator+(A a);
|
|
A(const A &a)
|
|
{
|
|
/* Try objects in ctor */
|
|
B b1 = NO_DTOR_THROW, b2 = NO_DTOR_THROW;
|
|
|
|
i = CurrentObjectNumber++;
|
|
printf("A copy ctor. i = %d\n", i);
|
|
alloc(i, FALSE);
|
|
}
|
|
|
|
~A(){
|
|
/* Try objects in dtor */
|
|
B b1 = NO_CTOR_THROW, b2 = NO_CTOR_THROW;
|
|
|
|
printf("A dtor. i = %d\n", i);
|
|
dealloc(i, FALSE);
|
|
};
|
|
};
|
|
|
|
A::A()
|
|
{
|
|
i=CurrentObjectNumber++;
|
|
printf("A ctor. i = %d\n", i);
|
|
alloc(i, FALSE);
|
|
}
|
|
|
|
A A::operator+(A a)
|
|
{
|
|
printf("A%d + A%d\n", i, a.i);
|
|
return A();
|
|
}
|
|
|
|
void Throwa(A a)
|
|
{
|
|
printf("Throwing\n");
|
|
throw a;
|
|
}
|
|
|
|
void bar()
|
|
{
|
|
A a;
|
|
|
|
Throwa(a);
|
|
}
|
|
|
|
void foobar()
|
|
{
|
|
B b;
|
|
bar();
|
|
}
|
|
|
|
// Somehow, inlining this causes different unwinding order..
|
|
|
|
void Rethrow2()
|
|
{
|
|
A a;
|
|
printf("Rethrowing\n");
|
|
throw;
|
|
}
|
|
|
|
#pragma inline_depth(0)
|
|
void Rethrow()
|
|
{
|
|
Rethrow2();
|
|
}
|
|
#pragma inline_depth()
|
|
|
|
void foobar2()
|
|
{
|
|
B b;
|
|
|
|
try{
|
|
A a;
|
|
bar();
|
|
}catch(A a){
|
|
printf("In catch;\n");
|
|
Rethrow();
|
|
}
|
|
}
|
|
|
|
void foobar3()
|
|
{
|
|
B b;
|
|
|
|
try{
|
|
A a;
|
|
bar();
|
|
}catch(A a){
|
|
printf("In catch\n");
|
|
A a2;
|
|
|
|
printf("Throwing new a\n");
|
|
throw a2;
|
|
}
|
|
}
|
|
|
|
void foobar4()
|
|
{
|
|
B b;
|
|
|
|
try{
|
|
B b;
|
|
try{
|
|
A a1, a2;
|
|
try {
|
|
A a1, a2;
|
|
foobar2();
|
|
}catch(A a){
|
|
printf("In catch #1\n");
|
|
B b;
|
|
printf("Rethrowing\n");
|
|
throw;
|
|
}
|
|
}catch(A &a){
|
|
printf("In catch #2\n");
|
|
A a2;
|
|
|
|
printf("Throwing new a\n");
|
|
throw a;
|
|
}
|
|
}catch(A a){
|
|
printf("In catch #3\n");
|
|
B b;
|
|
printf("Rethrowing\n");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
void throw_B_2()
|
|
{
|
|
B b;
|
|
printf("Throwing a new b\n");
|
|
throw b;
|
|
}
|
|
|
|
#pragma inline_depth(0)
|
|
void throw_B()
|
|
{
|
|
throw_B_2();
|
|
}
|
|
#pragma inline_depth()
|
|
|
|
|
|
void foobar5()
|
|
{
|
|
try {
|
|
B b1;
|
|
try {
|
|
B b2;
|
|
try {
|
|
B b3;
|
|
foobar();
|
|
}catch(B b){
|
|
printf("In catch #1\n");
|
|
FAIL(-1);
|
|
}
|
|
FAIL(-1);
|
|
}catch(A a){
|
|
A a2;
|
|
printf("In catch #2\n");
|
|
throw_B();
|
|
}
|
|
FAIL(-1);
|
|
}catch(B b){
|
|
printf("In catch #3\n");
|
|
printf("Throwing a new a\n");
|
|
throw A();
|
|
}
|
|
FAIL(-1);
|
|
}
|
|
|
|
|
|
/* Simple throw with unwinds */
|
|
void test1()
|
|
{
|
|
A a;
|
|
foobar();
|
|
}
|
|
|
|
/* Throw followed by a rethrow */
|
|
void test2()
|
|
{
|
|
A a;
|
|
foobar2();
|
|
}
|
|
|
|
/* Throw followed by a new throw */
|
|
void test3()
|
|
{
|
|
A a;
|
|
foobar3();
|
|
}
|
|
|
|
/* Nested trys with rethrow/throw/rethrow */
|
|
void test4()
|
|
{
|
|
A a;
|
|
foobar4();
|
|
}
|
|
|
|
/* Makes sure a new throw skips appropriate unwound frames. */
|
|
void test5()
|
|
{
|
|
A a;
|
|
foobar5();
|
|
}
|
|
|
|
// Tests 3 level of new throw
|
|
void test6()
|
|
{
|
|
try{
|
|
B b1;
|
|
try{
|
|
B b2;
|
|
try{
|
|
B b3;
|
|
printf("Throwing a b\n");
|
|
throw(b3);
|
|
}catch(B b){
|
|
B b4;
|
|
printf("In catch #1\n");
|
|
printf("Throwing a new b\n");
|
|
throw(b4);
|
|
}
|
|
FAIL(-1);
|
|
}catch(B b){
|
|
B b5;
|
|
printf("In catch #2\n");
|
|
printf("Throwing a new b\n");
|
|
throw(b5);
|
|
}
|
|
FAIL(-1);
|
|
}catch(B b){
|
|
A a1;
|
|
printf("In catch #3\n");
|
|
printf("Throwing a new a\n");
|
|
throw(a1);
|
|
}
|
|
FAIL(-1);
|
|
}
|
|
|
|
// Testing try/catch inside a catch
|
|
void test7()
|
|
{
|
|
B b1;
|
|
try{
|
|
B b2;
|
|
try{
|
|
B b3;
|
|
|
|
printf("Throwing a b\n");
|
|
throw(B());
|
|
}catch(B b){
|
|
B b4;
|
|
printf("In catch #1\n");
|
|
try{
|
|
B b5;
|
|
printf("Rethrowing b\n");
|
|
throw;
|
|
}catch(B b){
|
|
B b5;
|
|
printf("In catch #1 of catch#1\n");
|
|
printf("Rethrowing b\n");
|
|
throw;
|
|
}
|
|
}
|
|
}catch(B b){
|
|
B b6;
|
|
printf("In catch #2\n");
|
|
printf("Throwing a new A\n");
|
|
throw(A());
|
|
}
|
|
}
|
|
|
|
void ThrowB()
|
|
{
|
|
B b;
|
|
|
|
throw(B());
|
|
}
|
|
|
|
void bar8()
|
|
{
|
|
try{
|
|
B b5;
|
|
printf("Rethrowing b\n");
|
|
Rethrow();
|
|
}catch(B b){
|
|
B b5;
|
|
printf("In catch #1 of catch#1\n");
|
|
printf("Rethrowing b\n");
|
|
Rethrow();
|
|
}
|
|
}
|
|
|
|
void foo8()
|
|
{
|
|
B b;
|
|
try{
|
|
B b3;
|
|
|
|
printf("Throwing a b\n");
|
|
ThrowB();
|
|
}catch(B b){
|
|
B b4;
|
|
printf("In catch #1\n");
|
|
bar8();
|
|
}
|
|
}
|
|
|
|
// Testing call to try/catch function inside a catch
|
|
void test8()
|
|
{
|
|
B b1;
|
|
try{
|
|
B b2;
|
|
foo8();
|
|
}catch(B b){
|
|
B b6;
|
|
printf("In catch #2\n");
|
|
printf("Throwing a new A\n");
|
|
throw(A());
|
|
}
|
|
}
|
|
|
|
void foo9()
|
|
{
|
|
try {
|
|
puts("Rethrow");
|
|
throw;
|
|
}catch(...){
|
|
puts("In catch #2");
|
|
}
|
|
}
|
|
|
|
void test9()
|
|
{
|
|
try{
|
|
B b;
|
|
puts("Throwing B");
|
|
throw b;
|
|
}catch(...){
|
|
puts("In catch #1");
|
|
foo9();
|
|
}
|
|
puts("End of test9, throwing a A");
|
|
throw A();
|
|
}
|
|
|
|
void foo10()
|
|
{
|
|
try {
|
|
puts("Throwing a new B()");
|
|
throw B();
|
|
}catch(...){
|
|
puts("In catch #2");
|
|
}
|
|
}
|
|
|
|
void test10()
|
|
{
|
|
try{
|
|
B b;
|
|
puts("Throwing B");
|
|
throw b;
|
|
}catch(...){
|
|
puts("In catch #1");
|
|
foo10();
|
|
}
|
|
puts("End of test10, throwing a A");
|
|
throw A();
|
|
}
|
|
|
|
void main()
|
|
{
|
|
int i;
|
|
|
|
/* Call test(), with a different ctor/dtor throwing each time */
|
|
for(Test = 1; Test <= 10; Test++) {
|
|
|
|
CurrentObjectNumber = 0;
|
|
|
|
printf("\nTest #%d\n", Test);
|
|
|
|
try {
|
|
switch(Test){
|
|
case 1:
|
|
test1();
|
|
break;
|
|
case 2:
|
|
test2();
|
|
break;
|
|
case 3:
|
|
test3();
|
|
break;
|
|
case 4:
|
|
test4();
|
|
break;
|
|
case 5:
|
|
test5();
|
|
break;
|
|
case 6:
|
|
test6();
|
|
break;
|
|
case 7:
|
|
#if !defined(_M_IA64)
|
|
test7();
|
|
#else
|
|
continue;
|
|
#endif
|
|
break;
|
|
case 8:
|
|
test8();
|
|
break;
|
|
case 9:
|
|
#if !defined(_M_IA64)
|
|
test9();
|
|
#else
|
|
continue;
|
|
#endif
|
|
break;
|
|
case 10:
|
|
test10();
|
|
break;
|
|
}
|
|
|
|
FAIL(-1);
|
|
|
|
}catch(A a){
|
|
printf("In main's catch\n");
|
|
}catch(...){
|
|
FAIL(-1);
|
|
}
|
|
|
|
/* Any objects which didn't get dtor'd? */
|
|
for(i = 0; i < MaxObjectCount; i++) {
|
|
if(Object[i]) {
|
|
FAIL(i);
|
|
Object[i] = 0;
|
|
}
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
printf("\n");
|
|
if(Fail)
|
|
printf("FAILED %d tests\n", Fail);
|
|
else
|
|
printf("Passed\n");
|
|
|
|
}
|