mgehre created this revision. mgehre added a reviewer: gribozavr. Herald added a subscriber: Szelethus. Herald added a project: clang.
This fixes inference of gsl::Pointer on std::set::iterator with libstdc++ (the typedef for iterator on the template is a DependentNameType - we can only put the gsl::Pointer attribute on the underlaying record after instantiation) inference of gsl::Pointer on std::vector::iterator with libc++ (the class was forward-declared, we added the gsl::Pointer on the canonical decl (the forward decl), and later when the template was instantiated, there was no attribute on the definition so it was not instantiated). and a duplicate gsl::Pointer on some class with libstdc++ (we first added an attribute to a incomplete instantiation, and then another was copied from the template definition when the instantiation was completed). Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D66179 Files: clang/lib/Sema/SemaAttr.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp
Index: clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp =================================================================== --- clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp +++ clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp @@ -92,6 +92,59 @@ static_assert(sizeof(unordered_map<int>::iterator), ""); // Force instantiation. } // namespace inlinens +// The iterator typedef is a DependentNameType. +template <typename T> +class __unordered_multimap_iterator {}; +// CHECK: ClassTemplateDecl {{.*}} __unordered_multimap_iterator +// CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_multimap_iterator +// CHECK: TemplateArgument type 'int' +// CHECK: PointerAttr + +template <typename T> +class __unordered_multimap_base { +public: + using iterator = __unordered_multimap_iterator<T>; +}; + +template <typename T> +class unordered_multimap { + // CHECK: ClassTemplateDecl {{.*}} unordered_multimap + // CHECK: OwnerAttr {{.*}} + // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_multimap + // CHECK: OwnerAttr {{.*}} +public: + using _Mybase = __unordered_multimap_base<T>; + using iterator = typename _Mybase::iterator; +}; +static_assert(sizeof(unordered_multimap<int>::iterator), ""); // Force instantiation. + +// The canonical declaration of the iterator template is not its definition. +template <typename T> +class __unordered_multiset_iterator; +// CHECK: ClassTemplateDecl {{.*}} __unordered_multiset_iterator +// CHECK: PointerAttr +// CHECK: ClassTemplateSpecializationDecl {{.*}} __unordered_multiset_iterator +// CHECK: TemplateArgument type 'int' +// CHECK: PointerAttr + +template <typename T> +class __unordered_multiset_iterator { + // CHECK: ClassTemplateDecl {{.*}} prev {{.*}} __unordered_multiset_iterator + // CHECK: PointerAttr +}; + +template <typename T> +class unordered_multiset { + // CHECK: ClassTemplateDecl {{.*}} unordered_multiset + // CHECK: OwnerAttr {{.*}} + // CHECK: ClassTemplateSpecializationDecl {{.*}} unordered_multiset + // CHECK: OwnerAttr {{.*}} +public: + using iterator = __unordered_multiset_iterator<T>; +}; + +static_assert(sizeof(unordered_multiset<int>::iterator), ""); // Force instantiation. + // std::list has an implicit gsl::Owner attribute, // but explicit attributes take precedence. template <typename T> Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -552,6 +552,18 @@ continue; } + if (auto *A = dyn_cast<PointerAttr>(TmplAttr)) { + if (!New->hasAttr<PointerAttr>()) + New->addAttr(A->clone(Context)); + continue; + } + + if (auto *A = dyn_cast<OwnerAttr>(TmplAttr)) { + if (!New->hasAttr<OwnerAttr>()) + New->addAttr(A->clone(Context)); + continue; + } + assert(!TmplAttr->isPackExpansion()); if (TmplAttr->isLateParsed() && LateAttrs) { // Late parsed attributes must be instantiated and attached after the @@ -711,6 +723,9 @@ SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); + if (D->getUnderlyingType()->getAs<DependentNameType>()) + SemaRef.inferGslPointerAttribute(Typedef); + Typedef->setAccess(D->getAccess()); return Typedef; Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -88,13 +88,20 @@ template <typename Attribute> static void addGslOwnerPointerAttributeIfNotExisting(ASTContext &Context, CXXRecordDecl *Record) { - CXXRecordDecl *Canonical = Record->getCanonicalDecl(); - if (Canonical->hasAttr<OwnerAttr>() || Canonical->hasAttr<PointerAttr>()) + if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>()) return; - Canonical->addAttr(::new (Context) Attribute(SourceRange{}, Context, - /*DerefType*/ nullptr, - /*Spelling=*/0)); + Record->addAttr(::new (Context) Attribute(SourceRange{}, Context, + /*DerefType*/ nullptr, + /*Spelling=*/0)); + + // Put the attribute on the definition of a class template, so it is used + // during instantiation. + if (auto *Templ = + dyn_cast_or_null<ClassTemplateDecl>(Record->getDescribedTemplate())) { + if (auto *Def = Record->getDefinition()) + addGslOwnerPointerAttributeIfNotExisting<Attribute>(Context, Def); + } } void Sema::inferGslPointerAttribute(NamedDecl *ND, @@ -132,8 +139,8 @@ if (Parent->isInStdNamespace() && Iterators.count(ND->getName()) && Containers.count(Parent->getName())) - addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, - UnderlyingRecord); + addGslOwnerPointerAttributeIfNotExisting<PointerAttr>( + Context, UnderlyingRecord->getCanonicalDecl()); } void Sema::inferGslPointerAttribute(TypedefNameDecl *TD) { @@ -194,9 +201,9 @@ return; if (StdOwners.count(Record->getName())) - addGslOwnerPointerAttributeIfNotExisting<OwnerAttr>(Context, Record); + addGslOwnerPointerAttributeIfNotExisting<OwnerAttr>(Context, Canonical); else if (StdPointers.count(Record->getName())) - addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, Record); + addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, Canonical); return; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits