blob: 4c820baf60c915d6a01a08b811b38d041f0fbf7a [file] [log] [blame]
// checking for bad_alloc assignment operator
/***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the License); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1999-2007 Rogue Wave Software, Inc.
*
**************************************************************************/
// NOTE: this file is #included from the following tests,
// each of which #defines bad_alloc to the name of
// the corresponding exception class, and exercises
// the respective class members
//
// BAD_ALLOC_COPY_CTOR.cpp
// BAD_ALLOC_DEFAULT_CTOR.cpp
// BAD_ALLOC_DTOR.cpp
// BAD_CAST_ASSIGNMENT.cpp
// BAD_CAST_COPY_CTOR.cpp
// BAD_CAST_DEFAULT_CTOR.cpp
// BAD_CAST_DTOR.cpp
// BAD_EXCEPTION_ASSIGNMENT.cpp
// BAD_EXCEPTION_COPY_CTOR.cpp
// BAD_EXCEPTION_DEFAULT_CTOR.cpp
// BAD_EXCEPTION_DTOR.cpp
// BAD_TYPEID_ASSIGNMENT.cpp
// BAD_TYPEID_COPY_CTOR.cpp
// BAD_TYPEID_DEFAULT_CTOR.cpp
// BAD_TYPEID_DTOR.cpp
// EXCEPTION_ASSIGNMENT.cpp
// EXCEPTION_COPY_CTOR.cpp
// EXCEPTION_DEFAULT_CTOR.cpp
// EXCEPTION_DTOR.cpp
#include "config.h"
#if 2 == __GNUG__
# ifndef _RWSTD_NO_HONOR_STD
# ifdef _RWSTD_NO_STD_TERMINATE
# include "terminate.h"
# endif // _RWSTD_NO_STD_TERMINATE
# endif // _RWSTD_NO_HONOR_STD
#endif // gcc 2.x
#ifndef _RWSTD_NO_RUNTIME_IN_STD
# define NAMESPACE(name) namespace name
#else
# define NAMESPACE(ignore) extern "C++"
# define std /* empty */
#endif // _RWSTD_NO_RUNTIME_IN_STD
int ndefault_ctors;
int ncopy_ctors;
int ndtors;
int nassignments;
NAMESPACE (std) {
class bad_alloc
{
public:
const void *what_;
#if defined (TEST_DEFAULT_CTOR)
bad_alloc ();
#else // if !defined (TEST_DEFAULT_CTOR)
// provide a default ctor but with a different signature
// than the one above to prevent multiply defined symbol
// linker errors in case that one is defined in the
// runtime library
bad_alloc (int = 0) { }
# if defined (TEST_DTOR)
virtual ~bad_alloc ();
# elif defined (TEST_COPY_CTOR)
bad_alloc (const bad_alloc&);
# elif defined (TEST_WHAT)
virtual const char* what () const;
# else // test assignment
# if !defined (TEST_ASSIGNMENT)
# define TEST_ASSIGNMENT
# endif
bad_alloc& operator= (const bad_alloc&);
bad_alloc& assign (const bad_alloc &rhs) {
++nassignments;
return *this = rhs;
}
# endif // TEST_...
#endif // !TEST_DEFAULT_CTOR
};
} // namespace std
// use virtual inheritance here to prevent aggressive optimizers
// (like VisualAge C++) from optimizing the base class dtor away
struct Base0: virtual std::bad_alloc
{
int index0;
typedef std::bad_alloc Base;
Base0 ();
Base0 (const Base0&);
virtual ~Base0 ();
Base0& operator= (const Base0&);
virtual const char* what () const;
};
struct Base1: virtual std::bad_alloc
{
int index1;
typedef std::bad_alloc Base;
Base1 ();
Base1 (const Base1&);
virtual ~Base1 ();
Base1& operator= (const Base1&);
virtual const char* what () const;
};
int which_what;
struct Derived: Base0, Base1
{
typedef std::bad_alloc Base;
Derived ();
Derived (const Derived&);
virtual ~Derived ();
Derived& operator= (const Derived&);
virtual const char* what () const;
};
#if defined (TEST_COPY_CTOR) ///////////////////////////////////////
int test_member (int argc, void *ptr)
{
// the code below must not be executed
# ifndef _RWSTD_NO_EXCEPTIONS
try {
try {
if (1 < argc) {
// jump through hoops to try to foil
// even the most aggressive optimizers
Derived *pd = (Derived*)ptr;
Base0 *pb0 = (Derived*)ptr + argc;
Base1 *pb1 = (Derived*)ptr + argc + 1;
std::bad_alloc *pba = (Derived*)ptr + argc + 2;
if (argc < 6)
throw *pd;
if (argc < 7)
throw *pb0;
if (argc < 8)
throw *pb1;
if (argc < 9)
throw *pba;
}
}
catch (Derived e) {
e.index0 = e.index1 = __LINE__;
throw e;
}
catch (Base0 b0) {
b0.index0 = __LINE__;
throw b0;
}
catch (Base1 b1) {
b1.index1 = __LINE__;
throw b1;
}
catch (std::bad_alloc e) {
std::bad_alloc copy (e);
if (argc < 5)
throw copy;
if (argc < 4)
throw e;
if (argc < 3)
throw;
}
}
catch (std::bad_alloc e) {
return 0 != e.what_;
}
catch (...) {
return 2;
}
return 3;
# else // if defined (_RWSTD_NO_EXCEPTIONS)
std::bad_alloc *pe = (std::bad_alloc*)ptr;
std::bad_alloc *pf = new std::bad_alloc (*pe);
return !(1 == ndefault_ctors && 1 == ncopy_ctors && pe->what_ == pf->what_);
# endif // _RWSTD_NO_EXCEPTIONS
}
#elif defined (TEST_DEFAULT_CTOR) //////////////////////////////////
int test_member (int, void*)
{
// the code below must not be executed
std::bad_alloc *pe1 = new std::bad_alloc;
std::bad_alloc *pe2 = new Derived;
return pe1 < pe2;
}
#elif defined (TEST_DTOR) //////////////////////////////////////////
int test_member (int argc, void *ptr)
{
// the code below must not be executed
std::bad_alloc *pe;
if (1 < argc)
pe = (Derived*)ptr;
else
pe = (std::bad_alloc*)ptr;
delete pe;
return !(1 < argc ? 1 == ndtors : 0 == ndtors);
}
#elif defined (TEST_WHAT) //////////////////////////////////////////
int test_member (int argc, void *ptr)
{
// the code below must not be executed
std::bad_alloc *pe = (std::bad_alloc*)ptr;
Derived *pd = (Derived*)ptr + 1;
which_what = argc;
return pe [0].what () == pd [argc].what ();
}
#else // test assignment /////////////////////////////////////////
int test_member (int argc, void *ptr)
{
// the code below must not be executed
std::bad_alloc *pe = (Derived*)ptr;
std::bad_alloc& (std::bad_alloc::*pf)(const std::bad_alloc&) =
argc < 3 ? &std::bad_alloc::operator= : &std::bad_alloc::assign;
which_what = argc;
pe [argc] = pe [argc + 1];
(pe [argc + 1].*pf)(pe [argc + 2]);
return pe [0].what_ == pe [1].what_ || 2 < nassignments;
}
#endif // TEST_... ///////////////////////////////////////////////
int main (int argc, char *argv[])
{
(void)&argv;
(void)&nassignments;
(void)&ncopy_ctors;
(void)&ndefault_ctors;
// avoid executing the body of main unless explicitly requested
// by specifying at least one command line argument (this foils
// aggressive optimizers from eliminating the code)
if (argc < 2)
return 0;
return test_member (argc, argv);
}
Base0::Base0 (): Base (), index0 (++ndefault_ctors) { }
Base0::Base0 (const Base0 &rhs)
#if defined (TEST_COPY_CTOR)
: Base (rhs),
#else // if defined (TEST_COPY_CTOR)
: Base (),
#endif // TEST_COPY_CTOR
index0 (rhs.index0)
{
(void)&rhs; // silence unused argument warnings
++ncopy_ctors;
}
Base0::~Base0 ()
{
++ndtors;
index0 = 0;
}
Base0& Base0::operator=(const Base0 &rhs)
{
++nassignments;
index0 = rhs.index0;
#if defined (TEST_ASSIGNMENT)
Base::operator= (rhs);
#endif // TEST_ASSIGNMENT
return *this;
}
const char* Base0::what () const
{
#if defined (TEST_WHAT)
if (1 < which_what++)
return Base::what ();
#endif // TEST_WHAT
return "Base0";
}
Base1::Base1 (): Base (), index1 (++ndefault_ctors) { }
Base1::Base1 (const Base1 &rhs)
#if defined (TEST_COPY_CTOR)
: Base (rhs),
#else // if defined (TEST_COPY_CTOR)
: Base (),
#endif // TEST_COPY_CTOR
index1 (rhs.index1)
{
(void)&rhs; // silence unused argument warnings
++ncopy_ctors;
}
Base1::~Base1 ()
{
++ndtors;
index1 = 0;
}
const char* Base1::what () const
{
#if defined (TEST_WHAT)
if (2 < which_what++)
return Base::what ();
#endif // TEST_WHAT
return "Base1";
}
Base1& Base1::operator=(const Base1 &rhs)
{
++nassignments;
index1 = rhs.index1;
#if defined (TEST_ASSIGNMENT)
Base::operator= (rhs);
#endif // TEST_ASSIGNMENT
return *this;
}
Derived::Derived ()
: Base (), Base0 (), Base1 ()
{
++ndefault_ctors;
}
Derived::Derived (const Derived &rhs)
#if defined (TEST_COPY_CTOR)
: Base (rhs), Base0 (rhs), Base1 (rhs)
#else // if defined (TEST_COPY_CTOR)
: Base (), Base0 (), Base1 ()
#endif // TEST_COPY_CTOR
{
(void)&rhs; // silence unused argument warnings
++ncopy_ctors;
}
Derived::~Derived ()
{
++ndtors;
}
Derived& Derived::operator=(const Derived &rhs)
{
++nassignments;
Base0::operator= (rhs);
Base1::operator= (rhs);
return *this;
}
const char* Derived::what () const
{
if (3 < which_what++)
return Base1::what ();
return Base0::what ();
}