diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4164,7 +4164,7 @@ When annotating a class ``O`` with ``[[gsl::Owner(T)]]``, then each function that returns cv-qualified ``T&`` or ``T*`` is assumed to return a pointer/reference to the data owned by ``O``. The owned data is assumed to end -its lifetime once the owning object's lifetime ends. The argument is ``T`` is +its lifetime once the owning object's lifetime ends. The argument ``T`` is optional. This attribute may be used by analysis tools but will not have effect on code @@ -4177,7 +4177,7 @@ let Content = [{ When annotating a class with ``[[gsl::Pointer(T)]]``, it assumed to be a non-owning type whose objects can point to ``T`` type objects or dangle. -The argument is ``T`` is optional. +The argument ``T`` is optional. This attribute may be used by analysis tools but will not have effect on code generation. diff --git a/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp b/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp --- a/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp +++ b/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp @@ -83,14 +83,14 @@ static_assert(__is_gsl_pointer(int &), ""); static_assert(__is_gsl_pointer(int *), ""); -// Test builtin annotation for std types. +// Test builtin attributes for std types. namespace std { -// Complete class +// Attributes are added to a (complete) class. class any { }; static_assert(__is_gsl_owner(any), ""); -// Complete template +// Attributes are added to a instantiatons of a complete template. template class vector { public: @@ -99,45 +99,60 @@ static_assert(__is_gsl_owner(vector), ""); static_assert(__is_gsl_pointer(vector::iterator), ""); +// If std::container::iterator is a using declaration, Attributes are added to +// the underlying class template -class set_iterator {}; +class __set_iterator {}; template class set { public: - using iterator = set_iterator; + using iterator = __set_iterator; }; static_assert(__is_gsl_pointer(set::iterator), ""); +// If std::container::iterator is a typedef, Attributes are added to the +// underlying class. Inline namespaces are ignored when checking if +// the class lives in the std namespace. +inline namespace inlinens { template -class map_iterator {}; +class __map_iterator {}; template class map { public: - typedef map_iterator iterator; + typedef __map_iterator iterator; }; +} // namespace inlinens static_assert(__is_gsl_pointer(map::iterator), ""); -// list has an implicit gsl::Owner attribute, +// std::list has an implicit gsl::Owner attribute, // but explicit attributes take precedence. template class [[gsl::Pointer]] list{}; static_assert(!__is_gsl_owner(list), ""); static_assert(__is_gsl_pointer(list), ""); -// Forward declared template +// Forward declared template (Owner) template < class CharT, class Traits> class basic_regex; static_assert(__is_gsl_owner(basic_regex), ""); +// Forward declared template (Pointer) template class reference_wrapper; static_assert(__is_gsl_pointer(reference_wrapper), ""); -class thread; -static_assert(!__is_gsl_pointer(thread), ""); -static_assert(!__is_gsl_owner(thread), ""); +class some_unknown_type; +static_assert(!__is_gsl_pointer(some_unknown_type), ""); +static_assert(!__is_gsl_owner(some_unknown_type), ""); } // namespace std + +namespace user { +// If a class is not in the std namespace, we don't add implicit attributes. +class any { +}; +static_assert(!__is_gsl_owner(any), ""); +} // namespace user