mgehre updated this revision to Diff 216247. mgehre marked 6 inline comments as done. mgehre added a comment. Herald added a subscriber: mgorny.
- Put OwnerAttr/PointerAttr on all redeclarations - clang/lib/Sema/SemaAttr.cpp: Use Attribute::CreateImplicit as requested in review Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D66179/new/ https://reviews.llvm.org/D66179 Files: clang/lib/Sema/SemaAttr.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaInit.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp clang/test/SemaCXX/attr-gsl-owner-pointer.cpp clang/unittests/Sema/CMakeLists.txt clang/unittests/Sema/GslOwnerPointerInference.cpp
Index: clang/unittests/Sema/GslOwnerPointerInference.cpp =================================================================== --- /dev/null +++ clang/unittests/Sema/GslOwnerPointerInference.cpp @@ -0,0 +1,61 @@ +//== unittests/Sema/GslOwnerPointerInference.cpp - gsl::Owner/Pointer ========// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "../ASTMatchers/ASTMatchersTest.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "gtest/gtest.h" + +namespace clang { +using namespace ast_matchers; + +TEST(OwnerPointer, BothHaveAttributes) { + EXPECT_TRUE(matches( + R"cpp( + template<class T> + class [[gsl::Owner]] C; + + template<class T> + class [[gsl::Owner]] C {}; + + C<int> c; + )cpp", + classTemplateSpecializationDecl(hasName("C"), hasAttr(clang::attr::Owner)))); +} + +TEST(OwnerPointer, ForwardDeclOnly) { + EXPECT_TRUE(matches( + R"cpp( + template<class T> + class [[gsl::Owner]] C; + + template<class T> + class C {}; + + C<int> c; + )cpp", + classTemplateSpecializationDecl(hasName("C"), hasAttr(clang::attr::Owner)))); +} + +TEST(OwnerPointer, LateForwardDeclOnly) { + EXPECT_TRUE(matches( + R"cpp( + template<class T> + class C; + + template<class T> + class C {}; + + template<class T> + class [[gsl::Owner]] C; + + C<int> c; + )cpp", + classTemplateSpecializationDecl(hasName("C"), hasAttr(clang::attr::Owner)))); +} + +} // namespace clang Index: clang/unittests/Sema/CMakeLists.txt =================================================================== --- clang/unittests/Sema/CMakeLists.txt +++ clang/unittests/Sema/CMakeLists.txt @@ -5,11 +5,13 @@ add_clang_unittest(SemaTests ExternalSemaSourceTest.cpp CodeCompleteTest.cpp + GslOwnerPointerInference.cpp ) clang_target_link_libraries(SemaTests PRIVATE clangAST + clangASTMatchers clangBasic clangFrontend clangParse Index: clang/test/SemaCXX/attr-gsl-owner-pointer.cpp =================================================================== --- clang/test/SemaCXX/attr-gsl-owner-pointer.cpp +++ clang/test/SemaCXX/attr-gsl-owner-pointer.cpp @@ -105,3 +105,20 @@ class [[gsl::Owner(int)]] AddTheSameLater; // CHECK: CXXRecordDecl {{.*}} prev {{.*}} AddTheSameLater // CHECK: OwnerAttr {{.*}} int + +template <class T> +class [[gsl::Owner]] ForwardDeclared; +// CHECK: ClassTemplateDecl {{.*}} ForwardDeclared +// CHECK: OwnerAttr {{.*}} +// CHECK: ClassTemplateSpecializationDecl {{.*}} ForwardDeclared +// CHECK: TemplateArgument type 'int' +// CHECK: OwnerAttr {{.*}} + +template <class T> +class [[gsl::Owner]] ForwardDeclared { +// CHECK: ClassTemplateDecl {{.*}} ForwardDeclared +// CHECK: CXXRecordDecl {{.*}} ForwardDeclared definition +// CHECK: OwnerAttr {{.*}} +}; + +static_assert(sizeof(ForwardDeclared<int>), ""); // Force instantiation. 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/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -6560,7 +6560,7 @@ template <typename T> static bool isRecordWithAttr(QualType Type) { if (auto *RD = Type->getAsCXXRecordDecl()) - return RD->getCanonicalDecl()->hasAttr<T>(); + return RD->hasAttr<T>(); return false; } Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -4592,9 +4592,11 @@ } return; } - D->addAttr(::new (S.Context) - OwnerAttr(AL.getRange(), S.Context, DerefTypeLoc, - AL.getAttributeSpellingListIndex())); + for (Decl *Redecl : D->redecls()) { + Redecl->addAttr(::new (S.Context) + OwnerAttr(AL.getRange(), S.Context, DerefTypeLoc, + AL.getAttributeSpellingListIndex())); + } } else { if (checkAttrMutualExclusion<OwnerAttr>(S, D, AL)) return; @@ -4609,9 +4611,11 @@ } return; } - D->addAttr(::new (S.Context) - PointerAttr(AL.getRange(), S.Context, DerefTypeLoc, - AL.getAttributeSpellingListIndex())); + for (Decl *Redecl : D->redecls()) { + Redecl->addAttr(::new (S.Context) + PointerAttr(AL.getRange(), S.Context, DerefTypeLoc, + AL.getAttributeSpellingListIndex())); + } } } Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -88,13 +88,11 @@ 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)); + for (Decl *Redecl : Record->redecls()) + Redecl->addAttr(Attribute::CreateImplicit(Context, /*DerefType=*/nullptr)); } void Sema::inferGslPointerAttribute(NamedDecl *ND, @@ -189,8 +187,7 @@ // Handle classes that directly appear in std namespace. if (Record->isInStdNamespace()) { - CXXRecordDecl *Canonical = Record->getCanonicalDecl(); - if (Canonical->hasAttr<OwnerAttr>() || Canonical->hasAttr<PointerAttr>()) + if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>()) return; if (StdOwners.count(Record->getName()))
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits