1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestCxxFeatures.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 // .NAME TestCxxFeatures
17 // .SECTION Description
18 // Provides a reference for the set of C++ features that can be used
19 // by VTK.
20
21 #include "vtkConfigure.h"
22
23 //----------------------------------------------------------------------------
24
25 /* Check for known compilers. */
26
27 #if defined(__sgi) && !defined(__GNUC__)
28 # define VTK_CXX_SGI
29 # if !defined(_COMPILER_VERSION)
30 # define VTK_CXX_SGI_6
31 # endif
32 #endif
33
34 #if defined(__HP_aCC)
35 # define VTK_CXX_ACC
36 #endif
37
38 #if defined(__SUNPRO_CC)
39 # define VTK_CXX_SUNPRO
40 #endif
41
42 //----------------------------------------------------------------------------
43
44 /* Check for known compiler limitations. */
45
46 // Check for IRIX64-6.5-CC-o32 (old SGI compiler).
47 #if defined(VTK_CXX_SGI_6)
48 # define VTK_TYPENAME /* empty */
49 # define VTK_CLASS_TEMPLATE_SPECIALIZATION /* empty */
50 #endif
51
52 // Assume standard behavior if symbol is not already defined.
53 #if !defined(VTK_TYPENAME)
54 # define VTK_TYPENAME typename
55 #endif
56
57 // Assume standard behavior if symbol is not already defined.
58 #if !defined(VTK_CLASS_TEMPLATE_SPECIALIZATION)
59 # define VTK_CLASS_TEMPLATE_SPECIALIZATION template <>
60 #endif
61
62 //----------------------------------------------------------------------------
63
64 #include "vtkSystemIncludes.h"
65
66 //----------------------------------------------------------------------------
67
68 /* Test inclusion of typeinfo header. */
69
70 #include <typeinfo>
71
72 //----------------------------------------------------------------------------
73
74 /* Test use of namespaces. */
75
76 #if !defined(VTK_CXX_SGI_6)
77 // Fails on kulu.crd IRIX64-6.5-CC-o32 (old SGI compiler).
78 namespace NamespaceTest {}
79 namespace {}
NamespaceTestFunc()80 void NamespaceTestFunc() {}
81 namespace NamespaceTest
82 {
83 using ::NamespaceTestFunc;
84 }
85 using namespace NamespaceTest;
86 #endif
87
88 //----------------------------------------------------------------------------
89
90 /* Test nested classes defined outside. */
91
92 class NestedTestOuter
93 {
94 public:
95 NestedTestOuter();
96 ~NestedTestOuter();
97 private:
98 class NestedTestInner;
99 NestedTestInner* Inner;
100 };
101
102 class NestedTestOuter::NestedTestInner
103 {
104 public:
NestedTestInner()105 NestedTestInner() {}
~NestedTestInner()106 ~NestedTestInner() {}
107 };
108
NestedTestOuter()109 NestedTestOuter::NestedTestOuter()
110 {
111 this->Inner = new NestedTestInner;
112 }
113
~NestedTestOuter()114 NestedTestOuter::~NestedTestOuter()
115 {
116 delete this->Inner;
117 }
118
119 //----------------------------------------------------------------------------
120
121 /* Test inclusion of some stl headers. */
122 #ifdef _MSC_VER
123 #pragma warning (push, 2)
124 #endif
125
126 #include <vector>
127
128 #ifdef _MSC_VER
129 #pragma warning(pop)
130 #endif
131
132 #if !defined(VTK_CXX_SGI_6)
133 // Fails on kulu.crd IRIX64-6.5-CC-o32 (old SGI compiler).
UsingStdVector()134 void UsingStdVector()
135 {
136 using std::vector;
137 vector<int>();
138 }
139 #endif
140
141 //----------------------------------------------------------------------------
142
143 /* Test full template specialization of functions. */
144 template <class T>
FullySpecializedFunction(T *)145 int FullySpecializedFunction(T*)
146 {
147 return 0;
148 }
149
150 #if !defined(VTK_CXX_SGI)
151 // Fails on kulu.crd IRIX64-6.5-CC-o32 (old SGI compiler).
152 // Fails on manifold.crd IRIX64-6.5-CC-n32 (new SGI compiler).
153 template <>
FullySpecializedFunction(int *)154 int FullySpecializedFunction<int>(int*)
155 {
156 return 1;
157 }
158 #else
159 // Let overload resolution pick this one instead.
FullySpecializedFunction(int *)160 int FullySpecializedFunction(int*)
161 {
162 return 1;
163 }
164 #endif
165
TestFullySpecializedFunction()166 int TestFullySpecializedFunction()
167 {
168 int result = 1;
169 int should_be_0 = FullySpecializedFunction(static_cast<float*>(0));
170 if(should_be_0 != 0)
171 {
172 cerr << "FullySpecializedFunction<float*>() returned "
173 << should_be_0 << ", not 0.\n";
174 result = 0;
175 }
176 int should_be_1 = FullySpecializedFunction(static_cast<int*>(0));
177 if(should_be_1 != 1)
178 {
179 cerr << "FullySpecializedFunction(int*) returned "
180 << should_be_1 << ", not 1.\n";
181 result = 0;
182 }
183 return result;
184 }
185
186 //----------------------------------------------------------------------------
187
188 /* Test member template of non-template. */
189
190 class NonTemplate
191 {
192 void* Pointer;
193 public:
Set(T * t)194 template <class T> void Set(T* t) { this->Pointer = t; }
Get(T * & t)195 template <class T> void Get(T*& t) { t = static_cast<T*>(this->Pointer); }
196 };
197
TestNonTemplateMemberTemplate()198 int TestNonTemplateMemberTemplate()
199 {
200 int x = 123;
201 int* px = 0;
202 NonTemplate nt;
203 nt.Set(&x);
204 nt.Get(px);
205 return (*px == 123);
206 }
207
208 //----------------------------------------------------------------------------
209
210 /* Test member template of template. */
211
212 template <class T>
213 class OuterTemplate
214 {
215 T* Pointer;
216 public:
Set(U * u)217 template <class U> void Set(U* u) { this->Pointer = u; }
Get(U * & u)218 template <class U> void Get(U*& u) { u = static_cast<U*>(this->Pointer); }
219 };
220
TestTemplateMemberTemplate()221 int TestTemplateMemberTemplate()
222 {
223 int x = 123;
224 int* px = 0;
225 OuterTemplate<void> nt;
226 nt.Set(&x);
227 nt.Get(px);
228 return (*px == 123);
229 }
230
231 //----------------------------------------------------------------------------
232
233 /* Test use of standard "bool" type and values. */
234
235 #if !defined(VTK_CXX_SGI_6)
GetFalse()236 bool GetFalse()
237 {
238 return false;
239 }
240
GetTrue()241 bool GetTrue()
242 {
243 return true;
244 }
245
TestBool()246 int TestBool()
247 {
248 int result = 1;
249 bool should_be_false = GetFalse();
250 bool should_be_true = GetTrue();
251 if(should_be_false)
252 {
253 cerr << "GetFalse() returned " << should_be_false << ", not false.\n";
254 result = 0;
255 }
256 if(!should_be_true)
257 {
258 cerr << "GetTrue() returned " << should_be_true << ", not true.\n";
259 result = 0;
260 }
261 return result;
262 }
263 #endif
264 //----------------------------------------------------------------------------
265
266 /* Test full template specialization of classes. */
267
268 template <class T>
269 struct FullySpecializedClass
270 {
MethodFullySpecializedClass271 static int Method() { return 0; }
272 typedef T Type;
273 };
274
275 VTK_CLASS_TEMPLATE_SPECIALIZATION
276 struct FullySpecializedClass<float>
277 {
MethodFullySpecializedClass278 static int Method() { return 1; }
279 typedef int Type;
280 };
281
282 template <class T>
TestFullySpecializedClassTrait(T *)283 int TestFullySpecializedClassTrait(T*)
284 {
285 typedef VTK_TYPENAME FullySpecializedClass<T>::Type Type;
286 if(static_cast<Type>(3.1) == 3.1)
287 {
288 return 0;
289 }
290 return 1;
291 }
292
TestFullySpecializedClass()293 int TestFullySpecializedClass()
294 {
295 int result = 1;
296 int should_be_0 = FullySpecializedClass<int>::Method();
297 if(should_be_0 != 0)
298 {
299 cerr << "FullySpecializedClass<int>::Method() returned "
300 << should_be_0 << ", not 0.\n";
301 result = 0;
302 }
303 int should_be_1 = FullySpecializedClass<float>::Method();
304 if(should_be_1 != 1)
305 {
306 cerr << "FullySpecializedClass<float>::Method() returned "
307 << should_be_1 << ", not 1.\n";
308 result = 0;
309 }
310 if(!TestFullySpecializedClassTrait(static_cast<float*>(0)))
311 {
312 cerr << "Trait lookup of float didn't produce int.";
313 result = 0;
314 }
315 return result;
316 }
317
318 //----------------------------------------------------------------------------
319
320 /* Test if(int x = f()) style scoping. */
321
TestIfScopeHelper(int i)322 int TestIfScopeHelper(int i)
323 {
324 int result = 1;
325 if(int x = i)
326 {
327 if(x != i)
328 {
329 cerr << "TestIfScope: x != " << i << "\n";
330 result = 0;
331 }
332 }
333 else
334 {
335 if(x != i)
336 {
337 cerr << "TestIfScope: x != " << i << "\n";
338 result = 0;
339 }
340 }
341 int x = result;
342 return x;
343 }
344
TestIfScope()345 int TestIfScope()
346 {
347 int result = 1;
348 if(!TestIfScopeHelper(1))
349 {
350 result = 0;
351 }
352 if(!TestIfScopeHelper(0))
353 {
354 result = 0;
355 }
356 return result;
357 }
358
359 //----------------------------------------------------------------------------
360
361 /* Test non-type template parameter. */
362
363 template <int I>
364 struct NonTypeTemplate
365 {
GetValueNonTypeTemplate366 static int GetValue() { return I; }
367 };
368
TestNonTypeTemplate()369 int TestNonTypeTemplate()
370 {
371 int result = 1;
372 if(NonTypeTemplate<0>::GetValue() != 0)
373 {
374 cerr << "NonTypeTemplate<0>::GetValue() != 0\n";
375 result = 0;
376 }
377 if(NonTypeTemplate<1>::GetValue() != 1)
378 {
379 cerr << "NonTypeTemplate<1>::GetValue() != 1\n";
380 result = 0;
381 }
382 if(NonTypeTemplate<2>::GetValue() != 2)
383 {
384 cerr << "NonTypeTemplate<2>::GetValue() != 2\n";
385 result = 0;
386 }
387 return result;
388 }
389
390 //----------------------------------------------------------------------------
391
392 /* Test mixed type and non-type template arguments in a non-trival way. */
393
394 #if !defined(__BORLANDC__)
395 // Borland does not support this fancy array template.
396 template <class T, int N>
TestMixedTypeTemplateFunction(T (*)[N])397 int TestMixedTypeTemplateFunction(T (*)[N])
398 {
399 return N;
400 }
TestMixedTypeTemplate()401 int TestMixedTypeTemplate()
402 {
403 int x2[2];
404 float x3[3];
405 int result = 1;
406 if(TestMixedTypeTemplateFunction(&x2) != 2)
407 {
408 cerr << "TestMixedTypeTemplateFunction(&x2) != 2\n";
409 result = 0;
410 }
411 if(TestMixedTypeTemplateFunction(&x3) != 3)
412 {
413 cerr << "TestMixedTypeTemplateFunction(&x3) != 3\n";
414 result = 0;
415 }
416 return result;
417 }
418 #endif
419
420 //----------------------------------------------------------------------------
421
TestBinaryWriting()422 int TestBinaryWriting()
423 {
424 int result = 1;
425 // ios::binary does not exist on SGI and OSF cxx (DEC)
426 // it failed to compile on these machines:
427 // ct02_oc.crd IRIX64-6.5-CC-64
428 // manifold IRIX64-6.5-CC-n32
429 // kulu.crd IRIX64-6.5-CC-o32
430 // a62.iue.tuwien.ac.at OSF1-V5.1-cxx
431 #if defined(VTK_CXX_SGI) || defined( __DECCXX_VER)
432 ofstream fout_with_warning_C4701("TestCxxFeatures_TestBinaryWriting", ios::out );
433 #else
434 ofstream fout_with_warning_C4701("TestCxxFeatures_TestBinaryWriting", ios::out | ios::binary);
435 #endif
436 if(!fout_with_warning_C4701)
437 {
438 cerr << "Error opening TestCxxFeatures_TestBinaryWriting for binary writing.\n";
439 result = 0;
440 }
441 return result;
442 }
443
444 //----------------------------------------------------------------------------
445
446 class SafeBoolIdiomClass
447 {
448 private:
DummySafeBoolIdiomClass::SafeBoolDummy449 struct SafeBoolDummy { void Dummy() {} };
450 typedef void (SafeBoolDummy::* SafeBool)();
451 public:
SafeBoolIdiomClass(int x)452 SafeBoolIdiomClass(int x): Value(x) {}
operator SafeBool()453 operator SafeBool()
454 {
455 return this->Value? &SafeBoolDummy::Dummy : 0;
456 }
operator !()457 SafeBool operator !()
458 {
459 return this->Value? 0 : &SafeBoolDummy::Dummy;
460 }
461 protected:
462 int Value;
463 };
464
TestSafeBoolIdiom()465 int TestSafeBoolIdiom()
466 {
467 int result = 1;
468 SafeBoolIdiomClass cTrue(1);
469 SafeBoolIdiomClass cFalse(0);
470 if(cTrue) {}
471 else
472 {
473 cerr << "if(cTrue) evaluates to false.\n";
474 result = 0;
475 }
476 if(!cTrue)
477 {
478 cerr << "if(!cTrue) evaluates to true.\n";
479 result = 0;
480 }
481 if(cFalse)
482 {
483 cerr << "if(cFalse) evaluates to true.\n";
484 result = 0;
485 }
486 if(!cFalse) {}
487 else
488 {
489 cerr << "if(!cFalse) evaluates to false.\n";
490 result = 0;
491 }
492 return result;
493 }
494
495 //----------------------------------------------------------------------------
496
497 /* Test use of exceptions. */
498
499 #if defined(_MSC_VER)
500 # pragma warning (push)
501 # pragma warning (disable: 4702) /* Unreachable code. */
502 #endif
503
504 class TestExceptionUnwind
505 {
506 int* pvalue;
507 public:
TestExceptionUnwind(int * p)508 TestExceptionUnwind(int* p): pvalue(p) {}
~TestExceptionUnwind()509 ~TestExceptionUnwind() { *pvalue = 1; }
Use()510 void Use() {}
511 };
512
513 class ExceptionClass {};
514
TestThrowException(int * p)515 void TestThrowException(int* p)
516 {
517 TestExceptionUnwind unwind(p);
518 unwind.Use();
519 throw ExceptionClass();
520 }
521
TestException()522 int TestException()
523 {
524 int value = 0;
525 try
526 {
527 TestThrowException(&value);
528 }
529 catch(ExceptionClass&)
530 {
531 if(value)
532 {
533 return 1;
534 }
535 else
536 {
537 cerr << "TestExceptionUnwind object not destroyed!" << endl;
538 return 0;
539 }
540 }
541 catch(...)
542 {
543 cerr << "ExceptionClass not caught!" << endl;
544 return 0;
545 }
546 cerr << "No exception caught!" << endl;
547 return 0;
548 }
549
550 #if defined(_MSC_VER)
551 # pragma warning (pop)
552 #endif
553
554 //----------------------------------------------------------------------------
555
556 /* Test void return type syntax. */
557
TestVoidReturnInner()558 void TestVoidReturnInner() {}
TestVoidReturnOuter()559 void TestVoidReturnOuter()
560 {
561 // MIPSpro 7.3 does not support void returns.
562 #if !(defined(_COMPILER_VERSION) && (_COMPILER_VERSION < 740))
563 return TestVoidReturnInner();
564 #endif
565 }
566
567 // MIPSpro warns about type qualifiers on return types.
568 #if defined(_COMPILER_VERSION)
569 # pragma set woff 3303 // type qualifier on return is meaningless
570 #endif
571 // Intel C++ warns about type qualifiers on return types.
572 #if defined(__INTEL_COMPILER)
573 # pragma warning (push)
574 # pragma warning (disable:858) // type qualifier on return is meaningless
575 #endif
576
577 // clang warns about type qualifiers on return types.
578 #if defined(__clang__)
579 # pragma clang diagnostic push
580 # pragma clang diagnostic ignored "-Wignored-qualifiers"
581 #endif
582
583 // gcc>=4.3 says type qualifiers ignored on function return type
584 #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)))
585 # pragma GCC diagnostic push
586 #endif
587 #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)))
588 # pragma GCC diagnostic ignored "-Wignored-qualifiers"
589 #endif
590
591 // aCC warns "type qualifier on return type is meaningless" - just omit the
592 // function on aCC builds since there is no way to suppress the warning via
593 // pragmas...
594 #if !defined(__HP_aCC)
TestVoidConstReturn()595 void const TestVoidConstReturn() {}
596 #endif
597
598 #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)))
599 # pragma GCC diagnostic pop
600 #endif
601
602 #if defined(__clang__)
603 # pragma clang diagnostic pop
604 #endif
605
606 #if defined(__INTEL_COMPILER)
607 # pragma warning (pop)
608 #endif
609
610 #if defined(_COMPILER_VERSION)
611 # pragma reset woff 3303 // type qualifier on return is meaningless
612 #endif
613
614
615 //-------------------------------------------------------------------
616 // See if the following code works on all platforms
617 #if defined(_MSC_VER) && defined(_DEBUG)
618 /* MSVC debug hook to prevent dialogs when running from DART. */
619 # include <crtdbg.h>
TestDriverDebugReport(int type,char * message,int * retVal)620 static int TestDriverDebugReport(int type, char* message, int* retVal)
621 {
622 (void)type; (void)retVal;
623 fprintf(stderr, message);
624 exit(1);
625 }
626 #endif
627
628
629 //----------------------------------------------------------------------------
630
631 /* Test setlocale */
632 #include <locale.h>
TestSetLocale()633 int TestSetLocale()
634 {
635 char *oldLocale = strdup(setlocale(LC_NUMERIC,NULL));
636 setlocale(LC_NUMERIC,"English");
637
638 // restore the local
639 if (oldLocale)
640 {
641 setlocale(LC_NUMERIC,oldLocale);
642 free(oldLocale);
643 return 1;
644 }
645 return 0;
646 }
647
648 //----------------------------------------------------------------------------
649
650 #define DO_TEST(x) \
651 if(x()) { cout << "Passed: " #x "\n"; } \
652 else { cout << "Failed: " #x "\n"; result = 1; }
653
main()654 int main()
655 {
656 int result = 0;
657 DO_TEST(TestFullySpecializedFunction);
658 DO_TEST(TestNonTemplateMemberTemplate);
659 DO_TEST(TestTemplateMemberTemplate);
660 #if !defined(VTK_CXX_SGI_6)
661 DO_TEST(TestBool);
662 #endif
663 DO_TEST(TestFullySpecializedClass);
664 DO_TEST(TestIfScope);
665 DO_TEST(TestNonTypeTemplate);
666 #if !defined(__BORLANDC__)
667 DO_TEST(TestMixedTypeTemplate);
668 #endif
669 DO_TEST(TestBinaryWriting);
670 DO_TEST(TestSafeBoolIdiom);
671 DO_TEST(TestException);
672 DO_TEST(TestSetLocale);
673
674 #if defined(_MSC_VER) && defined(_DEBUG)
675 // just call the code to shut up a linker warning
676 int retVal = 0;
677 if (result)
678 {
679 // really shouldn't be called unless something else failed
680 // just want to make the compiler think it might get called
681 // all this will be yanked once I see the results of this test
682 TestDriverDebugReport(0, "a temp test", &retVal);
683 }
684 #endif
685 return result;
686 }
687