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 template <> 31 class vector<bool> {}; 32 // CHECK: ClassTemplateSpecializationDecl {{.*}} vector 33 // CHECK: OwnerAttr {{.*}} 34 35 // If std::container::iterator is a using declaration, attributes are inferred 36 // for the underlying class. 37 template <typename T> 38 class __set_iterator {}; 39 // CHECK: ClassTemplateDecl {{.*}} __set_iterator 40 // CHECK: PointerAttr 41 // CHECK: ClassTemplateSpecializationDecl {{.*}} __set_iterator 42 // CHECK: TemplateArgument type 'int' 43 // CHECK: PointerAttr 44 45 template <typename T> 46 class set { 47 // CHECK: ClassTemplateDecl {{.*}} set 48 // CHECK: OwnerAttr {{.*}} 49 // CHECK: ClassTemplateSpecializationDecl {{.*}} set 50 // CHECK: OwnerAttr {{.*}} 51 public: 52 using iterator = __set_iterator<T>; 53 }; 54 static_assert(sizeof(set<int>::iterator), ""); // Force instantiation. 55 56 // If std::container::iterator is a typedef, attributes are inferred for the 57 // underlying class. 58 template <typename T> 59 class __map_iterator {}; 60 // CHECK: ClassTemplateDecl {{.*}} __map_iterator 61 // CHECK: PointerAttr 62 // CHECK: ClassTemplateSpecializationDecl {{.*}} __map_iterator 63 // CHECK: TemplateArgument type 'int' 64 // CHECK: PointerAttr 65 66 template <typename T> 67 class map { 68 // CHECK: ClassTemplateDecl {{.*}} map 69 // CHECK: OwnerAttr {{.*}} 70 // CHECK: ClassTemplateSpecializationDecl {{.*}} map 71 // CHECK: OwnerAttr {{.*}} 72 public: 73 typedef __map_iterator<T> iterator; 74 }; 75 static_assert(sizeof(map<int>::iterator), ""); // Force instantiation. 76 77 // Inline namespaces are ignored when checking if 78 // the class lives in the std namespace. 79 inline namespace inlinens { 80 template <typename T> 81 class __unordered_map_iterator {}; 82 // CHECK: ClassTemplateDecl {{.*}} __unordered_map_iterator 83 // CHECK: PointerAttr 84 // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_map_iterator 85 // CHECK: TemplateArgument type 'int' 86 // CHECK: PointerAttr 87 88 template <typename T> 89 class unordered_map { 90 // CHECK: ClassTemplateDecl {{.*}} unordered_map 91 // CHECK: OwnerAttr {{.*}} 92 // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_map 93 // CHECK: OwnerAttr {{.*}} 94 public: 95 typedef __unordered_map_iterator<T> iterator; 96 }; 97 static_assert(sizeof(unordered_map<int>::iterator), ""); // Force instantiation. 98 } // namespace inlinens 99 100 // The iterator typedef is a DependentNameType. 101 template <typename T> 102 class __unordered_multimap_iterator {}; 103 // CHECK: ClassTemplateDecl {{.*}} __unordered_multimap_iterator 104 // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_multimap_iterator 105 // CHECK: TemplateArgument type 'int' 106 // CHECK: PointerAttr 107 108 template <typename T> 109 class __unordered_multimap_base { 110 public: 111 using iterator = __unordered_multimap_iterator<T>; 112 }; 113 114 template <typename T> 115 class unordered_multimap { 116 // CHECK: ClassTemplateDecl {{.*}} unordered_multimap 117 // CHECK: OwnerAttr {{.*}} 118 // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_multimap 119 // CHECK: OwnerAttr {{.*}} 120 public: 121 using _Mybase = __unordered_multimap_base<T>; 122 using iterator = typename _Mybase::iterator; 123 }; 124 static_assert(sizeof(unordered_multimap<int>::iterator), ""); // Force instantiation. 125 126 // The canonical declaration of the iterator template is not its definition. 127 template <typename T> 128 class __unordered_multiset_iterator; 129 // CHECK: ClassTemplateDecl {{.*}} __unordered_multiset_iterator 130 // CHECK: PointerAttr 131 // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_multiset_iterator 132 // CHECK: TemplateArgument type 'int' 133 // CHECK: PointerAttr 134 135 template <typename T> 136 class __unordered_multiset_iterator { 137 // CHECK: ClassTemplateDecl {{.*}} prev {{.*}} __unordered_multiset_iterator 138 // CHECK: PointerAttr 139 }; 140 141 template <typename T> 142 class unordered_multiset { 143 // CHECK: ClassTemplateDecl {{.*}} unordered_multiset 144 // CHECK: OwnerAttr {{.*}} 145 // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_multiset 146 // CHECK: OwnerAttr {{.*}} 147 public: 148 using iterator = __unordered_multiset_iterator<T>; 149 }; 150 151 static_assert(sizeof(unordered_multiset<int>::iterator), ""); // Force instantiation. 152 153 // std::list has an implicit gsl::Owner attribute, 154 // but explicit attributes take precedence. 155 template <typename T> 156 class [[gsl::Pointer]] list{}; 157 // CHECK: ClassTemplateDecl {{.*}} list 158 // CHECK: PointerAttr {{.*}} 159 // CHECK: ClassTemplateSpecializationDecl {{.*}} list 160 // CHECK: PointerAttr {{.*}} 161 162 static_assert(sizeof(list<int>), ""); // Force instantiation. 163 164 // Forward declared template (Owner). 165 template < 166 class CharT, 167 class Traits> 168 class basic_regex; 169 // CHECK: ClassTemplateDecl {{.*}} basic_regex 170 // CHECK: OwnerAttr {{.*}} 171 172 // Forward declared template (Pointer). 173 template <class T> 174 class reference_wrapper; 175 // CHECK: ClassTemplateDecl {{.*}} reference_wrapper 176 // CHECK: PointerAttr {{.*}} 177 178 class some_unknown_type; 179 // CHECK: CXXRecordDecl {{.*}} some_unknown_type 180 181 using size_t = unsigned; 182 inline constexpr size_t dynamic_extent = -1; 183 template <typename _Tp, size_t _Extent = dynamic_extent> 184 class span; 185 // CHECK: CXXRecordDecl {{.*}} span 186 // CHECK: PointerAttr {{.*}} 187 188 189 template <typename _Tp> 190 struct span<_Tp, dynamic_extent> {}; 191 // CHECK: ClassTemplatePartialSpecializationDecl {{.*}} span 192 // CHECK: PointerAttr {{.*}} 193 } // namespace std 194 195 namespace user { 196 // If a class is not in the std namespace, we don't infer the attributes. 197 class any { 198 }; 199 } // namespace user 200