// RUN: %clang_cc1 -ast-dump %s | \ // RUN: FileCheck --implicit-check-not OwnerAttr --implicit-check-not PointerAttr %s // Test attribute inference for types in the standard library. namespace std { // Attributes are inferred for a (complete) class. class any { // CHECK: CXXRecordDecl {{.*}} any // CHECK: OwnerAttr {{.*}} }; // Attributes are inferred for instantiations of a complete template. template class vector { public: class iterator {}; // CHECK: ClassTemplateDecl {{.*}} vector // CHECK: OwnerAttr {{.*}} // CHECK: CXXRecordDecl {{.*}} iterator // CHECK: PointerAttr {{.*}} // CHECK: ClassTemplateSpecializationDecl {{.*}} vector // CHECK: TemplateArgument type 'int' // CHECK: OwnerAttr // CHECK: CXXRecordDecl {{.*}} iterator // CHECK: PointerAttr {{.*}} }; static_assert(sizeof(vector), ""); // Force instantiation. static_assert(sizeof(vector::iterator), ""); // Force instantiation. // If std::container::iterator is a using declaration, attributes are inferred // for the underlying class. template class __set_iterator {}; // CHECK: ClassTemplateDecl {{.*}} __set_iterator // CHECK: PointerAttr // CHECK: ClassTemplateSpecializationDecl {{.*}} __set_iterator // CHECK: TemplateArgument type 'int' // CHECK: PointerAttr template class set { // CHECK: ClassTemplateDecl {{.*}} set // CHECK: OwnerAttr {{.*}} // CHECK: ClassTemplateSpecializationDecl {{.*}} set // CHECK: OwnerAttr {{.*}} public: using iterator = __set_iterator; }; static_assert(sizeof(set::iterator), ""); // Force instantiation. // If std::container::iterator is a typedef, attributes are inferred for the // underlying class. template class __map_iterator {}; // CHECK: ClassTemplateDecl {{.*}} __map_iterator // CHECK: PointerAttr // CHECK: ClassTemplateSpecializationDecl {{.*}} __map_iterator // CHECK: TemplateArgument type 'int' // CHECK: PointerAttr template class map { // CHECK: ClassTemplateDecl {{.*}} map // CHECK: OwnerAttr {{.*}} // CHECK: ClassTemplateSpecializationDecl {{.*}} map // CHECK: OwnerAttr {{.*}} public: typedef __map_iterator iterator; }; static_assert(sizeof(map::iterator), ""); // Force instantiation. // Inline namespaces are ignored when checking if // the class lives in the std namespace. inline namespace inlinens { template class __unordered_map_iterator {}; // CHECK: ClassTemplateDecl {{.*}} __unordered_map_iterator // CHECK: PointerAttr // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_map_iterator // CHECK: TemplateArgument type 'int' // CHECK: PointerAttr template class unordered_map { // CHECK: ClassTemplateDecl {{.*}} unordered_map // CHECK: OwnerAttr {{.*}} // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_map // CHECK: OwnerAttr {{.*}} public: typedef __unordered_map_iterator iterator; }; static_assert(sizeof(unordered_map::iterator), ""); // Force instantiation. } // namespace inlinens // The iterator typedef is a DependentNameType. template class __unordered_multimap_iterator {}; // CHECK: ClassTemplateDecl {{.*}} __unordered_multimap_iterator // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_multimap_iterator // CHECK: TemplateArgument type 'int' // CHECK: PointerAttr template class __unordered_multimap_base { public: using iterator = __unordered_multimap_iterator; }; template class unordered_multimap { // CHECK: ClassTemplateDecl {{.*}} unordered_multimap // CHECK: OwnerAttr {{.*}} // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_multimap // CHECK: OwnerAttr {{.*}} public: using _Mybase = __unordered_multimap_base; using iterator = typename _Mybase::iterator; }; static_assert(sizeof(unordered_multimap::iterator), ""); // Force instantiation. // The canonical declaration of the iterator template is not its definition. template class __unordered_multiset_iterator; // CHECK: ClassTemplateDecl {{.*}} __unordered_multiset_iterator // CHECK: PointerAttr // CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_multiset_iterator // CHECK: TemplateArgument type 'int' // CHECK: PointerAttr template class __unordered_multiset_iterator { // CHECK: ClassTemplateDecl {{.*}} prev {{.*}} __unordered_multiset_iterator // CHECK: PointerAttr }; template class unordered_multiset { // CHECK: ClassTemplateDecl {{.*}} unordered_multiset // CHECK: OwnerAttr {{.*}} // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_multiset // CHECK: OwnerAttr {{.*}} public: using iterator = __unordered_multiset_iterator; }; static_assert(sizeof(unordered_multiset::iterator), ""); // Force instantiation. // std::list has an implicit gsl::Owner attribute, // but explicit attributes take precedence. template class [[gsl::Pointer]] list{}; // CHECK: ClassTemplateDecl {{.*}} list // CHECK: PointerAttr {{.*}} // CHECK: ClassTemplateSpecializationDecl {{.*}} list // CHECK: PointerAttr {{.*}} static_assert(sizeof(list), ""); // Force instantiation. // Forward declared template (Owner). template < class CharT, class Traits> class basic_regex; // CHECK: ClassTemplateDecl {{.*}} basic_regex // CHECK: OwnerAttr {{.*}} // Forward declared template (Pointer). template class reference_wrapper; // CHECK: ClassTemplateDecl {{.*}} reference_wrapper // CHECK: PointerAttr {{.*}} class some_unknown_type; // CHECK: CXXRecordDecl {{.*}} some_unknown_type } // namespace std namespace user { // If a class is not in the std namespace, we don't infer the attributes. class any { }; } // namespace user