1 // RUN: %clang_cc1 -ast-dump %s | \ 2 // RUN: FileCheck --implicit-check-not OwnerAttr --implicit-check-not PointerAttr %s 3 4 // Test attribute inference for types in the standard library. 5 namespace std { 6 // Attributes are inferred for a (complete) class. 7 class any { 8 // CHECK: CXXRecordDecl {{.*}} any 9 // CHECK: OwnerAttr {{.*}} 10 }; 11 12 // Attributes are inferred for instantiations of a complete template. 13 template <typename T> 14 class vector { 15 public: 16 class iterator {}; 17 // CHECK: ClassTemplateDecl {{.*}} vector 18 // CHECK: OwnerAttr {{.*}} 19 // CHECK: CXXRecordDecl {{.*}} iterator 20 // CHECK: PointerAttr {{.*}} 21 // CHECK: ClassTemplateSpecializationDecl {{.*}} vector 22 // CHECK: TemplateArgument type 'int' 23 // CHECK: OwnerAttr 24 // CHECK: CXXRecordDecl {{.*}} iterator 25 // CHECK: PointerAttr {{.*}} 26 }; 27 static_assert(sizeof(vector<int>), ""); // Force instantiation. 28 static_assert(sizeof(vector<int>::iterator), ""); // Force instantiation. 29 30 // If std::container::iterator is a using declaration, attributes are inferred 31 // for the underlying class. 32 template <typename T> 33 class __set_iterator {}; 34 // CHECK: ClassTemplateDecl {{.*}} __set_iterator 35 // CHECK: PointerAttr 36 // CHECK: ClassTemplateSpecializationDecl {{.*}} __set_iterator 37 // CHECK: TemplateArgument type 'int' 38 // CHECK: PointerAttr 39 40 template <typename T> 41 class set { 42 // CHECK: ClassTemplateDecl {{.*}} set 43 // CHECK: OwnerAttr {{.*}} 44 // CHECK: ClassTemplateSpecializationDecl {{.*}} set 45 // CHECK: OwnerAttr {{.*}} 46 public: 47 using iterator = __set_iterator<T>; 48 }; 49 static_assert(sizeof(set<int>::iterator), ""); // Force instantiation. 50 51 // If std::container::iterator is a typedef, attributes are inferred for the 52 // underlying class. 53 template <typename T> 54 class __map_iterator {}; 55 // CHECK: ClassTemplateDecl {{.*}} __map_iterator 56 // CHECK: PointerAttr 57 // CHECK: ClassTemplateSpecializationDecl {{.*}} __map_iterator 58 // CHECK: TemplateArgument type 'int' 59 // CHECK: PointerAttr 60 61 template <typename T> 62 class map { 63 // CHECK: ClassTemplateDecl {{.*}} map 64 // CHECK: OwnerAttr {{.*}} 65 // CHECK: ClassTemplateSpecializationDecl {{.*}} map 66 // CHECK: OwnerAttr {{.*}} 67 public: 68 typedef __map_iterator<T> iterator; 69 }; 70 static_assert(sizeof(map<int>::iterator), ""); // Force instantiation. 71 72 // Inline namespaces are ignored when checking if 73 // the class lives in the std namespace. 74 inline namespace inlinens { 75 template <typename T> 76 class __unordered_map_iterator {}; 77 // CHECK: ClassTemplateDecl {{.*}} __unordered_map_iterator 78 // CHECK: PointerAttr 79 // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_map_iterator 80 // CHECK: TemplateArgument type 'int' 81 // CHECK: PointerAttr 82 83 template <typename T> 84 class unordered_map { 85 // CHECK: ClassTemplateDecl {{.*}} unordered_map 86 // CHECK: OwnerAttr {{.*}} 87 // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_map 88 // CHECK: OwnerAttr {{.*}} 89 public: 90 typedef __unordered_map_iterator<T> iterator; 91 }; 92 static_assert(sizeof(unordered_map<int>::iterator), ""); // Force instantiation. 93 } // namespace inlinens 94 95 // The iterator typedef is a DependentNameType. 96 template <typename T> 97 class __unordered_multimap_iterator {}; 98 // CHECK: ClassTemplateDecl {{.*}} __unordered_multimap_iterator 99 // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_multimap_iterator 100 // CHECK: TemplateArgument type 'int' 101 // CHECK: PointerAttr 102 103 template <typename T> 104 class __unordered_multimap_base { 105 public: 106 using iterator = __unordered_multimap_iterator<T>; 107 }; 108 109 template <typename T> 110 class unordered_multimap { 111 // CHECK: ClassTemplateDecl {{.*}} unordered_multimap 112 // CHECK: OwnerAttr {{.*}} 113 // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_multimap 114 // CHECK: OwnerAttr {{.*}} 115 public: 116 using _Mybase = __unordered_multimap_base<T>; 117 using iterator = typename _Mybase::iterator; 118 }; 119 static_assert(sizeof(unordered_multimap<int>::iterator), ""); // Force instantiation. 120 121 // The canonical declaration of the iterator template is not its definition. 122 template <typename T> 123 class __unordered_multiset_iterator; 124 // CHECK: ClassTemplateDecl {{.*}} __unordered_multiset_iterator 125 // CHECK: PointerAttr 126 // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_multiset_iterator 127 // CHECK: TemplateArgument type 'int' 128 // CHECK: PointerAttr 129 130 template <typename T> 131 class __unordered_multiset_iterator { 132 // CHECK: ClassTemplateDecl {{.*}} prev {{.*}} __unordered_multiset_iterator 133 // CHECK: PointerAttr 134 }; 135 136 template <typename T> 137 class unordered_multiset { 138 // CHECK: ClassTemplateDecl {{.*}} unordered_multiset 139 // CHECK: OwnerAttr {{.*}} 140 // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_multiset 141 // CHECK: OwnerAttr {{.*}} 142 public: 143 using iterator = __unordered_multiset_iterator<T>; 144 }; 145 146 static_assert(sizeof(unordered_multiset<int>::iterator), ""); // Force instantiation. 147 148 // std::list has an implicit gsl::Owner attribute, 149 // but explicit attributes take precedence. 150 template <typename T> 151 class [[gsl::Pointer]] list{}; 152 // CHECK: ClassTemplateDecl {{.*}} list 153 // CHECK: PointerAttr {{.*}} 154 // CHECK: ClassTemplateSpecializationDecl {{.*}} list 155 // CHECK: PointerAttr {{.*}} 156 157 static_assert(sizeof(list<int>), ""); // Force instantiation. 158 159 // Forward declared template (Owner). 160 template < 161 class CharT, 162 class Traits> 163 class basic_regex; 164 // CHECK: ClassTemplateDecl {{.*}} basic_regex 165 // CHECK: OwnerAttr {{.*}} 166 167 // Forward declared template (Pointer). 168 template <class T> 169 class reference_wrapper; 170 // CHECK: ClassTemplateDecl {{.*}} reference_wrapper 171 // CHECK: PointerAttr {{.*}} 172 173 class some_unknown_type; 174 // CHECK: CXXRecordDecl {{.*}} some_unknown_type 175 176 } // namespace std 177 178 namespace user { 179 // If a class is not in the std namespace, we don't infer the attributes. 180 class any { 181 }; 182 } // namespace user 183