Mercurial > hg > CbC > CbC_gcc
comparison gcc/attribs.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Functions dealing with attribute handling, used by most front ends. | 1 /* Functions dealing with attribute handling, used by most front ends. |
2 Copyright (C) 1992-2017 Free Software Foundation, Inc. | 2 Copyright (C) 1992-2018 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
7 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
26 #include "diagnostic-core.h" | 26 #include "diagnostic-core.h" |
27 #include "attribs.h" | 27 #include "attribs.h" |
28 #include "stor-layout.h" | 28 #include "stor-layout.h" |
29 #include "langhooks.h" | 29 #include "langhooks.h" |
30 #include "plugin.h" | 30 #include "plugin.h" |
31 #include "selftest.h" | |
32 #include "hash-set.h" | |
31 | 33 |
32 /* Table of the tables of attributes (common, language, format, machine) | 34 /* Table of the tables of attributes (common, language, format, machine) |
33 searched. */ | 35 searched. */ |
34 static const struct attribute_spec *attribute_tables[4]; | 36 static const struct attribute_spec *attribute_tables[4]; |
35 | 37 |
92 | 94 |
93 /* Default empty table of attributes. */ | 95 /* Default empty table of attributes. */ |
94 | 96 |
95 static const struct attribute_spec empty_attribute_table[] = | 97 static const struct attribute_spec empty_attribute_table[] = |
96 { | 98 { |
97 { NULL, 0, 0, false, false, false, NULL, false } | 99 { NULL, 0, 0, false, false, false, false, NULL, NULL } |
98 }; | 100 }; |
99 | 101 |
100 /* Return base name of the attribute. Ie '__attr__' is turned into 'attr'. | 102 /* Return base name of the attribute. Ie '__attr__' is turned into 'attr'. |
101 To avoid need for copying, we simply return length of the string. */ | 103 To avoid need for copying, we simply return length of the string. */ |
102 | 104 |
114 /* Insert an array of attributes ATTRIBUTES into a namespace. This | 116 /* Insert an array of attributes ATTRIBUTES into a namespace. This |
115 array must be NULL terminated. NS is the name of attribute | 117 array must be NULL terminated. NS is the name of attribute |
116 namespace. The function returns the namespace into which the | 118 namespace. The function returns the namespace into which the |
117 attributes have been registered. */ | 119 attributes have been registered. */ |
118 | 120 |
119 scoped_attributes* | 121 scoped_attributes * |
120 register_scoped_attributes (const struct attribute_spec * attributes, | 122 register_scoped_attributes (const struct attribute_spec *attributes, |
121 const char* ns) | 123 const char *ns) |
122 { | 124 { |
123 scoped_attributes *result = NULL; | 125 scoped_attributes *result = NULL; |
124 | 126 |
125 /* See if we already have attributes in the namespace NS. */ | 127 /* See if we already have attributes in the namespace NS. */ |
126 result = find_attribute_namespace (ns); | 128 result = find_attribute_namespace (ns); |
341 if (cxx11_attribute_p (attr)) | 343 if (cxx11_attribute_p (attr)) |
342 return TREE_PURPOSE (TREE_PURPOSE (attr)); | 344 return TREE_PURPOSE (TREE_PURPOSE (attr)); |
343 return get_identifier ("gnu"); | 345 return get_identifier ("gnu"); |
344 } | 346 } |
345 | 347 |
348 /* Check LAST_DECL and NODE of the same symbol for attributes that are | |
349 recorded in SPEC to be mutually exclusive with ATTRNAME, diagnose | |
350 them, and return true if any have been found. NODE can be a DECL | |
351 or a TYPE. */ | |
352 | |
353 static bool | |
354 diag_attr_exclusions (tree last_decl, tree node, tree attrname, | |
355 const attribute_spec *spec) | |
356 { | |
357 const attribute_spec::exclusions *excl = spec->exclude; | |
358 | |
359 tree_code code = TREE_CODE (node); | |
360 | |
361 if ((code == FUNCTION_DECL && !excl->function | |
362 && (!excl->type || !spec->affects_type_identity)) | |
363 || (code == VAR_DECL && !excl->variable | |
364 && (!excl->type || !spec->affects_type_identity)) | |
365 || (((code == TYPE_DECL || RECORD_OR_UNION_TYPE_P (node)) && !excl->type))) | |
366 return false; | |
367 | |
368 /* True if an attribute that's mutually exclusive with ATTRNAME | |
369 has been found. */ | |
370 bool found = false; | |
371 | |
372 if (last_decl && last_decl != node && TREE_TYPE (last_decl) != node) | |
373 { | |
374 /* Check both the last DECL and its type for conflicts with | |
375 the attribute being added to the current decl or type. */ | |
376 found |= diag_attr_exclusions (last_decl, last_decl, attrname, spec); | |
377 tree decl_type = TREE_TYPE (last_decl); | |
378 found |= diag_attr_exclusions (last_decl, decl_type, attrname, spec); | |
379 } | |
380 | |
381 /* NODE is either the current DECL to which the attribute is being | |
382 applied or its TYPE. For the former, consider the attributes on | |
383 both the DECL and its type. */ | |
384 tree attrs[2]; | |
385 | |
386 if (DECL_P (node)) | |
387 { | |
388 attrs[0] = DECL_ATTRIBUTES (node); | |
389 attrs[1] = TYPE_ATTRIBUTES (TREE_TYPE (node)); | |
390 } | |
391 else | |
392 { | |
393 attrs[0] = TYPE_ATTRIBUTES (node); | |
394 attrs[1] = NULL_TREE; | |
395 } | |
396 | |
397 /* Iterate over the mutually exclusive attribute names and verify | |
398 that the symbol doesn't contain it. */ | |
399 for (unsigned i = 0; i != sizeof attrs / sizeof *attrs; ++i) | |
400 { | |
401 if (!attrs[i]) | |
402 continue; | |
403 | |
404 for ( ; excl->name; ++excl) | |
405 { | |
406 /* Avoid checking the attribute against itself. */ | |
407 if (is_attribute_p (excl->name, attrname)) | |
408 continue; | |
409 | |
410 if (!lookup_attribute (excl->name, attrs[i])) | |
411 continue; | |
412 | |
413 /* An exclusion may apply either to a function declaration, | |
414 type declaration, or a field/variable declaration, or | |
415 any subset of the three. */ | |
416 if (TREE_CODE (node) == FUNCTION_DECL | |
417 && !excl->function) | |
418 continue; | |
419 | |
420 if (TREE_CODE (node) == TYPE_DECL | |
421 && !excl->type) | |
422 continue; | |
423 | |
424 if ((TREE_CODE (node) == FIELD_DECL | |
425 || TREE_CODE (node) == VAR_DECL) | |
426 && !excl->variable) | |
427 continue; | |
428 | |
429 found = true; | |
430 | |
431 /* Print a note? */ | |
432 bool note = last_decl != NULL_TREE; | |
433 auto_diagnostic_group d; | |
434 if (TREE_CODE (node) == FUNCTION_DECL | |
435 && fndecl_built_in_p (node)) | |
436 note &= warning (OPT_Wattributes, | |
437 "ignoring attribute %qE in declaration of " | |
438 "a built-in function %qD because it conflicts " | |
439 "with attribute %qs", | |
440 attrname, node, excl->name); | |
441 else | |
442 note &= warning (OPT_Wattributes, | |
443 "ignoring attribute %qE because " | |
444 "it conflicts with attribute %qs", | |
445 attrname, excl->name); | |
446 | |
447 if (note) | |
448 inform (DECL_SOURCE_LOCATION (last_decl), | |
449 "previous declaration here"); | |
450 } | |
451 } | |
452 | |
453 return found; | |
454 } | |
346 | 455 |
347 /* Process the attributes listed in ATTRIBUTES and install them in *NODE, | 456 /* Process the attributes listed in ATTRIBUTES and install them in *NODE, |
348 which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL, | 457 which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL, |
349 it should be modified in place; if a TYPE, a copy should be created | 458 it should be modified in place; if a TYPE, a copy should be created |
350 unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS. FLAGS gives further | 459 unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS. FLAGS gives further |
352 from tree.h. Depending on these flags, some attributes may be | 461 from tree.h. Depending on these flags, some attributes may be |
353 returned to be applied at a later stage (for example, to apply | 462 returned to be applied at a later stage (for example, to apply |
354 a decl attribute to the declaration rather than to its type). */ | 463 a decl attribute to the declaration rather than to its type). */ |
355 | 464 |
356 tree | 465 tree |
357 decl_attributes (tree *node, tree attributes, int flags) | 466 decl_attributes (tree *node, tree attributes, int flags, |
467 tree last_decl /* = NULL_TREE */) | |
358 { | 468 { |
359 tree a; | 469 tree a; |
360 tree returned_attrs = NULL_TREE; | 470 tree returned_attrs = NULL_TREE; |
361 | 471 |
362 if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node) | 472 if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node) |
431 attributes = tree_cons (get_identifier ("no_icf"), NULL, attributes); | 541 attributes = tree_cons (get_identifier ("no_icf"), NULL, attributes); |
432 } | 542 } |
433 | 543 |
434 targetm.insert_attributes (*node, &attributes); | 544 targetm.insert_attributes (*node, &attributes); |
435 | 545 |
546 /* Note that attributes on the same declaration are not necessarily | |
547 in the same order as in the source. */ | |
436 for (a = attributes; a; a = TREE_CHAIN (a)) | 548 for (a = attributes; a; a = TREE_CHAIN (a)) |
437 { | 549 { |
438 tree ns = get_attribute_namespace (a); | 550 tree ns = get_attribute_namespace (a); |
439 tree name = get_attribute_name (a); | 551 tree name = get_attribute_name (a); |
440 tree args = TREE_VALUE (a); | 552 tree args = TREE_VALUE (a); |
441 tree *anode = node; | 553 tree *anode = node; |
442 const struct attribute_spec *spec = | 554 const struct attribute_spec *spec |
443 lookup_scoped_attribute_spec (ns, name); | 555 = lookup_scoped_attribute_spec (ns, name); |
444 bool no_add_attrs = 0; | |
445 int fn_ptr_quals = 0; | 556 int fn_ptr_quals = 0; |
446 tree fn_ptr_tmp = NULL_TREE; | 557 tree fn_ptr_tmp = NULL_TREE; |
447 | 558 |
448 if (spec == NULL) | 559 if (spec == NULL) |
449 { | 560 { |
474 && !(flags & ATTR_FLAG_TYPE_IN_PLACE)) | 585 && !(flags & ATTR_FLAG_TYPE_IN_PLACE)) |
475 { | 586 { |
476 /* This is a c++11 attribute that appertains to a | 587 /* This is a c++11 attribute that appertains to a |
477 type-specifier, outside of the definition of, a class | 588 type-specifier, outside of the definition of, a class |
478 type. Ignore it. */ | 589 type. Ignore it. */ |
590 auto_diagnostic_group d; | |
479 if (warning (OPT_Wattributes, "attribute ignored")) | 591 if (warning (OPT_Wattributes, "attribute ignored")) |
480 inform (input_location, | 592 inform (input_location, |
481 "an attribute that appertains to a type-specifier " | 593 "an attribute that appertains to a type-specifier " |
482 "is ignored"); | 594 "is ignored"); |
483 continue; | 595 continue; |
488 if (flags & ((int) ATTR_FLAG_DECL_NEXT | 600 if (flags & ((int) ATTR_FLAG_DECL_NEXT |
489 | (int) ATTR_FLAG_FUNCTION_NEXT | 601 | (int) ATTR_FLAG_FUNCTION_NEXT |
490 | (int) ATTR_FLAG_ARRAY_NEXT)) | 602 | (int) ATTR_FLAG_ARRAY_NEXT)) |
491 { | 603 { |
492 /* Pass on this attribute to be tried again. */ | 604 /* Pass on this attribute to be tried again. */ |
493 returned_attrs = tree_cons (name, args, returned_attrs); | 605 tree attr = tree_cons (name, args, NULL_TREE); |
606 returned_attrs = chainon (returned_attrs, attr); | |
494 continue; | 607 continue; |
495 } | 608 } |
496 else | 609 else |
497 { | 610 { |
498 warning (OPT_Wattributes, "%qE attribute does not apply to types", | 611 warning (OPT_Wattributes, "%qE attribute does not apply to types", |
533 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; | 646 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; |
534 } | 647 } |
535 else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT) | 648 else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT) |
536 { | 649 { |
537 /* Pass on this attribute to be tried again. */ | 650 /* Pass on this attribute to be tried again. */ |
538 returned_attrs = tree_cons (name, args, returned_attrs); | 651 tree attr = tree_cons (name, args, NULL_TREE); |
652 returned_attrs = chainon (returned_attrs, attr); | |
539 continue; | 653 continue; |
540 } | 654 } |
541 | 655 |
542 if (TREE_CODE (*anode) != FUNCTION_TYPE | 656 if (TREE_CODE (*anode) != FUNCTION_TYPE |
543 && TREE_CODE (*anode) != METHOD_TYPE) | 657 && TREE_CODE (*anode) != METHOD_TYPE) |
555 { | 669 { |
556 warning (OPT_Wattributes, "type attributes ignored after type is already defined"); | 670 warning (OPT_Wattributes, "type attributes ignored after type is already defined"); |
557 continue; | 671 continue; |
558 } | 672 } |
559 | 673 |
674 bool no_add_attrs = false; | |
675 | |
676 /* Check for exclusions with other attributes on the current | |
677 declation as well as the last declaration of the same | |
678 symbol already processed (if one exists). Detect and | |
679 reject incompatible attributes. */ | |
680 bool built_in = flags & ATTR_FLAG_BUILT_IN; | |
681 if (spec->exclude | |
682 && (flag_checking || !built_in)) | |
683 { | |
684 /* Always check attributes on user-defined functions. | |
685 Check them on built-ins only when -fchecking is set. | |
686 Ignore __builtin_unreachable -- it's both const and | |
687 noreturn. */ | |
688 | |
689 if (!built_in | |
690 || !DECL_P (*anode) | |
691 || (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE | |
692 && (DECL_FUNCTION_CODE (*anode) | |
693 != BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE))) | |
694 { | |
695 bool no_add = diag_attr_exclusions (last_decl, *anode, name, spec); | |
696 if (!no_add && anode != node) | |
697 no_add = diag_attr_exclusions (last_decl, *node, name, spec); | |
698 no_add_attrs |= no_add; | |
699 } | |
700 } | |
701 | |
702 if (no_add_attrs) | |
703 continue; | |
704 | |
560 if (spec->handler != NULL) | 705 if (spec->handler != NULL) |
561 { | 706 { |
562 int cxx11_flag = | 707 int cxx11_flag = |
563 cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0; | 708 cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0; |
564 | 709 |
565 returned_attrs = chainon ((*spec->handler) (anode, name, args, | 710 /* Pass in an array of the current declaration followed |
566 flags|cxx11_flag, | 711 by the last pushed/merged declaration if one exists. |
567 &no_add_attrs), | 712 If the handler changes CUR_AND_LAST_DECL[0] replace |
568 returned_attrs); | 713 *ANODE with its value. */ |
714 tree cur_and_last_decl[] = { *anode, last_decl }; | |
715 tree ret = (spec->handler) (cur_and_last_decl, name, args, | |
716 flags|cxx11_flag, &no_add_attrs); | |
717 | |
718 *anode = cur_and_last_decl[0]; | |
719 if (ret == error_mark_node) | |
720 { | |
721 warning (OPT_Wattributes, "%qE attribute ignored", name); | |
722 no_add_attrs = true; | |
723 } | |
724 else | |
725 returned_attrs = chainon (ret, returned_attrs); | |
569 } | 726 } |
570 | 727 |
571 /* Layout the decl in case anything changed. */ | 728 /* Layout the decl in case anything changed. */ |
572 if (spec->type_required && DECL_P (*node) | 729 if (spec->type_required && DECL_P (*node) |
573 && (VAR_P (*node) | 730 && (VAR_P (*node) |
987 if (lang_hooks.types.copy_lang_qualifiers | 1144 if (lang_hooks.types.copy_lang_qualifiers |
988 && otype != TYPE_MAIN_VARIANT (otype)) | 1145 && otype != TYPE_MAIN_VARIANT (otype)) |
989 ttype = (lang_hooks.types.copy_lang_qualifiers | 1146 ttype = (lang_hooks.types.copy_lang_qualifiers |
990 (ttype, TYPE_MAIN_VARIANT (otype))); | 1147 (ttype, TYPE_MAIN_VARIANT (otype))); |
991 | 1148 |
992 ntype = build_distinct_type_copy (ttype); | 1149 tree dtype = ntype = build_distinct_type_copy (ttype); |
993 | 1150 |
994 TYPE_ATTRIBUTES (ntype) = attribute; | 1151 TYPE_ATTRIBUTES (ntype) = attribute; |
995 | 1152 |
996 hashval_t hash = type_hash_canon_hash (ntype); | 1153 hashval_t hash = type_hash_canon_hash (ntype); |
997 ntype = type_hash_canon (hash, ntype); | 1154 ntype = type_hash_canon (hash, ntype); |
998 | 1155 |
999 /* If the target-dependent attributes make NTYPE different from | 1156 if (ntype != dtype) |
1000 its canonical type, we will need to use structural equality | 1157 /* This variant was already in the hash table, don't mess with |
1001 checks for this type. */ | 1158 TYPE_CANONICAL. */; |
1002 if (TYPE_STRUCTURAL_EQUALITY_P (ttype) | 1159 else if (TYPE_STRUCTURAL_EQUALITY_P (ttype) |
1003 || !comp_type_attributes (ntype, ttype)) | 1160 || !comp_type_attributes (ntype, ttype)) |
1161 /* If the target-dependent attributes make NTYPE different from | |
1162 its canonical type, we will need to use structural equality | |
1163 checks for this type. | |
1164 | |
1165 We shouldn't get here for stripping attributes from a type; | |
1166 the no-attribute type might not need structural comparison. But | |
1167 we can if was discarded from type_hash_table. */ | |
1004 SET_TYPE_STRUCTURAL_EQUALITY (ntype); | 1168 SET_TYPE_STRUCTURAL_EQUALITY (ntype); |
1005 else if (TYPE_CANONICAL (ntype) == ntype) | 1169 else if (TYPE_CANONICAL (ntype) == ntype) |
1006 TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); | 1170 TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); |
1007 | 1171 |
1008 ttype = build_qualified_type (ntype, quals); | 1172 ttype = build_qualified_type (ntype, quals); |
1645 list = TREE_CHAIN (list); | 1809 list = TREE_CHAIN (list); |
1646 } | 1810 } |
1647 | 1811 |
1648 return list; | 1812 return list; |
1649 } | 1813 } |
1814 | |
1815 #if CHECKING_P | |
1816 | |
1817 namespace selftest | |
1818 { | |
1819 | |
1820 /* Helper types to verify the consistency attribute exclusions. */ | |
1821 | |
1822 typedef std::pair<const char *, const char *> excl_pair; | |
1823 | |
1824 struct excl_hash_traits: typed_noop_remove<excl_pair> | |
1825 { | |
1826 typedef excl_pair value_type; | |
1827 typedef value_type compare_type; | |
1828 | |
1829 static hashval_t hash (const value_type &x) | |
1830 { | |
1831 hashval_t h1 = htab_hash_string (x.first); | |
1832 hashval_t h2 = htab_hash_string (x.second); | |
1833 return h1 ^ h2; | |
1834 } | |
1835 | |
1836 static bool equal (const value_type &x, const value_type &y) | |
1837 { | |
1838 return !strcmp (x.first, y.first) && !strcmp (x.second, y.second); | |
1839 } | |
1840 | |
1841 static void mark_deleted (value_type &x) | |
1842 { | |
1843 x = value_type (NULL, NULL); | |
1844 } | |
1845 | |
1846 static void mark_empty (value_type &x) | |
1847 { | |
1848 x = value_type ("", ""); | |
1849 } | |
1850 | |
1851 static bool is_deleted (const value_type &x) | |
1852 { | |
1853 return !x.first && !x.second; | |
1854 } | |
1855 | |
1856 static bool is_empty (const value_type &x) | |
1857 { | |
1858 return !*x.first && !*x.second; | |
1859 } | |
1860 }; | |
1861 | |
1862 | |
1863 /* Self-test to verify that each attribute exclusion is symmetric, | |
1864 meaning that if attribute A is encoded as incompatible with | |
1865 attribute B then the opposite relationship is also encoded. | |
1866 This test also detects most cases of misspelled attribute names | |
1867 in exclusions. */ | |
1868 | |
1869 static void | |
1870 test_attribute_exclusions () | |
1871 { | |
1872 /* Iterate over the array of attribute tables first (with TI0 as | |
1873 the index) and over the array of attribute_spec in each table | |
1874 (with SI0 as the index). */ | |
1875 const size_t ntables = ARRAY_SIZE (attribute_tables); | |
1876 | |
1877 /* Set of pairs of mutually exclusive attributes. */ | |
1878 typedef hash_set<excl_pair, excl_hash_traits> exclusion_set; | |
1879 exclusion_set excl_set; | |
1880 | |
1881 for (size_t ti0 = 0; ti0 != ntables; ++ti0) | |
1882 for (size_t s0 = 0; attribute_tables[ti0][s0].name; ++s0) | |
1883 { | |
1884 const attribute_spec::exclusions *excl | |
1885 = attribute_tables[ti0][s0].exclude; | |
1886 | |
1887 /* Skip each attribute that doesn't define exclusions. */ | |
1888 if (!excl) | |
1889 continue; | |
1890 | |
1891 const char *attr_name = attribute_tables[ti0][s0].name; | |
1892 | |
1893 /* Iterate over the set of exclusions for every attribute | |
1894 (with EI0 as the index) adding the exclusions defined | |
1895 for each to the set. */ | |
1896 for (size_t ei0 = 0; excl[ei0].name; ++ei0) | |
1897 { | |
1898 const char *excl_name = excl[ei0].name; | |
1899 | |
1900 if (!strcmp (attr_name, excl_name)) | |
1901 continue; | |
1902 | |
1903 excl_set.add (excl_pair (attr_name, excl_name)); | |
1904 } | |
1905 } | |
1906 | |
1907 /* Traverse the set of mutually exclusive pairs of attributes | |
1908 and verify that they are symmetric. */ | |
1909 for (exclusion_set::iterator it = excl_set.begin (); | |
1910 it != excl_set.end (); | |
1911 ++it) | |
1912 { | |
1913 if (!excl_set.contains (excl_pair ((*it).second, (*it).first))) | |
1914 { | |
1915 /* An exclusion for an attribute has been found that | |
1916 doesn't have a corresponding exclusion in the opposite | |
1917 direction. */ | |
1918 char desc[120]; | |
1919 sprintf (desc, "'%s' attribute exclusion '%s' must be symmetric", | |
1920 (*it).first, (*it).second); | |
1921 fail (SELFTEST_LOCATION, desc); | |
1922 } | |
1923 } | |
1924 } | |
1925 | |
1926 void | |
1927 attribute_c_tests () | |
1928 { | |
1929 test_attribute_exclusions (); | |
1930 } | |
1931 | |
1932 } /* namespace selftest */ | |
1933 | |
1934 #endif /* CHECKING_P */ |