aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.old-deja/g++.robertl/eb78.C
blob: 15f26318efbd87eb4533f1981cf1177a4c8c2c76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Special g++ Options: -W -Wall -O

//This is the source code from FAQ-259, found in chapter 20 of "C++ FAQs."
//Copyright (C) 1994, Addison-Wesley Publishers, Inc.; All rights reserved.
//
//The book, "C++ FAQs" is by Marshall P. Cline and Greg A. Lomow,
//Copyright (C) 1994, Addison-Wesley Publishers, Inc.; All rights reserved.
//
//This code is presented for its instructional value.  It has been tested with
//care, but it is not guaranteed for any particular purpose.  Neither the
//publisher nor the authors offer any warranties or representations, nor do
//they accept any liabilities with respect to this code.

#include <string.h>
#include <iostream.h>

class BadIndex { };

class String {
public:

  String()
    : len_(0), data_(new char[1])
    { data_[0] = '\0'; }

  String(const char* s)
    : len_(strlen(s)), data_(new char[len_ + 1])
    { memcpy(data_, s, len_ + 1); }

 ~String()
    { delete [] data_; }

  String(const String& s)
    : len_(s.len_), data_(new char[s.len_ + 1])
    { memcpy(data_, s.data_, len_ + 1); }

  String& operator= (const String& s)
    {
      if (len_ != s.len_) { //makes self-assignment harmless
        char* newData = new char[s.len_ + 1];
        delete [] data_;
        data_ = newData;
        len_ = s.len_;
      }
      memcpy(data_, s.data_, len_ + 1);
      return *this;
    }

  unsigned len() const
    { return len_; }

  char& operator[] (unsigned i)
    { indexTest(i); return data_[i]; }
  char  operator[] (unsigned i) const
    { indexTest(i); return data_[i]; }

  friend ostream& operator<< (ostream& o, const String& s)
    { return o.write(s.data_, s.len_); }

  friend int operator== (const String& a, const String& b)
    { return a.len_ == b.len_ &&
             memcmp(a.data_, b.data_, a.len_) == 0; }
  friend int operator!= (const String& a, const String& b)
    { return ! (a == b); }

private:
  void indexTest(unsigned i) const
    { if (i >= len_) throw BadIndex(); }
  unsigned len_;  //ORDER DEPENDENCY; see FAQ-190
  char* data_;    //ORDER DEPENDENCY; see FAQ-190
};

class AccessViolation { };
class BadFileName     { };

class File {
public:
  File(const String& filename)
    throw(AccessViolation, BadFileName)
    {
      cout << "Open " << filename << "\n";
      if (filename == "badAccess.txt")
        throw AccessViolation();
      if (filename == "badName.txt")
        throw BadFileName();
    }
};

class UserClass {
public:
  void f(const String& filename) throw(BadFileName);
};

void
UserClass::f(const String& filename) throw(BadFileName)
{
  try {
    File f(filename);		// WARNING - unused
  }
  catch (const AccessViolation& e) {
    cout << "  FULLY recover from access-violation\n";
  }
  catch (const BadFileName& e) {
    cout << "  PARTIALLY recover from bad-file-name\n";
    throw;
  }
}

void
tryIt(const String& filename)
{
  try {
    UserClass u;
    u.f(filename);
    cout << "  OK\n";
  }
  catch (const BadFileName& e) {
    cout << "  Finish recovering from bad-file-name\n";
  }
}

main()
{
  tryIt("goodFile.txt");
  tryIt("badAccess.txt");
  tryIt("badName.txt");
}

// g++ -O -o warn warn.C -W -Wall
// warn.C: In method `void UserClass::f(const class String &)':
// warn.C:96: warning: unused variable `class File f'
// warn.C:101: warning: `struct cp_eh_info * __exception_info' might 
// be used uninitialized in this function