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