Revert "[LifetimeAnalysis] Support more STL idioms (template forward declaration and DependentNameType)"
This reverts commit r369591, because it causes the formerly-reliable -Wreturn-stack-address warning to start issuing false positives. Testcase provided on the commit thread. llvm-svn: 369677
This commit is contained in:
parent
1a28a06ebe
commit
966eea91ad
|
@ -88,11 +88,13 @@ void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
|
|||
template <typename Attribute>
|
||||
static void addGslOwnerPointerAttributeIfNotExisting(ASTContext &Context,
|
||||
CXXRecordDecl *Record) {
|
||||
if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>())
|
||||
CXXRecordDecl *Canonical = Record->getCanonicalDecl();
|
||||
if (Canonical->hasAttr<OwnerAttr>() || Canonical->hasAttr<PointerAttr>())
|
||||
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<OwnerAttr>() || Record->hasAttr<PointerAttr>())
|
||||
CXXRecordDecl *Canonical = Record->getCanonicalDecl();
|
||||
if (Canonical->hasAttr<OwnerAttr>() || Canonical->hasAttr<PointerAttr>())
|
||||
return;
|
||||
|
||||
if (StdOwners.count(Record->getName()))
|
||||
|
|
|
@ -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<OwnerAttr>(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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6561,7 +6561,7 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
|
|||
|
||||
template <typename T> static bool isRecordWithAttr(QualType Type) {
|
||||
if (auto *RD = Type->getAsCXXRecordDecl())
|
||||
return RD->hasAttr<T>();
|
||||
return RD->getCanonicalDecl()->hasAttr<T>();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6672,7 +6672,7 @@ static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
|
|||
|
||||
if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {
|
||||
const auto *Ctor = CCE->getConstructor();
|
||||
const CXXRecordDecl *RD = Ctor->getParent();
|
||||
const CXXRecordDecl *RD = Ctor->getParent()->getCanonicalDecl();
|
||||
if (CCE->getNumArgs() > 0 && RD->hasAttr<PointerAttr>())
|
||||
VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0]);
|
||||
}
|
||||
|
|
|
@ -552,18 +552,6 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
|||
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
|
||||
|
@ -723,9 +711,6 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
|
|||
|
||||
SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
|
||||
|
||||
if (D->getUnderlyingType()->getAs<DependentNameType>())
|
||||
SemaRef.inferGslPointerAttribute(Typedef);
|
||||
|
||||
Typedef->setAccess(D->getAccess());
|
||||
|
||||
return Typedef;
|
||||
|
|
|
@ -92,59 +92,6 @@ public:
|
|||
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>
|
||||
|
|
|
@ -105,20 +105,3 @@ class [[gsl::Owner(int)]] AddTheSameLater{};
|
|||
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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 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
|
Loading…
Reference in New Issue