diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 23cb47481f3d..e2542edf6ed5 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -88,11 +88,13 @@ void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { template static void addGslOwnerPointerAttributeIfNotExisting(ASTContext &Context, CXXRecordDecl *Record) { - if (Record->hasAttr() || Record->hasAttr()) + CXXRecordDecl *Canonical = Record->getCanonicalDecl(); + if (Canonical->hasAttr() || Canonical->hasAttr()) return; - for (Decl *Redecl : Record->redecls()) - Redecl->addAttr(Attribute::CreateImplicit(Context, /*DerefType=*/nullptr)); + Canonical->addAttr(::new (Context) Attribute(SourceRange{}, Context, + /*DerefType*/ nullptr, + /*Spelling=*/0)); } void Sema::inferGslPointerAttribute(NamedDecl *ND, @@ -187,7 +189,8 @@ void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) { // Handle classes that directly appear in std namespace. if (Record->isInStdNamespace()) { - if (Record->hasAttr() || Record->hasAttr()) + CXXRecordDecl *Canonical = Record->getCanonicalDecl(); + if (Canonical->hasAttr() || Canonical->hasAttr()) return; if (StdOwners.count(Record->getName())) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b694c058a3a3..2a72f7d5c61d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4592,11 +4592,9 @@ static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } return; } - for (Decl *Redecl : D->redecls()) { - Redecl->addAttr(::new (S.Context) - OwnerAttr(AL.getRange(), S.Context, DerefTypeLoc, - AL.getAttributeSpellingListIndex())); - } + D->addAttr(::new (S.Context) + OwnerAttr(AL.getRange(), S.Context, DerefTypeLoc, + AL.getAttributeSpellingListIndex())); } else { if (checkAttrMutualExclusion(S, D, AL)) return; @@ -4611,11 +4609,9 @@ static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } return; } - for (Decl *Redecl : D->redecls()) { - Redecl->addAttr(::new (S.Context) - PointerAttr(AL.getRange(), S.Context, DerefTypeLoc, - AL.getAttributeSpellingListIndex())); - } + D->addAttr(::new (S.Context) + PointerAttr(AL.getRange(), S.Context, DerefTypeLoc, + AL.getAttributeSpellingListIndex())); } } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index ee9963fca779..289a1403cd84 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6561,7 +6561,7 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, template static bool isRecordWithAttr(QualType Type) { if (auto *RD = Type->getAsCXXRecordDecl()) - return RD->hasAttr(); + return RD->getCanonicalDecl()->hasAttr(); return false; } @@ -6672,7 +6672,7 @@ static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call, if (auto *CCE = dyn_cast(Call)) { const auto *Ctor = CCE->getConstructor(); - const CXXRecordDecl *RD = Ctor->getParent(); + const CXXRecordDecl *RD = Ctor->getParent()->getCanonicalDecl(); if (CCE->getNumArgs() > 0 && RD->hasAttr()) VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0]); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 2e76dc1a5843..25d0db803983 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -552,18 +552,6 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } - if (auto *A = dyn_cast(TmplAttr)) { - if (!New->hasAttr()) - New->addAttr(A->clone(Context)); - continue; - } - - if (auto *A = dyn_cast(TmplAttr)) { - if (!New->hasAttr()) - New->addAttr(A->clone(Context)); - continue; - } - assert(!TmplAttr->isPackExpansion()); if (TmplAttr->isLateParsed() && LateAttrs) { // Late parsed attributes must be instantiated and attached after the @@ -723,9 +711,6 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); - if (D->getUnderlyingType()->getAs()) - SemaRef.inferGslPointerAttribute(Typedef); - Typedef->setAccess(D->getAccess()); return Typedef; diff --git a/clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp b/clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp index 352e1e473580..29675c2ac7e9 100644 --- a/clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp +++ b/clang/test/SemaCXX/attr-gsl-owner-pointer-std.cpp @@ -92,59 +92,6 @@ public: 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 diff --git a/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp b/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp index 5b438822ba21..1c3deb3982e8 100644 --- a/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp +++ b/clang/test/SemaCXX/attr-gsl-owner-pointer.cpp @@ -105,20 +105,3 @@ class [[gsl::Owner(int)]] AddTheSameLater{}; class [[gsl::Owner(int)]] AddTheSameLater; // CHECK: CXXRecordDecl {{.*}} prev {{.*}} AddTheSameLater // CHECK: OwnerAttr {{.*}} int - -template -class [[gsl::Owner]] ForwardDeclared; -// CHECK: ClassTemplateDecl {{.*}} ForwardDeclared -// CHECK: OwnerAttr {{.*}} -// CHECK: ClassTemplateSpecializationDecl {{.*}} ForwardDeclared -// CHECK: TemplateArgument type 'int' -// CHECK: OwnerAttr {{.*}} - -template -class [[gsl::Owner]] ForwardDeclared { -// CHECK: ClassTemplateDecl {{.*}} ForwardDeclared -// CHECK: CXXRecordDecl {{.*}} ForwardDeclared definition -// CHECK: OwnerAttr {{.*}} -}; - -static_assert(sizeof(ForwardDeclared), ""); // Force instantiation. diff --git a/clang/unittests/Sema/CMakeLists.txt b/clang/unittests/Sema/CMakeLists.txt index 6832908e7fb1..51e8d6c5b430 100644 --- a/clang/unittests/Sema/CMakeLists.txt +++ b/clang/unittests/Sema/CMakeLists.txt @@ -5,13 +5,11 @@ set(LLVM_LINK_COMPONENTS add_clang_unittest(SemaTests ExternalSemaSourceTest.cpp CodeCompleteTest.cpp - GslOwnerPointerInference.cpp ) clang_target_link_libraries(SemaTests PRIVATE clangAST - clangASTMatchers clangBasic clangFrontend clangParse diff --git a/clang/unittests/Sema/GslOwnerPointerInference.cpp b/clang/unittests/Sema/GslOwnerPointerInference.cpp deleted file mode 100644 index e340ccb4127b..000000000000 --- a/clang/unittests/Sema/GslOwnerPointerInference.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//== 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 [[gsl::Owner]] C; - - template - class [[gsl::Owner]] C {}; - - C c; - )cpp", - classTemplateSpecializationDecl(hasName("C"), hasAttr(clang::attr::Owner)))); -} - -TEST(OwnerPointer, ForwardDeclOnly) { - EXPECT_TRUE(matches( - R"cpp( - template - class [[gsl::Owner]] C; - - template - class C {}; - - C c; - )cpp", - classTemplateSpecializationDecl(hasName("C"), hasAttr(clang::attr::Owner)))); -} - -TEST(OwnerPointer, LateForwardDeclOnly) { - EXPECT_TRUE(matches( - R"cpp( - template - class C; - - template - class C {}; - - template - class [[gsl::Owner]] C; - - C c; - )cpp", - classTemplateSpecializationDecl(hasName("C"), hasAttr(clang::attr::Owner)))); -} - -} // namespace clang